Skip to content

Commit

Permalink
doc(mysql): document difference between Uuid and `uuid::fmt::Hyphen…
Browse files Browse the repository at this point in the history
…ated`
  • Loading branch information
abonander committed Oct 28, 2024
1 parent 028084b commit 3f7c6ca
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 3 deletions.
30 changes: 27 additions & 3 deletions sqlx-mysql/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,33 @@
//!
//! | Rust type | MySQL/MariaDB type(s) |
//! |---------------------------------------|------------------------------------------------------|
//! | `uuid::Uuid` | BINARY(16), VARCHAR, CHAR, TEXT |
//! | `uuid::fmt::Hyphenated` | CHAR(36), UUID (MariaDB-only) |
//! | `uuid::fmt::Simple` | CHAR(32) |
//! | `uuid::Uuid` | BINARY(16) (see note) |
//! | `uuid::fmt::Hyphenated` | CHAR(36), VARCHAR, TEXT, UUID (MariaDB-only) |
//! | `uuid::fmt::Simple` | CHAR(32), VARCHAR, TEXT |
//!
//! #### Note: `Uuid` uses binary format
//!
//! MySQL does not have a native datatype for UUIDs.
//! The `UUID()` function returns a 36-character `TEXT` value,
//! which encourages storing UUIDs as text.
//!
//! MariaDB's `UUID` type stores and retrieves as text, though it has a better representation
//! for index sorting (see [MariaDB manual: UUID data-type][mariadb-uuid] for details).
//!
//! As an opinionated library, SQLx chose to map `Uuid` to/from binary format by default
//! (16 bytes, the raw value of a UUID; SQL type `BINARY(16)`).
//! This saves 20 bytes over the text format for each value.
//!
//! The `impl Decode<MySql> for Uuid` does not support the text format, and will return an error.
//!
//! If you want to use the text format compatible with the `UUID()` function,
//! use [`uuid::fmt::Hyphenated`][::uuid::fmt::Hyphenated] in the place of `Uuid`.
//!
//! The MySQL official blog has an article showing how to support both binary and text format UUIDs
//! by storing the binary and adding a generated column for the text format, though this is rather
//! verbose and fiddly: <https://dev.mysql.com/blog-archive/storing-uuid-values-in-mysql-tables/>
//!
//! [mariadb-uuid]: https://mariadb.com/kb/en/uuid-data-type/
//!
//! ### [`json`](https://crates.io/crates/serde_json)
//!
Expand Down
9 changes: 9 additions & 0 deletions sqlx-mysql/src/types/uuid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ impl Decode<'_, MySql> for Uuid {
// delegate to the &[u8] type to decode from MySQL
let bytes = <&[u8] as Decode<MySql>>::decode(value)?;

if bytes.len() != 16 {
return Err(format!(
"Expected 16 bytes, got {}; `Uuid` uses binary format for MySQL/MariaDB. \
For text-formatted UUIDs, use `uuid::fmt::Hyphenated` instead of `Uuid`.",
bytes.len(),
)
.into());
}

// construct a Uuid from the returned bytes
Uuid::from_slice(bytes).map_err(Into::into)
}
Expand Down

0 comments on commit 3f7c6ca

Please sign in to comment.