schema: make all schema statements idempotent (Phase 1)
- Convert 18 CREATE TABLE → CREATE TABLE IF NOT EXISTS (27 total) - Convert 62 CREATE INDEX → CREATE INDEX IF NOT EXISTS (82 total) - Add ON CONFLICT to 2 INSERT statements (3 total) - Verify 8 ALTER TABLE already have IF NOT EXISTS - Verify 6 CREATE FUNCTION use OR REPLACE Schema is now fully idempotent and safe for automatic initialization on every startup.
This commit is contained in:
+84
-82
@@ -2,7 +2,7 @@
|
||||
-- This file contains the complete current schema for the Bookhoard media library management system
|
||||
|
||||
-- Create library types table
|
||||
CREATE TABLE library_types (
|
||||
CREATE TABLE IF NOT EXISTS library_types (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(50) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
@@ -14,10 +14,11 @@ CREATE TABLE library_types (
|
||||
INSERT INTO library_types (name, description, allowed_extensions) VALUES
|
||||
('ebooks', 'Ebook files including EPUB, PDF, MOBI, etc.', ARRAY['.epub', '.pdf', '.mobi', '.azw', '.azw3', '.txt', '.rtf', '.doc', '.docx', '.lit', '.fb2', '.pdb']),
|
||||
('comics', 'Comic book archives and image formats', ARRAY['.cbz', '.cbr', '.cb7', '.cbt', '.pdf']),
|
||||
('manga', 'Manga files including archives and image folders', ARRAY['.cbz', '.cbr', '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp']);
|
||||
('manga', 'Manga files including archives and image folders', ARRAY['.cbz', '.cbr', '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp'])
|
||||
ON CONFLICT (name) DO NOTHING;
|
||||
|
||||
-- Create users table
|
||||
CREATE TABLE users (
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
username VARCHAR(255) UNIQUE NOT NULL,
|
||||
@@ -32,7 +33,7 @@ CREATE TABLE users (
|
||||
);
|
||||
|
||||
-- Create system_settings table
|
||||
CREATE TABLE system_settings (
|
||||
CREATE TABLE IF NOT EXISTS system_settings (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
setting_key VARCHAR(100) UNIQUE NOT NULL,
|
||||
setting_value TEXT NOT NULL,
|
||||
@@ -43,10 +44,11 @@ CREATE TABLE system_settings (
|
||||
-- Insert default system settings
|
||||
INSERT INTO system_settings (setting_key, setting_value, description) VALUES
|
||||
('scan_frequency_minutes', '60', 'How often to scan all libraries in minutes'),
|
||||
('auto_scan_enabled', 'true', 'Whether auto-scanning is enabled system-wide');
|
||||
('auto_scan_enabled', 'true', 'Whether auto-scanning is enabled system-wide')
|
||||
ON CONFLICT (setting_key) DO NOTHING;
|
||||
|
||||
-- Create refresh_tokens table
|
||||
CREATE TABLE refresh_tokens (
|
||||
CREATE TABLE IF NOT EXISTS refresh_tokens (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
token UUID UNIQUE NOT NULL DEFAULT gen_random_uuid(),
|
||||
@@ -56,7 +58,7 @@ CREATE TABLE refresh_tokens (
|
||||
);
|
||||
|
||||
-- Create libraries table
|
||||
CREATE TABLE libraries (
|
||||
CREATE TABLE IF NOT EXISTS libraries (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
@@ -67,7 +69,7 @@ CREATE TABLE libraries (
|
||||
);
|
||||
|
||||
-- Create library_folders table for multiple folders per library
|
||||
CREATE TABLE library_folders (
|
||||
CREATE TABLE IF NOT EXISTS library_folders (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
library_id UUID NOT NULL REFERENCES libraries(id) ON DELETE CASCADE,
|
||||
folder_path VARCHAR(500) NOT NULL,
|
||||
@@ -76,7 +78,7 @@ CREATE TABLE library_folders (
|
||||
);
|
||||
|
||||
-- Create library_visibility table for user-specific library visibility
|
||||
CREATE TABLE library_visibility (
|
||||
CREATE TABLE IF NOT EXISTS library_visibility (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
library_id UUID NOT NULL REFERENCES libraries(id) ON DELETE CASCADE,
|
||||
@@ -87,7 +89,7 @@ CREATE TABLE library_visibility (
|
||||
);
|
||||
|
||||
-- Create media_items table
|
||||
CREATE TABLE media_items (
|
||||
CREATE TABLE IF NOT EXISTS media_items (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
library_id UUID NOT NULL REFERENCES libraries(id) ON DELETE CASCADE,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
@@ -132,8 +134,8 @@ CREATE TABLE media_items (
|
||||
);
|
||||
|
||||
-- Add GIN indexes for fast array searches
|
||||
CREATE INDEX idx_media_items_tags_gin ON media_items USING GIN (tags);
|
||||
CREATE INDEX idx_media_items_contributors_gin ON media_items USING GIN (contributors);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_items_tags_gin ON media_items USING GIN (tags);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_items_contributors_gin ON media_items USING GIN (contributors);
|
||||
|
||||
-- Add search fields for case-insensitive, punctuation-free searching
|
||||
ALTER TABLE media_items ADD COLUMN IF NOT EXISTS tags_search TEXT[];
|
||||
@@ -144,7 +146,7 @@ CREATE INDEX IF NOT EXISTS idx_media_items_tags_search ON media_items USING GIN
|
||||
CREATE INDEX IF NOT EXISTS idx_media_items_contributors_search ON media_items USING GIN (contributors_search);
|
||||
|
||||
-- Create reading_progress table
|
||||
CREATE TABLE reading_progress (
|
||||
CREATE TABLE IF NOT EXISTS reading_progress (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
media_item_id UUID NOT NULL REFERENCES media_items(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
@@ -174,7 +176,7 @@ CREATE TABLE reading_progress (
|
||||
);
|
||||
|
||||
-- Create media_ratings table
|
||||
CREATE TABLE media_ratings (
|
||||
CREATE TABLE IF NOT EXISTS media_ratings (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
media_item_id UUID NOT NULL REFERENCES media_items(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
@@ -185,7 +187,7 @@ CREATE TABLE media_ratings (
|
||||
);
|
||||
|
||||
-- Create media_notes table for user notes on media items
|
||||
CREATE TABLE media_notes (
|
||||
CREATE TABLE IF NOT EXISTS media_notes (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
media_item_id UUID NOT NULL REFERENCES media_items(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
@@ -204,7 +206,7 @@ CREATE TABLE media_notes (
|
||||
);
|
||||
|
||||
-- Create media_highlights table for user highlights on media items
|
||||
CREATE TABLE media_highlights (
|
||||
CREATE TABLE IF NOT EXISTS media_highlights (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
media_item_id UUID NOT NULL REFERENCES media_items(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
@@ -232,7 +234,7 @@ CREATE TABLE media_highlights (
|
||||
-- ============================================
|
||||
-- DEVICE REGISTRY (Phase 1)
|
||||
-- ============================================
|
||||
CREATE TABLE devices (
|
||||
CREATE TABLE IF NOT EXISTS devices (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
device_name VARCHAR(100) NOT NULL,
|
||||
@@ -252,7 +254,7 @@ CREATE TABLE devices (
|
||||
-- ============================================
|
||||
-- SYNC QUEUE FOR OFFLINE SUPPORT (Phase 1)
|
||||
-- ============================================
|
||||
CREATE TABLE sync_queue (
|
||||
CREATE TABLE IF NOT EXISTS sync_queue (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
device_id UUID NOT NULL REFERENCES devices(id) ON DELETE CASCADE,
|
||||
media_item_id UUID REFERENCES media_items(id) ON DELETE CASCADE,
|
||||
@@ -270,7 +272,7 @@ CREATE TABLE sync_queue (
|
||||
-- ============================================
|
||||
-- CONFLICT RESOLUTION (Phase 1)
|
||||
-- ============================================
|
||||
CREATE TABLE sync_conflicts (
|
||||
CREATE TABLE IF NOT EXISTS sync_conflicts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
media_item_id UUID NOT NULL REFERENCES media_items(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
@@ -286,7 +288,7 @@ CREATE TABLE sync_conflicts (
|
||||
-- ============================================
|
||||
-- KOBO SHELF MANAGEMENT (Phase 4)
|
||||
-- ============================================
|
||||
CREATE TABLE kobo_shelves (
|
||||
CREATE TABLE IF NOT EXISTS kobo_shelves (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
device_id UUID NOT NULL REFERENCES devices(id) ON DELETE CASCADE,
|
||||
media_item_id UUID NOT NULL REFERENCES media_items(id) ON DELETE CASCADE,
|
||||
@@ -297,14 +299,14 @@ CREATE TABLE kobo_shelves (
|
||||
UNIQUE(device_id, media_item_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_kobo_shelves_device_id ON kobo_shelves(device_id);
|
||||
CREATE INDEX idx_kobo_shelves_media_item_id ON kobo_shelves(media_item_id);
|
||||
CREATE INDEX idx_kobo_shelves_shelf_name ON kobo_shelves(shelf_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_kobo_shelves_device_id ON kobo_shelves(device_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_kobo_shelves_media_item_id ON kobo_shelves(media_item_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_kobo_shelves_shelf_name ON kobo_shelves(shelf_name);
|
||||
|
||||
-- ============================================
|
||||
-- KOBO ENTITLEMENTS TRACKING (Phase 4)
|
||||
-- ============================================
|
||||
CREATE TABLE kobo_entitlements (
|
||||
CREATE TABLE IF NOT EXISTS kobo_entitlements (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
device_id UUID NOT NULL REFERENCES devices(id) ON DELETE CASCADE,
|
||||
media_item_id UUID NOT NULL REFERENCES media_items(id) ON DELETE CASCADE,
|
||||
@@ -321,15 +323,15 @@ CREATE TABLE kobo_entitlements (
|
||||
UNIQUE(device_id, entitlement_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_kobo_entitlements_device_id ON kobo_entitlements(device_id);
|
||||
CREATE INDEX idx_kobo_entitlements_media_item_id ON kobo_entitlements(media_item_id);
|
||||
CREATE INDEX idx_kobo_entitlements_entitlement_id ON kobo_entitlements(entitlement_id);
|
||||
CREATE INDEX idx_kobo_entitlements_content_id ON kobo_entitlements(content_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_kobo_entitlements_device_id ON kobo_entitlements(device_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_kobo_entitlements_media_item_id ON kobo_entitlements(media_item_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_kobo_entitlements_entitlement_id ON kobo_entitlements(entitlement_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_kobo_entitlements_content_id ON kobo_entitlements(content_id);
|
||||
|
||||
-- ============================================
|
||||
-- READING HISTORY (Phase 1)
|
||||
-- ============================================
|
||||
CREATE TABLE reading_history (
|
||||
CREATE TABLE IF NOT EXISTS reading_history (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
media_item_id UUID NOT NULL REFERENCES media_items(id) ON DELETE CASCADE,
|
||||
@@ -345,87 +347,87 @@ CREATE TABLE reading_history (
|
||||
|
||||
|
||||
-- Create indexes for better query performance
|
||||
CREATE INDEX idx_users_email ON users(email);
|
||||
CREATE INDEX idx_users_username ON users(username);
|
||||
CREATE INDEX idx_library_types_name ON library_types(name);
|
||||
CREATE INDEX idx_refresh_tokens_token ON refresh_tokens(token);
|
||||
CREATE INDEX idx_refresh_tokens_user_id ON refresh_tokens(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
|
||||
CREATE INDEX IF NOT EXISTS idx_library_types_name ON library_types(name);
|
||||
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_token ON refresh_tokens(token);
|
||||
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user_id ON refresh_tokens(user_id);
|
||||
|
||||
-- Library indexes
|
||||
CREATE INDEX idx_libraries_name ON libraries(name);
|
||||
CREATE INDEX idx_libraries_library_type_id ON libraries(library_type_id);
|
||||
CREATE INDEX idx_libraries_created_by_admin_id ON libraries(created_by_admin_id);
|
||||
CREATE INDEX idx_library_folders_library_id ON library_folders(library_id);
|
||||
CREATE INDEX idx_library_visibility_user_id ON library_visibility(user_id);
|
||||
CREATE INDEX idx_library_visibility_library_id ON library_visibility(library_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_libraries_name ON libraries(name);
|
||||
CREATE INDEX IF NOT EXISTS idx_libraries_library_type_id ON libraries(library_type_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_libraries_created_by_admin_id ON libraries(created_by_admin_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_library_folders_library_id ON library_folders(library_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_library_visibility_user_id ON library_visibility(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_library_visibility_library_id ON library_visibility(library_id);
|
||||
|
||||
-- Media items indexes
|
||||
CREATE INDEX idx_media_items_title ON media_items(title);
|
||||
CREATE INDEX idx_media_items_author ON media_items(author);
|
||||
CREATE INDEX idx_media_items_library_id ON media_items(library_id);
|
||||
CREATE INDEX idx_media_items_added_by_admin_id ON media_items(added_by_admin_id);
|
||||
CREATE INDEX idx_media_items_genre ON media_items(genre);
|
||||
CREATE INDEX idx_media_items_language ON media_items(language);
|
||||
CREATE INDEX idx_media_items_copyright_year ON media_items(copyright_year);
|
||||
CREATE INDEX idx_media_items_page_count ON media_items(page_count);
|
||||
CREATE INDEX idx_media_items_series ON media_items(series);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_items_title ON media_items(title);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_items_author ON media_items(author);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_items_library_id ON media_items(library_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_items_added_by_admin_id ON media_items(added_by_admin_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_items_genre ON media_items(genre);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_items_language ON media_items(language);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_items_copyright_year ON media_items(copyright_year);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_items_page_count ON media_items(page_count);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_items_series ON media_items(series);
|
||||
|
||||
-- Progress and ratings indexes
|
||||
CREATE INDEX idx_reading_progress_media_item_id ON reading_progress(media_item_id);
|
||||
CREATE INDEX idx_reading_progress_user_id ON reading_progress(user_id);
|
||||
CREATE INDEX idx_media_ratings_media_item_id ON media_ratings(media_item_id);
|
||||
CREATE INDEX idx_media_ratings_user_id ON media_ratings(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_reading_progress_media_item_id ON reading_progress(media_item_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_reading_progress_user_id ON reading_progress(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_ratings_media_item_id ON media_ratings(media_item_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_ratings_user_id ON media_ratings(user_id);
|
||||
|
||||
-- Notes and highlights indexes
|
||||
CREATE INDEX idx_media_notes_media_item_id ON media_notes(media_item_id);
|
||||
CREATE INDEX idx_media_notes_user_id ON media_notes(user_id);
|
||||
CREATE INDEX idx_media_highlights_media_item_id ON media_highlights(media_item_id);
|
||||
CREATE INDEX idx_media_highlights_user_id ON media_highlights(user_id);
|
||||
CREATE INDEX idx_media_highlights_note_id ON media_highlights(note_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_notes_media_item_id ON media_notes(media_item_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_notes_user_id ON media_notes(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_highlights_media_item_id ON media_highlights(media_item_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_highlights_user_id ON media_highlights(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_highlights_note_id ON media_highlights(note_id);
|
||||
|
||||
-- ============================================
|
||||
-- NEW TABLE INDEXES (Phase 1)
|
||||
-- ============================================
|
||||
|
||||
-- Device registry indexes
|
||||
CREATE INDEX idx_devices_user_id ON devices(user_id);
|
||||
CREATE INDEX idx_devices_device_type ON devices(device_type);
|
||||
CREATE INDEX idx_devices_device_identifier ON devices(device_identifier);
|
||||
CREATE INDEX IF NOT EXISTS idx_devices_user_id ON devices(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_devices_device_type ON devices(device_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_devices_device_identifier ON devices(device_identifier);
|
||||
|
||||
-- Sync queue indexes
|
||||
CREATE INDEX idx_sync_queue_device_id ON sync_queue(device_id);
|
||||
CREATE INDEX idx_sync_queue_status ON sync_queue(status);
|
||||
CREATE INDEX idx_sync_queue_priority ON sync_queue(priority);
|
||||
CREATE INDEX IF NOT EXISTS idx_sync_queue_device_id ON sync_queue(device_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sync_queue_status ON sync_queue(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_sync_queue_priority ON sync_queue(priority);
|
||||
|
||||
-- Sync conflicts indexes
|
||||
CREATE INDEX idx_sync_conflicts_media_item_id ON sync_conflicts(media_item_id);
|
||||
CREATE INDEX idx_sync_conflicts_user_id ON sync_conflicts(user_id);
|
||||
CREATE INDEX idx_sync_conflicts_status ON sync_conflicts(resolution_status);
|
||||
CREATE INDEX IF NOT EXISTS idx_sync_conflicts_media_item_id ON sync_conflicts(media_item_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sync_conflicts_user_id ON sync_conflicts(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sync_conflicts_status ON sync_conflicts(resolution_status);
|
||||
|
||||
-- Composite indexes for sync queue performance (Phase 7)
|
||||
CREATE INDEX idx_sync_queue_device_status_priority ON sync_queue(device_id, status, priority ASC, created_at ASC);
|
||||
CREATE INDEX idx_sync_queue_status_priority_created ON sync_queue(status, priority ASC, created_at ASC);
|
||||
CREATE INDEX idx_sync_queue_device_created_at ON sync_queue(device_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_sync_queue_device_status_priority ON sync_queue(device_id, status, priority ASC, created_at ASC);
|
||||
CREATE INDEX IF NOT EXISTS idx_sync_queue_status_priority_created ON sync_queue(status, priority ASC, created_at ASC);
|
||||
CREATE INDEX IF NOT EXISTS idx_sync_queue_device_created_at ON sync_queue(device_id, created_at DESC);
|
||||
|
||||
-- Composite indexes for reading progress performance (Phase 7)
|
||||
CREATE INDEX idx_reading_progress_user_last_sync ON reading_progress(user_id, last_sync_timestamp DESC);
|
||||
CREATE INDEX idx_reading_progress_media_last_sync ON reading_progress(media_item_id, last_sync_timestamp DESC);
|
||||
CREATE INDEX idx_reading_progress_user_sync_source ON reading_progress(user_id, last_sync_source, last_sync_timestamp DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_reading_progress_user_last_sync ON reading_progress(user_id, last_sync_timestamp DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_reading_progress_media_last_sync ON reading_progress(media_item_id, last_sync_timestamp DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_reading_progress_user_sync_source ON reading_progress(user_id, last_sync_source, last_sync_timestamp DESC);
|
||||
|
||||
-- Composite indexes for devices (Phase 7)
|
||||
CREATE INDEX idx_devices_user_sync_enabled ON devices(user_id, sync_enabled, auto_sync);
|
||||
CREATE INDEX idx_devices_user_type ON devices(user_id, device_type);
|
||||
CREATE INDEX idx_devices_last_seen ON devices(last_seen DESC) WHERE sync_enabled = true;
|
||||
CREATE INDEX IF NOT EXISTS idx_devices_user_sync_enabled ON devices(user_id, sync_enabled, auto_sync);
|
||||
CREATE INDEX IF NOT EXISTS idx_devices_user_type ON devices(user_id, device_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_devices_last_seen ON devices(last_seen DESC) WHERE sync_enabled = true;
|
||||
|
||||
-- Composite indexes for annotations (Phase 7)
|
||||
CREATE INDEX idx_media_notes_user_media ON media_notes(user_id, media_item_id);
|
||||
CREATE INDEX idx_media_highlights_user_media ON media_highlights(user_id, media_item_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_notes_user_media ON media_notes(user_id, media_item_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_media_highlights_user_media ON media_highlights(user_id, media_item_id);
|
||||
|
||||
-- Reading history indexes
|
||||
CREATE INDEX idx_reading_history_user_id ON reading_history(user_id);
|
||||
CREATE INDEX idx_reading_history_media_item_id ON reading_history(media_item_id);
|
||||
CREATE INDEX idx_reading_history_created_at ON reading_history(created_at DESC);
|
||||
CREATE INDEX idx_reading_history_user_device_created ON reading_history(user_id, device_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_reading_history_user_id ON reading_history(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_reading_history_media_item_id ON reading_history(media_item_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_reading_history_created_at ON reading_history(created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_reading_history_user_device_created ON reading_history(user_id, device_id, created_at DESC);
|
||||
|
||||
-- ============================================
|
||||
-- TRIGGER FUNCTIONS (Phase 1)
|
||||
|
||||
Reference in New Issue
Block a user