feat(versions): schema and VersionDao for hash-keyed photo versions
photo_versions links a version's content_hash to its primary original's; photo_version_references keeps provenance-only reference photos; photo_version_display holds the global display choice. VersionDao covers linking (chains flatten to the root), the display choice, per-original summaries for /photos, the hidden-row set for non-SQL listings, and the copy of the original's date/GPS/camera onto version rows. Also the SQL predicate listings use to hide a version while its original is reachable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e7aaa961ad
commit
044240037a
5 files changed
+1155
No files matched your search
@@ -0,0 +1,3 @@
|
||||
DROP TABLE IF EXISTS photo_version_display;
|
||||
DROP TABLE IF EXISTS photo_version_references;
|
||||
DROP TABLE IF EXISTS photo_versions;
|
||||
@@ -0,0 +1,41 @@
|
||||
-- Photo versions (#191): an AI restoration, upscale or edit that sits on
|
||||
-- disk near its original and is shown as the *same photo*.
|
||||
--
|
||||
-- The link is hash-keyed like every other derived table (CLAUDE.md →
|
||||
-- "Multi-library data model"): a version records the blake3
|
||||
-- `content_hash` of its primary original, so the link survives moves,
|
||||
-- renames and an archive handoff. File name and location are hints only.
|
||||
-- The version keeps its own `image_exif` row, so it still downloads and
|
||||
-- thumbnails on its own; listings hide it while its original is reachable
|
||||
-- in the current view (same rule as `duplicate_of_hash`).
|
||||
|
||||
-- A file is a version of at most one original.
|
||||
CREATE TABLE photo_versions (
|
||||
version_hash TEXT PRIMARY KEY NOT NULL,
|
||||
original_hash TEXT NOT NULL,
|
||||
kind TEXT NOT NULL, -- restored | upscale | edit
|
||||
source TEXT NOT NULL, -- xmp | name | backfill | api
|
||||
created_at BIGINT NOT NULL,
|
||||
-- Denormalized back-ref to a live image_exif row for the version, kept
|
||||
-- current by the back-ref refresh pass (same pattern as face_detections).
|
||||
library_id INTEGER NOT NULL,
|
||||
rel_path TEXT NOT NULL
|
||||
);
|
||||
CREATE INDEX idx_photo_versions_original ON photo_versions(original_hash);
|
||||
|
||||
-- Reference photos (extra context fed to the model). Provenance only: a
|
||||
-- reference is never hidden or grouped because of the version.
|
||||
CREATE TABLE photo_version_references (
|
||||
version_hash TEXT NOT NULL,
|
||||
reference_hash TEXT NOT NULL,
|
||||
PRIMARY KEY (version_hash, reference_hash)
|
||||
);
|
||||
CREATE INDEX idx_photo_version_references_ref ON photo_version_references(reference_hash);
|
||||
|
||||
-- The global (not per-user) choice of which file represents a photo.
|
||||
-- No row = show the original.
|
||||
CREATE TABLE photo_version_display (
|
||||
original_hash TEXT PRIMARY KEY NOT NULL,
|
||||
display_hash TEXT NOT NULL,
|
||||
decided_at BIGINT NOT NULL
|
||||
);
|
||||
@@ -54,6 +54,7 @@ pub mod reconcile;
|
||||
pub mod schema;
|
||||
pub mod search_dao;
|
||||
pub mod user_ai_prefs_dao;
|
||||
pub mod version_dao;
|
||||
|
||||
pub use calendar_dao::{CalendarEventDao, SqliteCalendarEventDao};
|
||||
pub use daily_summary_dao::{DailySummaryDao, InsertDailySummary, SqliteDailySummaryDao};
|
||||
@@ -71,6 +72,7 @@ pub use precomputed_reel_dao::{PrecomputedReelDao, SqlitePrecomputedReelDao};
|
||||
pub use preview_dao::{PreviewDao, SqlitePreviewDao};
|
||||
pub use search_dao::{SearchHistoryDao, SqliteSearchHistoryDao};
|
||||
pub use user_ai_prefs_dao::{SqliteUserAiPrefsDao, UserAiPrefsDao};
|
||||
pub use version_dao::{SqliteVersionDao, VersionDao};
|
||||
|
||||
pub trait UserDao {
|
||||
fn create_user(&mut self, user: &str, password: &str) -> Option<User>;
|
||||
|
||||
@@ -345,6 +345,33 @@ diesel::table! {
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
photo_version_display (original_hash) {
|
||||
original_hash -> Text,
|
||||
display_hash -> Text,
|
||||
decided_at -> BigInt,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
photo_version_references (version_hash, reference_hash) {
|
||||
version_hash -> Text,
|
||||
reference_hash -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
photo_versions (version_hash) {
|
||||
version_hash -> Text,
|
||||
original_hash -> Text,
|
||||
kind -> Text,
|
||||
source -> Text,
|
||||
created_at -> BigInt,
|
||||
library_id -> Integer,
|
||||
rel_path -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
precomputed_reels (id) {
|
||||
id -> Integer,
|
||||
@@ -392,6 +419,9 @@ diesel::allow_tables_to_appear_in_same_query!(
|
||||
personas,
|
||||
persons,
|
||||
photo_insights,
|
||||
photo_version_display,
|
||||
photo_version_references,
|
||||
photo_versions,
|
||||
precomputed_reels,
|
||||
search_history,
|
||||
tagged_photo,
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user