use uuid::Uuid; use crate::db::models::{ContactEvidence, NewContactEvidence}; use crate::db::{Db, db_error}; use crate::error::AppResult; pub async fn upsert(db: &Db, input: &NewContactEvidence) -> AppResult { let client = db.client().await?; let row = client .query_one( "WITH inserted AS ( INSERT INTO contact_evidence (contact_id, origin_id, page_url, evidence_text, evidence_hash, confidence) VALUES ($1,$2,$3,$4,$5,$6) ON CONFLICT DO NOTHING RETURNING * ) SELECT * FROM inserted UNION ALL SELECT * FROM contact_evidence WHERE contact_id = $1 AND origin_id = $2 AND page_url = $3 AND COALESCE(evidence_hash, '') = COALESCE($5, '') LIMIT 1", &[ &input.contact_id, &input.origin_id, &input.page_url, &input.evidence_text, &input.evidence_hash, &input.confidence, ], ) .await .map_err(db_error)?; ContactEvidence::from_row(&row).map_err(db_error) } pub async fn list_by_contact(db: &Db, contact_id: Uuid) -> AppResult> { let client = db.client().await?; let rows = client .query( "SELECT * FROM contact_evidence WHERE contact_id = $1 ORDER BY collected_at DESC, id DESC", &[&contact_id], ) .await .map_err(db_error)?; rows.iter() .map(ContactEvidence::from_row) .collect::, _>>() .map_err(db_error) } pub async fn delete(db: &Db, id: Uuid) -> AppResult { let client = db.client().await?; Ok(client .execute("DELETE FROM contact_evidence WHERE id = $1", &[&id]) .await .map_err(db_error)? > 0) }