treewide: move migration logic into pinakes-migrations crate

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I98b8ed2eee464ecfd42f492dec49adeb6a6a6964
This commit is contained in:
raf 2026-05-20 17:01:03 +03:00
commit 9f9aa80265
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
43 changed files with 76 additions and 31 deletions

View file

@ -29,7 +29,7 @@ deadpool-postgres = { workspace = true }
postgres-types = { workspace = true }
postgres-native-tls = { workspace = true }
native-tls = { workspace = true }
refinery = { workspace = true }
pinakes-migrations = { workspace = true }
walkdir = { workspace = true }
notify = { workspace = true }
winnow = { workspace = true }

View file

@ -1,28 +1,17 @@
use crate::error::{PinakesError, Result};
mod sqlite_migrations {
use refinery::embed_migrations;
embed_migrations!("../../migrations/sqlite");
}
mod postgres_migrations {
use refinery::embed_migrations;
embed_migrations!("../../migrations/postgres");
}
pub fn run_sqlite_migrations(conn: &mut rusqlite::Connection) -> Result<()> {
sqlite_migrations::migrations::runner()
.run(conn)
.map_err(|e| PinakesError::Migration(e.to_string()))?;
Ok(())
pinakes_migrations::sqlite_migrations()
.to_latest(conn)
.map_err(|e| PinakesError::Migration(e.to_string()))
}
pub async fn run_postgres_migrations(
client: &mut tokio_postgres::Client,
) -> Result<()> {
postgres_migrations::migrations::runner()
pinakes_migrations::postgres_runner()
.run_async(client)
.await
.map_err(|e| PinakesError::Migration(e.to_string()))?;
Ok(())
.map(|_| ())
.map_err(|e| PinakesError::Migration(e.to_string()))
}

View file

@ -1082,8 +1082,8 @@ impl StorageBackend for SqliteBackend {
.map_err(|e| PinakesError::Database(e.to_string()))?;
let count: u64 =
db.query_row("SELECT COUNT(*) FROM media_items", [], |row| {
row.get(0)
})?;
row.get::<_, i64>(0)
})?.cast_unsigned();
db.execute("DELETE FROM media_items", [])?;
count
};
@ -2441,12 +2441,12 @@ impl StorageBackend for SqliteBackend {
.map_err(|e| PinakesError::Database(e.to_string()))?;
let total_media: u64 =
db.query_row("SELECT COUNT(*) FROM media_items", [], |r| r.get(0))?;
db.query_row("SELECT COUNT(*) FROM media_items", [], |r| r.get::<_, i64>(0))?.cast_unsigned();
let total_size: u64 = db.query_row(
"SELECT COALESCE(SUM(file_size), 0) FROM media_items",
[],
|r| r.get(0),
)?;
|r| r.get::<_, i64>(0),
)?.cast_unsigned();
let avg_size: u64 = total_size.checked_div(total_media).unwrap_or(0);
// Media count by type
@ -2455,7 +2455,7 @@ impl StorageBackend for SqliteBackend {
ORDER BY COUNT(*) DESC",
)?;
let media_by_type: Vec<(String, u64)> = stmt
.query_map([], |r| Ok((r.get::<_, String>(0)?, r.get::<_, u64>(1)?)))?
.query_map([], |r| Ok((r.get::<_, String>(0)?, r.get::<_, i64>(1)?.cast_unsigned())))?
.filter_map(std::result::Result::ok)
.collect();
@ -2465,7 +2465,7 @@ impl StorageBackend for SqliteBackend {
GROUP BY media_type ORDER BY SUM(file_size) DESC",
)?;
let storage_by_type: Vec<(String, u64)> = stmt
.query_map([], |r| Ok((r.get::<_, String>(0)?, r.get::<_, u64>(1)?)))?
.query_map([], |r| Ok((r.get::<_, String>(0)?, r.get::<_, i64>(1)?.cast_unsigned())))?
.filter_map(std::result::Result::ok)
.collect();
@ -2491,7 +2491,7 @@ impl StorageBackend for SqliteBackend {
mt.tag_id = t.id GROUP BY t.id ORDER BY cnt DESC LIMIT 10",
)?;
let top_tags: Vec<(String, u64)> = stmt
.query_map([], |r| Ok((r.get::<_, String>(0)?, r.get::<_, u64>(1)?)))?
.query_map([], |r| Ok((r.get::<_, String>(0)?, r.get::<_, i64>(1)?.cast_unsigned())))?
.filter_map(std::result::Result::ok)
.collect();
@ -2502,22 +2502,22 @@ impl StorageBackend for SqliteBackend {
DESC LIMIT 10",
)?;
let top_collections: Vec<(String, u64)> = stmt
.query_map([], |r| Ok((r.get::<_, String>(0)?, r.get::<_, u64>(1)?)))?
.query_map([], |r| Ok((r.get::<_, String>(0)?, r.get::<_, i64>(1)?.cast_unsigned())))?
.filter_map(std::result::Result::ok)
.collect();
let total_tags: u64 =
db.query_row("SELECT COUNT(*) FROM tags", [], |r| r.get(0))?;
db.query_row("SELECT COUNT(*) FROM tags", [], |r| r.get::<_, i64>(0))?.cast_unsigned();
let total_collections: u64 =
db.query_row("SELECT COUNT(*) FROM collections", [], |r| r.get(0))?;
db.query_row("SELECT COUNT(*) FROM collections", [], |r| r.get::<_, i64>(0))?.cast_unsigned();
// Duplicates: count of hashes that appear more than once
let total_duplicates: u64 = db.query_row(
"SELECT COUNT(*) FROM (SELECT content_hash FROM media_items GROUP BY \
content_hash HAVING COUNT(*) > 1)",
[],
|r| r.get(0),
)?;
|r| r.get::<_, i64>(0),
)?.cast_unsigned();
Ok(super::LibraryStatistics {
total_media,

View file

@ -0,0 +1,14 @@
[package]
name = "pinakes-migrations"
edition.workspace = true
version.workspace = true
license.workspace = true
[dependencies]
rusqlite = { workspace = true }
tokio-postgres = { workspace = true }
rusqlite_migration = { workspace = true }
refinery = { workspace = true }
[lints]
workspace = true

View file

@ -0,0 +1,42 @@
use rusqlite_migration::{M, Migrations};
mod postgres_migrations {
use refinery::embed_migrations;
embed_migrations!("migrations/postgres");
}
pub fn sqlite_migrations() -> Migrations<'static> {
Migrations::new(vec![
M::up(include_str!("../migrations/sqlite/V1__initial_schema.sql")),
M::up(include_str!("../migrations/sqlite/V2__fts5_indexes.sql")),
M::up(include_str!("../migrations/sqlite/V3__audit_indexes.sql")),
M::up(include_str!("../migrations/sqlite/V4__thumbnail_path.sql")),
M::up(include_str!(
"../migrations/sqlite/V5__integrity_and_saved_searches.sql"
)),
M::up(include_str!("../migrations/sqlite/V6__plugin_system.sql")),
M::up(include_str!("../migrations/sqlite/V7__user_management.sql")),
M::up(include_str!(
"../migrations/sqlite/V8__media_server_features.sql"
)),
M::up(include_str!(
"../migrations/sqlite/V9__fix_indexes_and_constraints.sql"
)),
M::up(include_str!("../migrations/sqlite/V10__incremental_scan.sql")),
M::up(include_str!(
"../migrations/sqlite/V11__session_persistence.sql"
)),
M::up(include_str!("../migrations/sqlite/V12__book_management.sql")),
M::up(include_str!("../migrations/sqlite/V13__photo_metadata.sql")),
M::up(include_str!("../migrations/sqlite/V14__perceptual_hash.sql")),
M::up(include_str!("../migrations/sqlite/V15__managed_storage.sql")),
M::up(include_str!("../migrations/sqlite/V16__sync_system.sql")),
M::up(include_str!("../migrations/sqlite/V17__enhanced_sharing.sql")),
M::up(include_str!("../migrations/sqlite/V18__file_management.sql")),
M::up(include_str!("../migrations/sqlite/V19__markdown_links.sql")),
])
}
pub fn postgres_runner() -> refinery::Runner {
postgres_migrations::migrations::runner()
}