Skip to main content

drizzle_mysql/values/
insert.rs

1//! The field type of generated `MySQL` insert models.
2
3use super::MySQLValue;
4use crate::prelude::*;
5use core::marker::PhantomData;
6use drizzle_core::{
7    SQL, SQLChunk, SQLParam, ToSQL, TypedPlaceholder, param::Param, placeholder::Placeholder,
8};
9
10/// A typed SQL fragment stored in an insert or update field.
11#[doc(hidden)]
12#[derive(Debug, Clone)]
13pub struct ValueWrapper<'a, V: SQLParam, T> {
14    pub value: SQL<'a, V>,
15    pub _phantom: PhantomData<T>,
16}
17
18impl<'a, V: SQLParam, T> ValueWrapper<'a, V, T> {
19    pub const fn new<U>(value: SQL<'a, V>) -> ValueWrapper<'a, V, U> {
20        ValueWrapper {
21            value,
22            _phantom: PhantomData,
23        }
24    }
25}
26
27/// One field of a generated insert model: left out, `NULL`, or a value.
28///
29/// You rarely build this directly. The `with_*` setters and `new` on a
30/// generated `InsertX` model convert their arguments into it.
31#[derive(Debug, Clone, Default)]
32#[allow(clippy::large_enum_variant)]
33pub enum MySQLInsertValue<'a, V: SQLParam, T> {
34    /// Leave the column out of the INSERT so the database default applies.
35    #[default]
36    Omit,
37    /// Insert SQL `NULL`.
38    Null,
39    /// Insert a value, placeholder, or typed SQL expression.
40    Value(ValueWrapper<'a, V, T>),
41}
42
43impl<'a, T> MySQLInsertValue<'a, MySQLValue<'a>, T> {
44    /// Converts this field to a `'static` form that owns its data.
45    #[must_use]
46    pub fn into_owned(self) -> MySQLInsertValue<'static, MySQLValue<'static>, T> {
47        match self {
48            Self::Omit => MySQLInsertValue::Omit,
49            Self::Null => MySQLInsertValue::Null,
50            Self::Value(wrapper) => {
51                MySQLInsertValue::Value(ValueWrapper::<MySQLValue<'static>, T>::new(
52                    wrapper
53                        .value
54                        .into_owned_with(|value| MySQLValue::from(value.into_owned())),
55                ))
56            }
57        }
58    }
59}
60
61impl<'a, T> From<T> for MySQLInsertValue<'a, MySQLValue<'a>, T>
62where
63    T: Into<MySQLValue<'a>>,
64{
65    fn from(value: T) -> Self {
66        let sql = SQL::param(value.into());
67        Self::Value(ValueWrapper::<MySQLValue<'a>, T>::new(sql))
68    }
69}
70
71impl<'a> From<&str> for MySQLInsertValue<'a, MySQLValue<'a>, String> {
72    fn from(value: &str) -> Self {
73        Self::Value(ValueWrapper::<MySQLValue<'a>, String>::new(SQL::param(
74            MySQLValue::from(String::from(value)),
75        )))
76    }
77}
78
79impl<'a, T> From<Placeholder> for MySQLInsertValue<'a, MySQLValue<'a>, T> {
80    fn from(placeholder: Placeholder) -> Self {
81        Self::Value(ValueWrapper::<MySQLValue<'a>, T>::new(
82            core::iter::once(SQLChunk::Param(Param {
83                placeholder,
84                value: None,
85            }))
86            .collect(),
87        ))
88    }
89}
90
91impl<'a, M, N, T> From<TypedPlaceholder<M, N>> for MySQLInsertValue<'a, MySQLValue<'a>, T>
92where
93    M: drizzle_core::types::DataType,
94    N: drizzle_core::expr::Nullability,
95{
96    fn from(value: TypedPlaceholder<M, N>) -> Self {
97        Placeholder::from(value).into()
98    }
99}
100
101impl<'a, T> From<Option<T>> for MySQLInsertValue<'a, MySQLValue<'a>, T>
102where
103    T: ToSQL<'a, MySQLValue<'a>>,
104{
105    fn from(value: Option<T>) -> Self {
106        value.map_or(Self::Omit, |value| {
107            Self::Value(ValueWrapper::<MySQLValue<'a>, T>::new(value.to_sql()))
108        })
109    }
110}