-- Copyright (C) 2026 Intel Corporation -- SPDX-License-Identifier: PostgreSQL -- Table shape, including both triggers' declared firing conditions \d vamana_databases Table "public.vamana_databases" Column | Type | Collation | Nullable | Default -------------------------+---------+-----------+----------+--------- datname | name | | not null | enabled | boolean | | not null | true restart_generation | bigint | | not null | 0 graph_memory_mb | integer | | | search_num_threads | integer | | | residency_memory | integer | | | search_work_mem | integer | | | search_threads_reserved | integer | | | maintenance_num_threads | integer | | | Indexes: "vamana_databases_pkey" PRIMARY KEY, btree (datname) Check constraints: "vamana_databases_graph_memory_mb_check" CHECK (graph_memory_mb > 0) "vamana_databases_maintenance_num_threads_check" CHECK (maintenance_num_threads >= 0 AND maintenance_num_threads <= 1024) "vamana_databases_residency_memory_check" CHECK (residency_memory > 0) "vamana_databases_search_num_threads_check" CHECK (search_num_threads >= 1 AND search_num_threads <= 1024) "vamana_databases_search_threads_reserved_check" CHECK (search_threads_reserved >= 0 AND search_threads_reserved <= 1024) "vamana_databases_search_work_mem_check" CHECK (search_work_mem > 0) Triggers: vamana_databases_changed AFTER INSERT OR DELETE OR UPDATE ON vamana_databases FOR EACH STATEMENT EXECUTE FUNCTION vamana_databases_notify() vamana_databases_check_search_work_mem_ceiling_ins AFTER INSERT ON vamana_databases REFERENCING NEW TABLE AS new_rows FOR EACH STATEMENT EXECUTE FUNCTION vamana_databases_check_search_work_mem_ceiling() vamana_databases_check_search_work_mem_ceiling_upd AFTER UPDATE ON vamana_databases REFERENCING NEW TABLE AS new_rows FOR EACH STATEMENT EXECUTE FUNCTION vamana_databases_check_search_work_mem_ceiling() vamana_databases_queue_reservation AFTER INSERT OR UPDATE ON vamana_databases FOR EACH ROW EXECUTE FUNCTION vamana_databases_queue_reservation() vamana_databases_reject_delete_with_live_indexes BEFORE DELETE ON vamana_databases FOR EACH ROW EXECUTE FUNCTION vamana_databases_reject_delete_with_live_indexes() vamana_databases_reject_truncate_with_live_indexes BEFORE TRUNCATE ON vamana_databases FOR EACH STATEMENT EXECUTE FUNCTION vamana_databases_reject_truncate_with_live_indexes() \d svs_index_residency Table "public.svs_index_residency" Column | Type | Collation | Nullable | Default ----------------+--------+-----------+----------+--------- index_relid | oid | | not null | db_oid | oid | | not null | resident_bytes | bigint | | not null | Indexes: "svs_index_residency_pkey" PRIMARY KEY, btree (index_relid) CREATE DATABASE vamana_databases_test_bypass_a; CREATE DATABASE vamana_databases_test_bypass_b; \set VERBOSITY terse INSERT INTO vamana_databases (datname, search_work_mem) VALUES ('vamana_databases_test_bypass_a', 70000), ('vamana_databases_test_bypass_b', 70000); ERROR: search_work_mem total would exceed svs.max_search_work_mem \set VERBOSITY default SELECT count(*) = 0 AS multi_row_over_ceiling_fully_rejected FROM vamana_databases WHERE datname IN ('vamana_databases_test_bypass_a', 'vamana_databases_test_bypass_b'); multi_row_over_ceiling_fully_rejected --------------------------------------- t (1 row) DROP DATABASE vamana_databases_test_bypass_a; DROP DATABASE vamana_databases_test_bypass_b; -- The row-level trigger resolves datname against pg_database, so every row -- here must name a database that actually exists. CREATE DATABASE vamana_databases_test_dbc; CREATE DATABASE vamana_databases_test_dbd; CREATE DATABASE vamana_databases_test_dbe; -- A nonexistent database is rejected outright, before any row is queued. INSERT INTO vamana_databases (datname) VALUES ('vamana_databases_test_missing'); ERROR: database "vamana_databases_test_missing" does not exist -- INSERT/UPDATE/DELETE succeed; the row-level trigger is declared AFTER -- INSERT OR UPDATE only, so DELETE below cannot invoke it. INSERT INTO vamana_databases (datname) VALUES ('template1'), ('postgres'), ('vamana_databases_test_dbc'); -- All three rows have residency_memory NULL, so each resolves independently -- against svs.default_residency_memory: not a shared allowance one -- database's admission consumes for the others. -- -- search_work_mem is NULL on all three too, resolving against -- svs.default_search_work_mem -- a different GUC from the ceiling -- (svs.max_search_work_mem). SELECT count(DISTINCT residency_memory_limit) = 1 AS all_three_resolve_to_the_same_default, count(DISTINCT search_work_mem_limit) = 1 AS all_three_resolve_search_work_mem_the_same, count(*) = 3 AS all_three_admitted FROM pg_stat_vamana_worker w JOIN pg_database d ON d.oid = w.db_oid WHERE d.datname IN ('template1', 'postgres', 'vamana_databases_test_dbc'); all_three_resolve_to_the_same_default | all_three_resolve_search_work_mem_the_same | all_three_admitted ---------------------------------------+--------------------------------------------+-------------------- t | t | t (1 row) -- vamana_databases_test_dbc was CREATE DATABASE'd fresh at the top of this -- file and nothing else in the suite can have touched it, so unlike -- contrib_regression (the shared database every other regression file also -- builds real indexes in) it is safe to assert the exact value here rather -- than just NULL-vs-not: newly admitted, nothing loaded or built yet, so -- committed/build/drift are all exactly zero, not merely non-NULL. SELECT residency_bytes_committed = 0 AS committed_is_zero, build_bytes_committed = 0 AS build_is_zero, residency_drift = 0 AS drift_is_zero FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = 'vamana_databases_test_dbc'); committed_is_zero | build_is_zero | drift_is_zero -------------------+---------------+--------------- t | t | t (1 row) UPDATE vamana_databases SET enabled = false WHERE datname IN ('template1', 'postgres', 'vamana_databases_test_dbc'); DELETE FROM vamana_databases WHERE datname = 'template1'; -- Placeholder columns accept NULL and non-NULL values INSERT INTO vamana_databases (datname) VALUES ('vamana_databases_test_dbd'); INSERT INTO vamana_databases (datname, graph_memory_mb, residency_memory, search_work_mem, search_num_threads) VALUES ('vamana_databases_test_dbe', 512, 4096, 2048, 8); -- Scoped to the rows this test created: other regression files may have -- already self-enrolled their own database (e.g. contrib_regression) by the -- time this file runs, and this assertion must not depend on run order. SELECT datname, graph_memory_mb, residency_memory, search_work_mem, search_num_threads FROM vamana_databases WHERE datname IN ('postgres', 'vamana_databases_test_dbc', 'vamana_databases_test_dbd', 'vamana_databases_test_dbe') ORDER BY datname; datname | graph_memory_mb | residency_memory | search_work_mem | search_num_threads ---------------------------+-----------------+------------------+-----------------+-------------------- postgres | | | | vamana_databases_test_dbc | | | | vamana_databases_test_dbd | | | | vamana_databases_test_dbe | 512 | 4096 | 2048 | 8 (4 rows) -- residency_memory and search_work_mem each reject zero and negative values, -- symmetric with every other placeholder column's CHECK (> 0). INSERT INTO vamana_databases (datname, residency_memory) VALUES ('vamana_databases_test_dbd', 0); ERROR: new row for relation "vamana_databases" violates check constraint "vamana_databases_residency_memory_check" DETAIL: Failing row contains (vamana_databases_test_dbd, t, 0, null, null, 0, null, null, null). INSERT INTO vamana_databases (datname, residency_memory) VALUES ('vamana_databases_test_dbd', -1); ERROR: new row for relation "vamana_databases" violates check constraint "vamana_databases_residency_memory_check" DETAIL: Failing row contains (vamana_databases_test_dbd, t, 0, null, null, -1, null, null, null). INSERT INTO vamana_databases (datname, search_work_mem) VALUES ('vamana_databases_test_dbd', 0); ERROR: new row for relation "vamana_databases" violates check constraint "vamana_databases_search_work_mem_check" DETAIL: Failing row contains (vamana_databases_test_dbd, t, 0, null, null, null, 0, null, null). INSERT INTO vamana_databases (datname, search_work_mem) VALUES ('vamana_databases_test_dbd', -1); ERROR: new row for relation "vamana_databases" violates check constraint "vamana_databases_search_work_mem_check" DETAIL: Failing row contains (vamana_databases_test_dbd, t, 0, null, null, null, -1, null, null). -- A residency_memory override that alone exceeds svs.max_residency_memory is -- rejected in the enrolling transaction itself, not at some later load: the -- INSERT never commits, so the row never exists to load against. 2 TB is -- larger than any sane cluster-wide ceiling. template1 rather than dbd: dbd -- already has a row (above), and this must be a fresh enrollment. -- -- The error's DETAIL line names the live global committed sum, which varies -- with the rest of this regression run; terse verbosity drops it, leaving -- only the primary message. \set VERBOSITY terse INSERT INTO vamana_databases (datname, residency_memory) VALUES ('template1', 2 * 1024 * 1024); ERROR: admitting database 1 at 2199023255552 bytes would exceed svs.max_residency_memory \set VERBOSITY default SELECT count(*) = 0 AS oversized_override_never_committed FROM vamana_databases WHERE datname = 'template1'; oversized_override_never_committed ------------------------------------ t (1 row) -- Same shape, for search_work_mem against svs.max_search_work_mem: the -- catalog-time sum check rejects a single row that alone exceeds the -- ceiling, even though it lives in a separate trigger from the residency -- check and reads only this table, not shmem. \set VERBOSITY terse INSERT INTO vamana_databases (datname, search_work_mem) VALUES ('template1', 2 * 1024 * 1024); ERROR: search_work_mem total would exceed svs.max_search_work_mem \set VERBOSITY default SELECT count(*) = 0 AS oversized_search_work_mem_never_committed FROM vamana_databases WHERE datname = 'template1'; oversized_search_work_mem_never_committed ------------------------------------------- t (1 row) -- total_memory_mb no longer exists: the residency/build axis split -- dissolved the combined cap. SELECT total_memory_mb FROM vamana_databases LIMIT 0; ERROR: column "total_memory_mb" does not exist LINE 1: SELECT total_memory_mb FROM vamana_databases LIMIT 0; ^ -- INSERT/UPDATE/DELETE/TRUNCATE are all revoked from PUBLIC; the table owner -- retains them CREATE ROLE vamana_databases_test_nonowner NOLOGIN; SET ROLE vamana_databases_test_nonowner; INSERT INTO vamana_databases (datname) VALUES ('postgres'); ERROR: permission denied for table vamana_databases UPDATE vamana_databases SET enabled = false WHERE datname = 'postgres'; ERROR: permission denied for table vamana_databases DELETE FROM vamana_databases WHERE datname = 'postgres'; ERROR: permission denied for table vamana_databases TRUNCATE vamana_databases; ERROR: permission denied for table vamana_databases RESET ROLE; DROP ROLE vamana_databases_test_nonowner; -- Owning this table is superuser-equivalent; the comment must say so SELECT obj_description('vamana_databases'::regclass, 'pg_class') LIKE '%superuser-equivalent%' AS owner_warning_present; owner_warning_present ----------------------- t (1 row) -- Unlike residency_memory, search_work_mem has no decrease-validation -- trigger at all: nothing about this axis is durable or crash-sensitive, so -- a lower value has nothing to make unsafe. UPDATE vamana_databases SET search_work_mem = 1 WHERE datname = 'vamana_databases_test_dbe'; SELECT search_work_mem FROM vamana_databases WHERE datname = 'vamana_databases_test_dbe'; search_work_mem ----------------- 1 (1 row) TRUNCATE vamana_databases; SELECT count(*) FROM vamana_databases; count ------- 0 (1 row) DROP DATABASE vamana_databases_test_dbc; DROP DATABASE vamana_databases_test_dbd; DROP DATABASE vamana_databases_test_dbe; -- Enabling a database from a savepoint that is released into its parent, -- then discarded by rolling back that parent, must reserve no worker slot. -- The reservation happens at PRE_COMMIT of the whole transaction, so a -- leaked entry would show up immediately, before COMMIT returns. CREATE DATABASE vamana_databases_test_leak; BEGIN; SAVEPOINT outer_sp; SAVEPOINT inner_sp; INSERT INTO vamana_databases (datname, enabled) VALUES ('vamana_databases_test_leak', true); RELEASE SAVEPOINT inner_sp; ROLLBACK TO SAVEPOINT outer_sp; COMMIT; SELECT count(*) FROM vamana_databases WHERE datname = 'vamana_databases_test_leak'; count ------- 0 (1 row) SELECT count(*) FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = 'vamana_databases_test_leak'); count ------- 0 (1 row) DROP DATABASE vamana_databases_test_leak; -- Enable this database for the remaining regression files, which share this -- one contrib_regression database and build vamana indexes. The launcher -- reserves the slot at COMMIT and spawns the worker; the first search then -- waits for it via VamanaWorkerWaitUntilAvailable. INSERT INTO vamana_databases (datname, enabled) VALUES ('contrib_regression', true); -- New memory-accounting stats columns: shape, zero-vs-NULL, and visibility. -- The enrolling INSERT above already admitted this database synchronously, -- in the same transaction, so residency_bytes_committed/build_bytes_committed -- read 0, not NULL: "admitted at zero" and "never admitted" are different -- states. (The exact-zero case, including residency_drift, is proven above -- against vamana_databases_test_dbc; contrib_regression is shared with -- every other regression file, so its drift can be nonzero here -- a -- durable row not yet reconciled by a fresh reload, not a bug.) SELECT residency_bytes_committed = 0 AS committed_is_zero, build_bytes_committed = 0 AS build_is_zero, residency_drift IS NOT NULL AS drift_is_not_null, search_scratch_bytes_in_flight FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = current_database()); committed_is_zero | build_is_zero | drift_is_not_null | search_scratch_bytes_in_flight -------------------+---------------+-------------------+-------------------------------- t | t | t | 0 (1 row) -- The slot-grain column exists and reads NULL until something computes it. SELECT DISTINCT search_scratch_bytes_per_query IS NULL AS unset_before_any_search FROM pg_stat_vamana_worker_slot WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = current_database()); unset_before_any_search ------------------------- t (1 row) -- An unprivileged role reads these columns for its own row only, the same -- visibility rule as every other pg_stat_vamana_worker column. Enabling a -- second database gives a real foreign row to check the unprivileged role -- cannot see, not just a NULL one indistinguishable from "nothing admitted". -- -- postgres's earlier worker slot outlives the TRUNCATE that emptied the -- table (it's released only on the launcher's own async reconcile), so wait -- for it to clear before enrolling again, or the row found below could be -- that stale slot rather than this fresh enrollment. DO $$ BEGIN FOR i IN 1 .. 300 LOOP PERFORM 1 FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = 'postgres'); EXIT WHEN NOT FOUND; PERFORM pg_sleep(0.1); END LOOP; END $$; INSERT INTO vamana_databases (datname, enabled) VALUES ('postgres', true); DO $$ BEGIN FOR i IN 1 .. 300 LOOP PERFORM 1 FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = 'postgres'); EXIT WHEN FOUND; PERFORM pg_sleep(0.1); END LOOP; END $$; -- Confirm the foreign row actually exists as superuser first, so the -- unprivileged role's zero-row result below proves visibility is denied -- rather than proving the row never showed up. SELECT count(*) = 1 AS foreign_row_exists_for_superuser FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = 'postgres'); foreign_row_exists_for_superuser ---------------------------------- t (1 row) -- residency_drift as a boolean, not a raw value: contrib_regression's drift -- can be nonzero depending on what the rest of the suite already built here. CREATE ROLE vamana_databases_test_stats_reader NOLOGIN; SET ROLE vamana_databases_test_stats_reader; SELECT residency_bytes_committed, build_bytes_committed, residency_drift IS NOT NULL AS drift_is_not_null, search_scratch_bytes_in_flight FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = current_database()); residency_bytes_committed | build_bytes_committed | drift_is_not_null | search_scratch_bytes_in_flight ---------------------------+-----------------------+-------------------+-------------------------------- 0 | 0 | t | 0 (1 row) SELECT count(*) = 0 AS foreign_row_not_visible FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = 'postgres'); foreign_row_not_visible ------------------------- t (1 row) RESET ROLE; DROP ROLE vamana_databases_test_stats_reader; UPDATE vamana_databases SET enabled = false WHERE datname = 'postgres'; -- Live-index counter is commit-accurate. The BEFORE DELETE guard reads -- indexCount as a hard gate, so it must equal committed catalog truth and -- must not reflect a rolled-back CREATE/DROP INDEX. pg_stat_vamana_worker is -- cross-database, so each query filters to this database's slot; index_count is -- uniform across a database's slots, so SELECT DISTINCT then yields one row. CREATE TABLE vamana_counter_t (id serial PRIMARY KEY, val vector(3)); INSERT INTO vamana_counter_t (val) VALUES ('[0,0,0]'), ('[1,1,1]'); SET client_min_messages = error; -- Counter tracks a committed CREATE then DROP. CREATE INDEX vamana_counter_i ON vamana_counter_t USING vamana (val vector_l2_ops); SELECT DISTINCT index_count FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = current_database()); index_count ------------- 1 (1 row) DROP INDEX vamana_counter_i; SELECT DISTINCT index_count FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = current_database()); index_count ------------- 0 (1 row) -- Aborted DROP does not under-count: the index is back, the count still reflects it. CREATE INDEX vamana_counter_i ON vamana_counter_t USING vamana (val vector_l2_ops); BEGIN; DROP INDEX vamana_counter_i; ROLLBACK; SELECT DISTINCT index_count FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = current_database()); index_count ------------- 1 (1 row) -- Aborted CREATE does not over-count. BEGIN; CREATE INDEX vamana_counter_i2 ON vamana_counter_t USING vamana (val vector_l2_ops); ROLLBACK; SELECT DISTINCT index_count FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = current_database()); index_count ------------- 1 (1 row) -- ROLLBACK TO SAVEPOINT discards only that subtransaction's delta. BEGIN; SAVEPOINT sp; DROP INDEX vamana_counter_i; ROLLBACK TO SAVEPOINT sp; COMMIT; SELECT DISTINCT index_count FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = current_database()); index_count ------------- 1 (1 row) -- A released savepoint's delta commits exactly once. BEGIN; SAVEPOINT sp; DROP INDEX vamana_counter_i; RELEASE SAVEPOINT sp; COMMIT; SELECT DISTINCT index_count FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = current_database()); index_count ------------- 0 (1 row) -- A savepoint released into its parent, then discarded by a rollback to an -- earlier ancestor, must not commit its delta. Nothing new exists after -- COMMIT, so the count must stay at 0. BEGIN; SAVEPOINT outer_sp; SAVEPOINT inner_sp; CREATE INDEX vamana_counter_nested ON vamana_counter_t USING vamana (val vector_l2_ops); RELEASE SAVEPOINT inner_sp; ROLLBACK TO SAVEPOINT outer_sp; COMMIT; SELECT DISTINCT index_count FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = current_database()); index_count ------------- 0 (1 row) -- Counter moves only on CREATE/DROP, never on a bare rebuild. REINDEX and -- TRUNCATE both re-run the build with no create or drop, and REINDEX -- CONCURRENTLY builds a transient index then drops the old one; none may shift -- the count. It must equal committed catalog truth for the BEFORE DELETE guard. CREATE INDEX vamana_counter_i ON vamana_counter_t USING vamana (val vector_l2_ops); REINDEX INDEX vamana_counter_i; TRUNCATE vamana_counter_t; REINDEX INDEX CONCURRENTLY vamana_counter_i; SELECT DISTINCT index_count FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = current_database()); index_count ------------- 1 (1 row) DROP INDEX vamana_counter_i; SELECT DISTINCT index_count FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = current_database()); index_count ------------- 0 (1 row) RESET client_min_messages; DROP TABLE vamana_counter_t; -- svs_teardown_database() drops every vamana index the caller owns, reporting -- one row per index. A count of live vamana indexes in this database, so the -- teardown cases can assert against "nothing left" without ordering assumptions. CREATE VIEW vamana_live_indexes AS SELECT count(*) AS n FROM pg_class c JOIN pg_am a ON a.oid = c.relam WHERE a.amname = 'vamana' AND c.relkind = 'i'; CREATE TABLE vamana_td_a (id int, val vector(3)); CREATE TABLE vamana_td_b (id int, val vector(3)); INSERT INTO vamana_td_a VALUES (1, '[1,1,1]'); INSERT INTO vamana_td_b VALUES (1, '[1,1,1]'); SET client_min_messages = error; CREATE INDEX vamana_td_ia ON vamana_td_a USING vamana (val vector_l2_ops); CREATE INDEX vamana_td_ib ON vamana_td_b USING vamana (val vector_l2_ops); RESET client_min_messages; -- All indexes owned by the caller: each dropped, no reason, nothing left. SELECT index_name, dropped, reason FROM svs_teardown_database() ORDER BY index_name; index_name | dropped | reason ---------------------+---------+-------- public.vamana_td_ia | t | public.vamana_td_ib | t | (2 rows) SELECT n FROM vamana_live_indexes; n --- 0 (1 row) -- Mixed ownership: the caller owns only some indexes. Owned indexes drop; -- unowned ones report dropped=false with the ownership error, and the call -- continues rather than aborting on the first failure — which also proves the -- function is not SECURITY DEFINER (drops run with the caller's privileges). -- The caller owns one of the two indexes, so a caught error and a successful -- drop both occur in one call: the surviving-unowned + dropped-owned result -- proves the loop recovered memory context and resource owner after the -- subtransaction rollback and continued. CREATE ROLE vamana_td_other; CREATE ROLE vamana_td_caller; CREATE TABLE vamana_td_c (id int, val vector(3)); CREATE TABLE vamana_td_d (id int, val vector(3)); INSERT INTO vamana_td_c VALUES (1, '[1,1,1]'); INSERT INTO vamana_td_d VALUES (1, '[1,1,1]'); SET client_min_messages = error; CREATE INDEX vamana_td_ic ON vamana_td_c USING vamana (val vector_l2_ops); CREATE INDEX vamana_td_id ON vamana_td_d USING vamana (val vector_l2_ops); RESET client_min_messages; ALTER TABLE vamana_td_c OWNER TO vamana_td_other; ALTER TABLE vamana_td_d OWNER TO vamana_td_caller; SET ROLE vamana_td_caller; SELECT index_name, dropped, reason FROM svs_teardown_database() ORDER BY index_name; WARNING: svs_teardown_database: could not drop index public.vamana_td_ic: must be owner of index vamana_td_ic index_name | dropped | reason ---------------------+---------+------------------------------------- public.vamana_td_ic | f | must be owner of index vamana_td_ic public.vamana_td_id | t | (2 rows) RESET ROLE; -- The owned index is gone; the unowned one survives. SELECT n FROM vamana_live_indexes; n --- 1 (1 row) DROP TABLE vamana_td_c; -- removes the surviving unowned index DROP TABLE vamana_td_a, vamana_td_b, vamana_td_d; DROP ROLE vamana_td_other, vamana_td_caller; -- Already-clean database: teardown returns zero rows without error. SELECT * FROM svs_teardown_database(); index_relid | index_name | dropped | reason -------------+------------+---------+-------- (0 rows) -- svs_warmup_index/svs_warmup_database gate on SELECT on the index's table -- (same policy as pg_prewarm): warming only makes the index resident, no more -- sensitive than reading it. Contrast svs_teardown_database above, which gates -- on ownership because it drops. CREATE ROLE vamana_warm_reader; CREATE TABLE vamana_warm_a (id int, val vector(3)); CREATE TABLE vamana_warm_b (id int, val vector(3)); INSERT INTO vamana_warm_a VALUES (1, '[1,1,1]'); INSERT INTO vamana_warm_b VALUES (1, '[1,1,1]'); SET client_min_messages = error; CREATE INDEX vamana_warm_ia ON vamana_warm_a USING vamana (val vector_l2_ops); CREATE INDEX vamana_warm_ib ON vamana_warm_b USING vamana (val vector_l2_ops); RESET client_min_messages; -- The table owner may warm its index. SELECT svs_warmup_index('vamana_warm_ia'); svs_warmup_index ------------------ (1 row) -- A role is granted SELECT on vamana_warm_a only: it may warm that index, but -- warming vamana_warm_ib is denied, not silently skipped. GRANT SELECT ON vamana_warm_a TO vamana_warm_reader; SET ROLE vamana_warm_reader; SELECT svs_warmup_index('vamana_warm_ia'); svs_warmup_index ------------------ (1 row) SELECT svs_warmup_index('vamana_warm_ib'); ERROR: permission denied for index vamana_warm_ib RESET ROLE; -- svs_warmup_database warms exactly the vamana indexes the caller may read and -- skips the rest silently, so the count equals the caller's readable count -- however many exist: vamana_warm_reader reads vamana_warm_a but not _b. SET ROLE vamana_warm_reader; SELECT svs_warmup_database() = (SELECT count(*) FROM pg_index i JOIN pg_class ic ON ic.oid = i.indexrelid JOIN pg_am am ON am.oid = ic.relam WHERE am.amname = 'vamana' AND has_table_privilege(i.indrelid, 'SELECT')) AS warms_only_readable; warms_only_readable --------------------- t (1 row) RESET ROLE; DROP TABLE vamana_warm_a, vamana_warm_b; DROP ROLE vamana_warm_reader; -- BEFORE DELETE guard: a row cannot be removed while vamana indexes still -- exist in its database, reading the committed index count from shmem. CREATE TABLE vamana_gate_t (id int, val vector(3)); INSERT INTO vamana_gate_t VALUES (1, '[1,1,1]'); SET client_min_messages = error; CREATE INDEX vamana_gate_i ON vamana_gate_t USING vamana (val vector_l2_ops); RESET client_min_messages; -- Rejected while the index exists; the row is untouched. DELETE FROM vamana_databases WHERE datname = current_database(); ERROR: cannot remove "contrib_regression" from vamana_databases: 1 vamana index(es) still exist in that database HINT: run svs_teardown_database() in "contrib_regression" first SELECT count(*) FROM vamana_databases WHERE datname = current_database(); count ------- 1 (1 row) -- TRUNCATE must be rejected for the identical reason: a row-level BEFORE -- DELETE trigger alone cannot stop it (TRUNCATE never fires row triggers), -- so this needs its own BEFORE TRUNCATE guard. TRUNCATE vamana_databases; ERROR: cannot truncate vamana_databases: 1 vamana index(es) still exist in database "contrib_regression" HINT: run svs_teardown_database() in "contrib_regression" first SELECT count(*) FROM vamana_databases WHERE datname = current_database(); count ------- 1 (1 row) -- After teardown the count is zero, so the same DELETE is allowed. Rolled -- back to keep this database enabled for the remaining regression files. SELECT dropped FROM svs_teardown_database(); dropped --------- t (1 row) SELECT DISTINCT index_count FROM pg_stat_vamana_worker WHERE db_oid = (SELECT oid FROM pg_database WHERE datname = current_database()); index_count ------------- 0 (1 row) BEGIN; DELETE FROM vamana_databases WHERE datname = current_database(); ROLLBACK; -- TRUNCATE is allowed once no indexes remain, same as DELETE above. Rolled -- back for the same reason: keep this database enabled for the rest of the -- suite. BEGIN; TRUNCATE vamana_databases; ROLLBACK; DROP TABLE vamana_gate_t; -- A row whose database was dropped without cleanup is deletable: the guard -- tolerates the missing database and allows the DELETE. CREATE DATABASE vamana_gate_gone; INSERT INTO vamana_databases (datname, enabled) VALUES ('vamana_gate_gone', false); DROP DATABASE vamana_gate_gone; DELETE FROM vamana_databases WHERE datname = 'vamana_gate_gone'; DROP VIEW vamana_live_indexes;