drizzle_postgres/values/
insert.rs1use super::{OwnedPostgresValue, PostgresValue};
4use drizzle_core::{
5 ToSQL, param::Param, placeholder::Placeholder, sql::SQL, sql::SQLChunk, traits::SQLParam,
6};
7use std::borrow::Cow;
8use std::marker::PhantomData;
9
10#[cfg(feature = "uuid")]
11use uuid::Uuid;
12
13#[derive(Debug, Clone)]
19pub struct ValueWrapper<'a, V: SQLParam, T> {
20 pub value: SQL<'a, V>,
21 pub _phantom: PhantomData<T>,
22}
23
24impl<'a, V: SQLParam, T> ValueWrapper<'a, V, T> {
25 pub const fn new<U>(value: SQL<'a, V>) -> ValueWrapper<'a, V, U> {
26 ValueWrapper {
27 value,
28 _phantom: PhantomData,
29 }
30 }
31}
32
33#[derive(Debug, Clone, Default)]
35#[allow(clippy::large_enum_variant)]
36pub enum PostgresInsertValue<'a, V: SQLParam, T> {
37 #[default]
39 Omit,
40 Null,
42 Value(ValueWrapper<'a, V, T>),
44}
45
46impl<'a, T> PostgresInsertValue<'a, PostgresValue<'a>, T> {
47 pub fn into_owned(self) -> PostgresInsertValue<'static, PostgresValue<'static>, T> {
49 match self {
50 PostgresInsertValue::Omit => PostgresInsertValue::Omit,
51 PostgresInsertValue::Null => PostgresInsertValue::Null,
52 PostgresInsertValue::Value(wrapper) => {
53 if let Some(SQLChunk::Param(param)) = wrapper.value.chunks.first() {
55 if let Some(ref postgres_val) = param.value {
56 let postgres_val = postgres_val.as_ref();
57 let owned_postgres_val = OwnedPostgresValue::from(postgres_val.clone());
58 let static_postgres_val = PostgresValue::from(owned_postgres_val);
59 let static_sql = SQL::param(static_postgres_val);
60 PostgresInsertValue::Value(ValueWrapper::<PostgresValue<'static>, T>::new(
61 static_sql,
62 ))
63 } else {
64 let static_sql = SQL::param(PostgresValue::Null);
66 PostgresInsertValue::Value(ValueWrapper::<PostgresValue<'static>, T>::new(
67 static_sql,
68 ))
69 }
70 } else {
71 let static_sql = SQL::param(PostgresValue::Null);
73 PostgresInsertValue::Value(ValueWrapper::<PostgresValue<'static>, T>::new(
74 static_sql,
75 ))
76 }
77 }
78 }
79 }
80}
81
82impl<'a, T> From<T> for PostgresInsertValue<'a, PostgresValue<'a>, T>
88where
89 T: TryInto<PostgresValue<'a>>,
90{
91 fn from(value: T) -> Self {
92 let sql = value
93 .try_into()
94 .map(|v: PostgresValue<'a>| SQL::from(v))
95 .unwrap_or_else(|_| SQL::from(PostgresValue::Null));
96 PostgresInsertValue::Value(ValueWrapper::<PostgresValue<'a>, T>::new(sql))
97 }
98}
99
100impl<'a> From<&str> for PostgresInsertValue<'a, PostgresValue<'a>, String> {
102 fn from(value: &str) -> Self {
103 let postgres_value = SQL::param(Cow::Owned(PostgresValue::from(value.to_string())));
104 PostgresInsertValue::Value(ValueWrapper::<PostgresValue<'a>, String>::new(
105 postgres_value,
106 ))
107 }
108}
109
110impl<'a, T> From<Placeholder> for PostgresInsertValue<'a, PostgresValue<'a>, T> {
112 fn from(placeholder: Placeholder) -> Self {
113 let chunk = SQLChunk::Param(Param {
114 placeholder,
115 value: None,
116 });
117 PostgresInsertValue::Value(ValueWrapper::<PostgresValue<'a>, T>::new(
118 std::iter::once(chunk).collect(),
119 ))
120 }
121}
122
123impl<'a, T> From<Option<T>> for PostgresInsertValue<'a, PostgresValue<'a>, T>
125where
126 T: ToSQL<'a, PostgresValue<'a>>,
127{
128 fn from(value: Option<T>) -> Self {
129 match value {
130 Some(v) => {
131 let sql = v.to_sql();
132 PostgresInsertValue::Value(ValueWrapper::<PostgresValue<'a>, T>::new(sql))
133 }
134 None => PostgresInsertValue::Omit,
135 }
136 }
137}
138
139#[cfg(feature = "uuid")]
141impl<'a> From<Uuid> for PostgresInsertValue<'a, PostgresValue<'a>, String> {
142 fn from(value: Uuid) -> Self {
143 let postgres_value = PostgresValue::Uuid(value);
144 let sql = SQL::param(postgres_value);
145 PostgresInsertValue::Value(ValueWrapper::<PostgresValue<'a>, String>::new(sql))
146 }
147}
148
149#[cfg(feature = "uuid")]
150impl<'a> From<&'a Uuid> for PostgresInsertValue<'a, PostgresValue<'a>, String> {
151 fn from(value: &'a Uuid) -> Self {
152 let postgres_value = PostgresValue::Uuid(*value);
153 let sql = SQL::param(postgres_value);
154 PostgresInsertValue::Value(ValueWrapper::<PostgresValue<'a>, String>::new(sql))
155 }
156}