feat(drive): impl policy photo + music policies
add `include_in_photo_index` and `include_in_music_index` policies
both true for default personal drive
photo is implemented
music is not yet implemented
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
-- ════════════════════════════════════════════════════════════════════════════
|
||||
-- PR-A / §15 — default personal drives get include_in_photo_index +
|
||||
-- include_in_music_index materialised on the JSONB `policies` bag
|
||||
-- ════════════════════════════════════════════════════════════════════════════
|
||||
-- `docs/plan/drive.md` §15 locks the two policies as symmetric per-drive
|
||||
-- opt-in flags. The default personal drive is always in scope for Photos +
|
||||
-- Music, so we materialise both flags = `true` on every default personal
|
||||
-- drive rather than carving out a `default_for_user IS NOT NULL` OR-branch
|
||||
-- in the query predicate. Net effect: the SQL predicate is a single positive
|
||||
-- rule keyed off the JSONB flag alone (see `list_media_files` after the
|
||||
-- companion Rust rewrite).
|
||||
--
|
||||
-- New default personal drives get these flags at creation time via
|
||||
-- `DriveRepository::create_personal_drive_atomic` (the INSERT literal on
|
||||
-- that path was updated alongside this migration). This migration handles
|
||||
-- the existing rows, seeded by the D0 backfill.
|
||||
--
|
||||
-- Non-default drives (secondary personals, shared drives) are NOT touched —
|
||||
-- they stay opted-out until the owner flips the flag via the admin
|
||||
-- "Manage policies" modal.
|
||||
--
|
||||
-- Idempotent: `policies || {…}` is a no-op if the keys are already set to
|
||||
-- the same values, and JSONB `||` is right-precedence so the migration
|
||||
-- never overwrites an owner's explicit opt-out that was already recorded.
|
||||
-- (If someone had `include_in_photo_index=false` set on their default
|
||||
-- personal via a manual PATCH, this UPDATE would still overwrite to true;
|
||||
-- that's acceptable — the D5 policy UI didn't exist for these flags
|
||||
-- before this PR, so no such manual opt-out can be in the wild yet.)
|
||||
|
||||
UPDATE storage.drives
|
||||
SET policies = policies || '{"include_in_photo_index": true, "include_in_music_index": true}'::jsonb
|
||||
WHERE default_for_user IS NOT NULL;
|
||||
@@ -0,0 +1,25 @@
|
||||
-- ════════════════════════════════════════════════════════════════════════════
|
||||
-- PR-A / §15 — partial covering index for the drive-scoped Photos timeline
|
||||
-- ════════════════════════════════════════════════════════════════════════════
|
||||
-- Sibling of `idx_files_media_timeline` (initial_schema.sql:581), keyed on
|
||||
-- `drive_id` instead of `user_id`. The Photos handler predicate is being
|
||||
-- rewritten to `fi.drive_id IN (drives with include_in_photo_index = true
|
||||
-- AND caller has Read)` — that subquery produces a small drive-id set,
|
||||
-- and this index gives Postgres one IndexScan per drive_id already
|
||||
-- ordered by `media_sort_date DESC`, so LIMIT stops the scan early.
|
||||
-- Same O(LIMIT) shape as the pre-D7 user_id-keyed hot path.
|
||||
--
|
||||
-- The old `idx_files_media_timeline (user_id, media_sort_date DESC)` index
|
||||
-- is intentionally kept for now — it still backs the dedup / storage sweep
|
||||
-- paths that D7 will migrate separately. Once D7 drops the `user_id`
|
||||
-- column those paths lose their backing index at the same moment; that PR
|
||||
-- can drop the old index in the same migration.
|
||||
--
|
||||
-- Partial WHERE clause is identical to the existing sibling so the index
|
||||
-- stays as compact as its predecessor: only image/video rows that aren't
|
||||
-- trashed.
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_files_media_timeline_by_drive
|
||||
ON storage.files (drive_id, media_sort_date DESC)
|
||||
WHERE NOT is_trashed
|
||||
AND (mime_type LIKE 'image/%' OR mime_type LIKE 'video/%');
|
||||
Reference in New Issue
Block a user