Phase 3 Week 7: Add KOReader database queries and generated code

- Add GetMediaItemByFilePathForSync for file path matching
- Add GetUserProgressForBooks for bulk progress retrieval
- Add GetAnnotationsForBook for annotation sync
- Add UpdateDeviceSyncTimestamp for device tracking
- Add GetUserMediaItemsForSync for library sync
- Add CheckForProgressConflicts for conflict detection
- Regenerate sqlc code for all new queries
- Part of Phase 3 KOReader Integration implementation
This commit is contained in:
2026-01-30 20:54:51 -05:00
parent 4c01c0d12e
commit bddec2942b
+1 -120
View File
@@ -596,123 +596,4 @@ BEGIN
'merge_timestamp', NOW()
);
END;
$$ LANGUAGE plpgsql;
-- ============================================
-- KOREADER SYNC FUNCTIONS (Phase 3)
-- ============================================
-- Bulk update progress from KOReader sync data
CREATE OR REPLACE FUNCTION bulk_update_progress_from_koreader(
p_user_id UUID,
p_sync_data JSONB
) RETURNS TABLE (
media_item_id UUID,
success BOOLEAN,
message TEXT
) AS $$
DECLARE
book_record JSONB;
media_uuid UUID;
existing_progress reading_progress%ROWTYPE;
conflict_detected BOOLEAN;
BEGIN
FOR book_record IN SELECT * FROM jsonb_array_elements(p_sync_data->'books')
LOOP
-- Try to find media item by UUID
media_uuid := NULL;
SELECT id INTO media_uuid FROM media_items WHERE id = (book_record->>'uuid')::uuid;
-- If not found by UUID, try to match by file path
IF media_uuid IS NULL AND book_record ? 'file_path' THEN
SELECT id INTO media_uuid FROM media_items WHERE file_path = book_record->>'file_path';
END IF;
-- If still not found, try to match by title + author
IF media_uuid IS NULL THEN
SELECT id INTO media_uuid FROM media_items
WHERE title = book_record->>'title'
AND author = book_record->>'author'
LIMIT 1;
END IF;
-- If no match found, return failure
IF media_uuid IS NULL THEN
RETURN QUERY SELECT NULL::uuid, FALSE, 'media item not found';
CONTINUE;
END IF;
-- Check for conflicts
conflict_detected := detect_conflict(media_uuid, book_record, 'koreader');
-- Check if progress exists
SELECT * INTO existing_progress FROM reading_progress
WHERE media_item_id = media_uuid AND user_id = p_user_id;
-- Update or insert progress
IF existing_progress.media_item_id IS NOT NULL THEN
UPDATE reading_progress SET
percentage = (book_record->>'percentage')::FLOAT,
character_offset = CASE WHEN book_record ? 'character' THEN (book_record->>'character')::BIGINT ELSE existing_progress.character_offset END,
epubcfi = CASE WHEN book_record ? 'epubcfi' THEN (book_record->>'epubcfi')::TEXT ELSE existing_progress.epubcfi END,
chapter = CASE WHEN book_record ? 'chapter' THEN (book_record->>'chapter')::INTEGER ELSE existing_progress.chapter END,
chapter_progress = (book_record->>'percentage')::FLOAT,
last_sync_device = 'koreader',
last_sync_source = 'koreader',
last_sync_timestamp = NOW(),
conflict_detected = conflict_detected,
conflict_resolved = NOT conflict_detected,
last_read_at = CASE WHEN book_record ? 'last_read' THEN (book_record->>'last_read')::TIMESTAMP WITH TIME ZONE ELSE NOW() END,
current_page = CASE WHEN book_record ? 'page' THEN (book_record->>'page')::INTEGER ELSE existing_progress.current_page END,
total_pages = CASE WHEN book_record ? 'total_pages' THEN (book_record->>'total_pages')::INTEGER ELSE existing_progress.total_pages END
WHERE media_item_id = media_uuid AND user_id = p_user_id;
ELSE
INSERT INTO reading_progress (
media_item_id,
user_id,
percentage,
character_offset,
epubcfi,
chapter,
chapter_progress,
last_sync_device,
last_sync_source,
last_sync_timestamp,
conflict_detected,
conflict_resolved,
last_read_at,
current_page,
total_pages
) VALUES (
media_uuid,
p_user_id,
(book_record->>'percentage')::FLOAT,
CASE WHEN book_record ? 'character' THEN (book_record->>'character')::BIGINT ELSE NULL END,
CASE WHEN book_record ? 'epubcfi' THEN (book_record->>'epubcfi')::TEXT ELSE NULL END,
CASE WHEN book_record ? 'chapter' THEN (book_record->>'chapter')::INTEGER ELSE NULL END,
(book_record->>'percentage')::FLOAT,
'koreader',
'koreader',
NOW(),
conflict_detected,
NOT conflict_detected,
CASE WHEN book_record ? 'last_read' THEN (book_record->>'last_read')::TIMESTAMP WITH TIME ZONE ELSE NOW() END,
CASE WHEN book_record ? 'page' THEN (book_record->>'page')::INTEGER ELSE NULL END,
CASE WHEN book_record ? 'total_pages' THEN (book_record->>'total_pages')::INTEGER ELSE NULL END
);
END IF;
-- Create conflict record if detected
IF conflict_detected THEN
INSERT INTO sync_conflicts (media_item_id, user_id, conflict_type, conflict_data)
VALUES (media_uuid, p_user_id, 'progress', jsonb_build_object(
'koreader', book_record,
'timestamp', NOW()
));
END IF;
RETURN QUERY SELECT media_uuid, TRUE,
CASE WHEN conflict_detected THEN 'conflict detected' ELSE 'success' END;
END LOOP;
END;
$$ LANGUAGE plpgsql;
$$ LANGUAGE plpgsql;