Skip to main content

sea_orm/value/
text_uuid.rs

1use std::ops::{Deref, DerefMut};
2
3use sea_query::{ValueType, ValueTypeErr};
4
5use crate::TryGetable;
6use crate::{self as sea_orm, TryFromU64};
7use crate::{DbErr, TryGetError};
8
9/// Newtype making sure that UUIDs will be stored as `TEXT` columns,
10/// instead of `BLOB` (which is the default).
11/// Advantages:
12/// - TEXT makes it easier to interact with the SQLite DB directly
13/// - Allows for queries like `WHERE id IN (<uuid>, <uuid>, ...)` which are
14///   impossible to write with `BLOB` values
15#[derive(Clone, Debug, PartialEq, Eq, Copy)]
16pub struct TextUuid(pub uuid::Uuid);
17
18impl From<TextUuid> for sea_query::Value {
19    fn from(value: TextUuid) -> Self {
20        value.0.to_string().into()
21    }
22}
23
24impl TryGetable for TextUuid {
25    fn try_get_by<I: sea_orm::ColIdx>(
26        res: &sea_orm::QueryResult,
27        index: I,
28    ) -> Result<Self, sea_orm::TryGetError> {
29        let uuid_str: String = res.try_get_by(index)?;
30        let uuid = uuid::Uuid::parse_str(&uuid_str).map_err(|e| {
31            TryGetError::DbErr(DbErr::Type(format!("Failed to parse string as UUID: {e}")))
32        })?;
33        Ok(TextUuid(uuid))
34    }
35}
36
37impl ValueType for TextUuid {
38    fn try_from(v: sea_orm::Value) -> Result<Self, ValueTypeErr> {
39        match v {
40            sea_orm::Value::String(Some(s)) => {
41                let uuid = uuid::Uuid::parse_str(&s).map_err(|_| ValueTypeErr)?;
42                Ok(TextUuid(uuid))
43            }
44            _ => Err(ValueTypeErr),
45        }
46    }
47
48    fn type_name() -> String {
49        "TextUuid".to_string()
50    }
51
52    fn array_type() -> sea_query::ArrayType {
53        <String as sea_query::ValueType>::array_type()
54    }
55
56    fn column_type() -> sea_orm::ColumnType {
57        <String as sea_query::ValueType>::column_type()
58    }
59}
60
61// This seems to be required when using TextUuid as a primary key
62impl TryFromU64 for TextUuid {
63    fn try_from_u64(_n: u64) -> Result<Self, sea_orm::DbErr> {
64        Err(sea_orm::DbErr::ConvertFromU64("TextUuid"))
65    }
66}
67
68impl sea_query::Nullable for TextUuid {
69    fn null() -> sea_orm::Value {
70        <String as sea_query::Nullable>::null()
71    }
72}
73
74impl sea_orm::IntoActiveValue<TextUuid> for TextUuid {
75    fn into_active_value(self) -> crate::ActiveValue<TextUuid> {
76        sea_orm::ActiveValue::Set(self)
77    }
78}
79
80impl Deref for TextUuid {
81    type Target = uuid::Uuid;
82
83    fn deref(&self) -> &uuid::Uuid {
84        &self.0
85    }
86}
87
88impl DerefMut for TextUuid {
89    fn deref_mut(&mut self) -> &mut uuid::Uuid {
90        &mut self.0
91    }
92}
93
94impl From<uuid::Uuid> for TextUuid {
95    fn from(value: uuid::Uuid) -> Self {
96        TextUuid(value)
97    }
98}
99
100impl From<TextUuid> for uuid::Uuid {
101    fn from(value: TextUuid) -> Self {
102        value.0
103    }
104}