From 05ffcb312dd22db9d5ad2b6697b804be86fb0b03 Mon Sep 17 00:00:00 2001 From: Joshua Koudys Date: Sun, 26 Jul 2020 22:45:06 -0400 Subject: [PATCH] Uuid support for MySQL (#536) * feat: uuid decoder for mysql, patterned on postgres * feat: Add uuid on mysql encoding * fix: encode after converting to bytes * fix: use the byte decoder on uuids * fix: remove unused import * feat: Adds mysql encoding/decoding support for Hyphenated uuid * fix: uncommented feature flag line * fix: unresolved import * fix: use sqlx string type for binary uuid Co-authored-by: Ian Hume --- sqlx-core/src/mysql/types/mod.rs | 12 +++++++ sqlx-core/src/mysql/types/uuid.rs | 58 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 sqlx-core/src/mysql/types/uuid.rs diff --git a/sqlx-core/src/mysql/types/mod.rs b/sqlx-core/src/mysql/types/mod.rs index 9aa85b2f..fe701cb6 100644 --- a/sqlx-core/src/mysql/types/mod.rs +++ b/sqlx-core/src/mysql/types/mod.rs @@ -55,6 +55,15 @@ //! |---------------------------------------|------------------------------------------------------| //! | `rust_decimal::Decimal` | DECIMAL | //! +//! ### [`uuid`](https://crates.io/crates/uuid) +//! +//! Requires the `uuid` Cargo feature flag. +//! +//! | Rust type | MySQL type(s) | +//! |---------------------------------------|------------------------------------------------------| +//! | `uuid::Uuid` | BYTE(16), VARCHAR, CHAR, TEXT | +//! | `uuid::adapter::Hyphenated` | CHAR(36) | +//! //! ### [`json`](https://crates.io/crates/json) //! //! Requires the `json` Cargo feature flag. @@ -88,5 +97,8 @@ mod chrono; #[cfg(feature = "time")] mod time; +#[cfg(feature = "uuid")] +mod uuid; + #[cfg(feature = "json")] mod json; diff --git a/sqlx-core/src/mysql/types/uuid.rs b/sqlx-core/src/mysql/types/uuid.rs new file mode 100644 index 00000000..3bd72b88 --- /dev/null +++ b/sqlx-core/src/mysql/types/uuid.rs @@ -0,0 +1,58 @@ +use uuid::{adapter::Hyphenated, Uuid}; + +use crate::decode::Decode; +use crate::encode::{Encode, IsNull}; +use crate::error::BoxDynError; +use crate::mysql::io::MySqlBufMutExt; +use crate::mysql::protocol::text::{ColumnFlags, ColumnType}; +use crate::mysql::{MySql, MySqlTypeInfo, MySqlValueRef}; +use crate::types::Type; + +impl Type for Uuid { + fn type_info() -> MySqlTypeInfo { + MySqlTypeInfo::binary(ColumnType::String) + } +} + +impl Encode<'_, MySql> for Uuid { + fn encode_by_ref(&self, buf: &mut Vec) -> IsNull { + buf.put_bytes_lenenc(self.as_bytes()); + + IsNull::No + } +} + +impl Decode<'_, MySql> for Uuid { + fn decode(value: MySqlValueRef<'_>) -> Result { + // delegate to the &[u8] type to decode from MySQL + let bytes = <&[u8] as Decode>::decode(value)?; + + // construct a Uuid from the returned bytes + Uuid::from_slice(bytes).map_err(Into::into) + } +} + +impl Type for Hyphenated { + fn type_info() -> MySqlTypeInfo { + MySqlTypeInfo { + r#type: ColumnType::String, // CHAR + char_set: 224, // utf8mb4_unicode_ci + flags: ColumnFlags::empty(), + } + } +} + +impl Encode<'_, MySql> for Hyphenated { + fn encode_by_ref(&self, buf: &mut Vec) -> IsNull { + buf.put_str_lenenc(&self.to_string()); + + IsNull::No + } +} + +impl Decode<'_, MySql> for Hyphenated { + fn decode(value: MySqlValueRef<'_>) -> Result { + let uuid: Result = Uuid::parse_str(value.as_str()?).map_err(Into::into); + Ok(uuid?.to_hyphenated()) + } +}