bl4_idb/
repository.rs

1//! Repository trait for items database operations.
2//!
3//! This trait defines the interface for all database backends.
4
5use crate::types::*;
6use std::collections::HashMap;
7
8/// Error type for repository operations
9#[derive(Debug, thiserror::Error)]
10pub enum RepoError {
11    #[error("Item not found: {0}")]
12    NotFound(String),
13
14    #[error("Database error: {0}")]
15    Database(String),
16
17    #[error("IO error: {0}")]
18    Io(#[from] std::io::Error),
19
20    #[error("Parse error: {0}")]
21    Parse(#[from] ParseError),
22}
23
24/// Result type for repository operations
25pub type RepoResult<T> = Result<T, RepoError>;
26
27/// Trait for items database operations (synchronous version for CLI)
28pub trait ItemsRepository {
29    /// Initialize the database schema
30    fn init(&self) -> RepoResult<()>;
31
32    // === Items CRUD ===
33
34    /// Add a new item with just its serial
35    fn add_item(&self, serial: &str) -> RepoResult<()>;
36
37    /// Get an item by serial
38    fn get_item(&self, serial: &str) -> RepoResult<Option<Item>>;
39
40    /// Update item metadata
41    fn update_item(&self, serial: &str, update: &ItemUpdate) -> RepoResult<()>;
42
43    /// List items with optional filters
44    fn list_items(&self, filter: &ItemFilter) -> RepoResult<Vec<Item>>;
45
46    /// Delete an item
47    fn delete_item(&self, serial: &str) -> RepoResult<bool>;
48
49    // === Verification ===
50
51    /// Set verification status for an item
52    fn set_verification_status(
53        &self,
54        serial: &str,
55        status: VerificationStatus,
56        notes: Option<&str>,
57    ) -> RepoResult<()>;
58
59    /// Set legal status for an item
60    fn set_legal(&self, serial: &str, legal: bool) -> RepoResult<()>;
61
62    /// Set legal status for all items
63    fn set_all_legal(&self, legal: bool) -> RepoResult<usize>;
64
65    // === Metadata ===
66
67    /// Set item type
68    fn set_item_type(&self, serial: &str, item_type: &str) -> RepoResult<()>;
69
70    /// Set source for an item
71    fn set_source(&self, serial: &str, source: &str) -> RepoResult<()>;
72
73    /// Set source for items without one
74    fn set_source_for_null(&self, source: &str) -> RepoResult<usize>;
75
76    /// Set source for items matching a condition (SQL WHERE clause)
77    /// WARNING: condition is inserted directly into SQL - do not use with untrusted input
78    fn set_source_where(&self, source: &str, condition: &str) -> RepoResult<usize>;
79
80    // === Parts ===
81
82    /// Get parts for an item
83    fn get_parts(&self, serial: &str) -> RepoResult<Vec<ItemPart>>;
84
85    // === Multi-source values ===
86
87    /// Set a field value with source attribution
88    fn set_value(
89        &self,
90        serial: &str,
91        field: &str,
92        value: &str,
93        source: ValueSource,
94        source_detail: Option<&str>,
95        confidence: Confidence,
96    ) -> RepoResult<()>;
97
98    /// Get all values for a field across sources
99    fn get_values(&self, serial: &str, field: &str) -> RepoResult<Vec<ItemValue>>;
100
101    /// Get the best value for a field
102    fn get_best_value(&self, serial: &str, field: &str) -> RepoResult<Option<ItemValue>>;
103
104    /// Get all values for an item
105    fn get_all_values(&self, serial: &str) -> RepoResult<Vec<ItemValue>>;
106
107    /// Get best value for each field as a map
108    fn get_best_values(&self, serial: &str) -> RepoResult<HashMap<String, String>>;
109
110    /// Get best values for all items (bulk query)
111    fn get_all_items_best_values(&self) -> RepoResult<HashMap<String, HashMap<String, String>>>;
112
113    // === Statistics ===
114
115    /// Get database statistics
116    fn stats(&self) -> RepoResult<DbStats>;
117
118    // === Migration ===
119
120    /// Migrate column values to item_values table
121    fn migrate_column_values(&self, dry_run: bool) -> RepoResult<MigrationStats>;
122}
123
124/// Extension trait for attachment operations (feature-gated)
125#[cfg(feature = "attachments")]
126pub trait AttachmentsRepository {
127    /// Add an image attachment
128    fn add_attachment(
129        &self,
130        serial: &str,
131        name: &str,
132        mime_type: &str,
133        data: &[u8],
134        view: &str,
135    ) -> RepoResult<i64>;
136
137    /// Get attachments for an item (without data)
138    fn get_attachments(&self, serial: &str) -> RepoResult<Vec<Attachment>>;
139
140    /// Get attachment data by ID
141    fn get_attachment_data(&self, id: i64) -> RepoResult<Option<Vec<u8>>>;
142
143    /// Delete an attachment
144    fn delete_attachment(&self, id: i64) -> RepoResult<bool>;
145}
146
147/// Extension trait for import/export operations
148pub trait ImportExportRepository {
149    /// Import an item from a directory
150    fn import_from_dir(&self, dir: &std::path::Path) -> RepoResult<String>;
151
152    /// Export an item to a directory
153    fn export_to_dir(&self, serial: &str, dir: &std::path::Path) -> RepoResult<()>;
154}
155
156/// Extension trait for bulk operations
157pub trait BulkRepository {
158    /// Add multiple items at once
159    fn add_items_bulk(&self, serials: &[&str]) -> RepoResult<BulkResult>;
160
161    /// Set values for multiple items
162    fn set_values_bulk(&self, values: &[BulkValueSet]) -> RepoResult<BulkResult>;
163}
164
165/// Request for bulk value setting
166#[derive(Debug, Clone)]
167pub struct BulkValueSet {
168    pub serial: String,
169    pub field: String,
170    pub value: String,
171    pub source: ValueSource,
172    pub source_detail: Option<String>,
173    pub confidence: Confidence,
174}
175
176/// Result of a bulk operation
177#[derive(Debug, Clone, Default)]
178pub struct BulkResult {
179    pub succeeded: usize,
180    pub failed: usize,
181    pub errors: Vec<(String, String)>, // (serial, error message)
182}