diff --git a/sqlx-core/src/sqlite/types/mod.rs b/sqlx-core/src/sqlite/types/mod.rs index 84ca6154..34f32891 100644 --- a/sqlx-core/src/sqlite/types/mod.rs +++ b/sqlx-core/src/sqlite/types/mod.rs @@ -23,6 +23,15 @@ //! | `chrono::DateTime` | DATETIME | //! | `chrono::DateTime` | DATETIME | //! +//! ### [`uuid`](https://crates.io/crates/uuid) +//! +//! Requires the `uuid` Cargo feature flag. +//! +//! | Rust type | Sqlite type(s) | +//! |---------------------------------------|------------------------------------------------------| +//! | `uuid::Uuid` | BLOB, TEXT | +//! | `uuid::adapter::Hyphenated` | TEXT | +//! //! # Nullable //! //! In addition, `Option` is supported where `T` implements `Type`. An `Option` represents @@ -33,6 +42,8 @@ mod bool; mod bytes; #[cfg(feature = "chrono")] mod chrono; +#[cfg(feature = "uuid")] +mod uuid; mod float; mod int; #[cfg(feature = "json")] diff --git a/sqlx-core/src/sqlite/types/uuid.rs b/sqlx-core/src/sqlite/types/uuid.rs new file mode 100644 index 00000000..0de47fdb --- /dev/null +++ b/sqlx-core/src/sqlite/types/uuid.rs @@ -0,0 +1,54 @@ +use uuid::{adapter::Hyphenated, Uuid}; +use std::borrow::Cow; +use crate::decode::Decode; +use crate::encode::{Encode, IsNull}; +use crate::error::BoxDynError; +use crate::sqlite::type_info::DataType; +use crate::sqlite::{Sqlite, SqliteArgumentValue, SqliteTypeInfo, SqliteValueRef}; +use crate::types::Type; + +impl Type for Uuid { + fn type_info() -> SqliteTypeInfo { + SqliteTypeInfo(DataType::Blob) + } + + fn compatible(ty: &SqliteTypeInfo) -> bool { + matches!(ty.0, DataType::Blob | DataType::Text) + } +} + +impl<'q> Encode<'q, Sqlite> for &'q Uuid { + fn encode_by_ref(&self, args: &mut Vec>) -> IsNull { + args.push(SqliteArgumentValue::Blob(Cow::Borrowed(self.as_bytes()))); + + IsNull::No + } +} + +impl Decode<'_, Sqlite> for Uuid { + fn decode(value: SqliteValueRef<'_>) -> Result { + // construct a Uuid from the returned bytes + Uuid::from_slice(value.blob()).map_err(Into::into) + } +} + +impl Type for Hyphenated { + fn type_info() -> SqliteTypeInfo { + SqliteTypeInfo(DataType::Text) + } +} + +impl<'q> Encode<'q, Sqlite> for &'q Hyphenated { + fn encode_by_ref(&self, args: &mut Vec>) -> IsNull { + args.push(SqliteArgumentValue::Text(Cow::Owned(self.to_string()))); + + IsNull::No + } +} + +impl Decode<'_, Sqlite> for Hyphenated { + fn decode(value: SqliteValueRef<'_>) -> Result { + let uuid: Result = Uuid::parse_str(&value.text().map(ToOwned::to_owned)?).map_err(Into::into); + Ok(uuid?.to_hyphenated()) + } +}