summaryrefslogtreecommitdiff
path: root/src/db/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/db/mod.rs')
-rw-r--r--src/db/mod.rs30
1 files changed, 30 insertions, 0 deletions
diff --git a/src/db/mod.rs b/src/db/mod.rs
index fa3d74e..6005813 100644
--- a/src/db/mod.rs
+++ b/src/db/mod.rs
@@ -4,6 +4,7 @@ use std::str::FromStr;
use hex_literal::hex;
use sqlx::{
+ error::{DatabaseError, ErrorKind},
migrate::{Migrate as _, MigrateDatabase as _},
sqlite::{Sqlite, SqliteConnectOptions, SqlitePool, SqlitePoolOptions},
};
@@ -161,3 +162,32 @@ impl<T> NotFound for Result<T, sqlx::Error> {
self.optional()?.ok_or_else(map)
}
}
+
+pub trait Duplicate {
+ type Ok;
+ type Error;
+
+ fn duplicate<E, F>(self, map: F) -> Result<Self::Ok, E>
+ where
+ E: From<Self::Error>,
+ F: FnOnce() -> E;
+}
+
+impl<T> Duplicate for Result<T, sqlx::Error> {
+ type Ok = T;
+ type Error = sqlx::Error;
+
+ fn duplicate<E, F>(self, map: F) -> Result<T, E>
+ where
+ E: From<sqlx::Error>,
+ F: FnOnce() -> E,
+ {
+ match self {
+ Ok(value) => Ok(value),
+ Err(error) => match error.as_database_error().map(DatabaseError::kind) {
+ Some(ErrorKind::UniqueViolation) => Err(map()),
+ _ => Err(error.into()),
+ },
+ }
+ }
+}