-- Jellyfin strict index-removal runbook
-- Strategy: exactly ONE DROP per maintenance window.
-- Generated: 2026-03-08
--
-- Important:
-- 1) Execute only one window per maintenance period.
-- 2) Keep each statement standalone (no BEGIN/COMMIT around CONCURRENTLY).
-- 3) If regression appears, run that window's rollback CREATE INDEX CONCURRENTLY.

/* =====================================================================
   Shared baseline (run before each window)
   ===================================================================== */
SELECT
	now() AS captured_at,
	schemaname,
	relname AS table_name,
	indexrelname AS index_name,
	idx_scan,
	idx_tup_read,
	idx_tup_fetch,
	pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname IN ('library', 'authentication', 'users', 'activitylog', 'displaypreferences')
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;

/* =====================================================================
   WINDOW 1 (lowest risk first)
   Target: library.IX_MediaStreamInfos_StreamIndex_StreamType_Language
   ===================================================================== */
-- Drop:
DROP INDEX CONCURRENTLY IF EXISTS library."IX_MediaStreamInfos_StreamIndex_StreamType_Language";

-- Verify impact:
SELECT
	now() AS check_time,
	relname AS table_name,
	indexrelname AS index_name,
	idx_scan,
	idx_tup_read,
	idx_tup_fetch,
	pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'library'
	AND relname = 'MediaStreamInfos'
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;

-- Rollback (recreate):
CREATE INDEX CONCURRENTLY "IX_MediaStreamInfos_StreamIndex_StreamType_Language"
	ON library."MediaStreamInfos" USING btree ("StreamIndex", "StreamType", "Language");

/* =====================================================================
   WINDOW 2
   Target: library.IX_MediaStreamInfos_StreamIndex_StreamType
   ===================================================================== */
-- Drop:
DROP INDEX CONCURRENTLY IF EXISTS library."IX_MediaStreamInfos_StreamIndex_StreamType";

-- Verify impact:
SELECT
	now() AS check_time,
	relname AS table_name,
	indexrelname AS index_name,
	idx_scan,
	idx_tup_read,
	idx_tup_fetch,
	pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'library'
	AND relname = 'MediaStreamInfos'
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;

-- Rollback (recreate):
CREATE INDEX CONCURRENTLY "IX_MediaStreamInfos_StreamIndex_StreamType"
	ON library."MediaStreamInfos" USING btree ("StreamIndex", "StreamType");

/* =====================================================================
   WINDOW 3
   Target: library.IX_MediaStreamInfos_StreamIndex
   ===================================================================== */
-- Drop:
DROP INDEX CONCURRENTLY IF EXISTS library."IX_MediaStreamInfos_StreamIndex";

-- Verify impact:
SELECT
	now() AS check_time,
	relname AS table_name,
	indexrelname AS index_name,
	idx_scan,
	idx_tup_read,
	idx_tup_fetch,
	pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'library'
	AND relname = 'MediaStreamInfos'
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;

-- Rollback (recreate):
CREATE INDEX CONCURRENTLY "IX_MediaStreamInfos_StreamIndex"
	ON library."MediaStreamInfos" USING btree ("StreamIndex");

/* =====================================================================
   WINDOW 4 (medium risk)
   Target: library.baseitemproviders_providerid_idx
   ===================================================================== */
-- Drop:
DROP INDEX CONCURRENTLY IF EXISTS library.baseitemproviders_providerid_idx;

-- Verify impact:
SELECT
	now() AS check_time,
	relname AS table_name,
	indexrelname AS index_name,
	idx_scan,
	idx_tup_read,
	idx_tup_fetch,
	pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'library'
	AND relname = 'BaseItemProviders'
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;

-- Rollback (recreate):
CREATE INDEX CONCURRENTLY baseitemproviders_providerid_idx
	ON library."BaseItemProviders" USING btree ("ProviderId", "ItemId");

/* =====================================================================
   WINDOW 5 (medium risk)
   Target: library.baseitemproviders_providervalue_idx
   ===================================================================== */
-- Drop:
DROP INDEX CONCURRENTLY IF EXISTS library.baseitemproviders_providervalue_idx;

-- Verify impact:
SELECT
	now() AS check_time,
	relname AS table_name,
	indexrelname AS index_name,
	idx_scan,
	idx_tup_read,
	idx_tup_fetch,
	pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'library'
	AND relname = 'BaseItemProviders'
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;

-- Rollback (recreate):
CREATE INDEX CONCURRENTLY baseitemproviders_providervalue_idx
	ON library."BaseItemProviders" USING btree ("ProviderValue", "ProviderId");

/* =====================================================================
   WINDOW 6 (highest risk among current candidates; keep for last)
   Target: library.IX_BaseItemProviders_ProviderId_ProviderValue_ItemId
   ===================================================================== */
-- Drop:
DROP INDEX CONCURRENTLY IF EXISTS library."IX_BaseItemProviders_ProviderId_ProviderValue_ItemId";

-- Verify impact:
SELECT
	now() AS check_time,
	relname AS table_name,
	indexrelname AS index_name,
	idx_scan,
	idx_tup_read,
	idx_tup_fetch,
	pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'library'
	AND relname = 'BaseItemProviders'
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;

-- Rollback (recreate):
CREATE INDEX CONCURRENTLY "IX_BaseItemProviders_ProviderId_ProviderValue_ItemId"
	ON library."BaseItemProviders" USING btree ("ProviderId", "ProviderValue", "ItemId");

/* =====================================================================
   Explicit exclusions (do not remove in this runbook)
   =====================================================================
   - Any PK_* index
   - Any UNIQUE index enforcing constraints
   - users.IX_Users_Username
   - authentication.IX_DeviceOptions_DeviceId
   ===================================================================== */