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:
+1
-120
@@ -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;
|
||||
Reference in New Issue
Block a user