1use super::PostgresValue;
7use super::insert::ValueWrapper;
8use crate::prelude::*;
9use crate::types::Any;
10use drizzle_core::expr::{
11 AcceptsNullability, ColumnBinOp, ColumnNeg, Excluded, Expr, Null, Nullability, SQLExpr, Scalar,
12};
13use drizzle_core::{
14 PostgresDialect, SQLColumnInfo, ToSQL, TypedPlaceholder,
15 param::Param,
16 placeholder::Placeholder,
17 sql::SQL,
18 sql::SQLChunk,
19 traits::SQLParam,
20 types::{Assignable, DataType},
21};
22
23#[cfg(feature = "uuid")]
24use uuid::Uuid;
25
26#[derive(Debug, Clone, Default)]
32#[allow(clippy::large_enum_variant)]
33pub enum PostgresUpdateValue<
34 'a,
35 V: SQLParam,
36 T,
37 Target: DataType = Any,
38 TargetNull: Nullability = Null,
39> {
40 #[default]
42 Skip,
43 Null,
45 Value(ValueWrapper<'a, V, (T, Target, TargetNull)>),
47}
48
49impl<V: SQLParam, T, Target: DataType, TargetNull: Nullability>
50 PostgresUpdateValue<'_, V, T, Target, TargetNull>
51{
52 pub const fn is_skip(&self) -> bool {
54 matches!(self, Self::Skip)
55 }
56}
57
58impl<'a, T, Target, TargetNull> From<T>
65 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
66where
67 T: TryInto<PostgresValue<'a>>,
68 Target: DataType,
69 TargetNull: Nullability,
70{
71 fn from(value: T) -> Self {
72 let sql = SQL::from(
75 TryInto::<PostgresValue<'a>>::try_into(value).unwrap_or_else(|_| {
76 panic!(
77 "could not convert a `{}` to a PostgreSQL value",
78 core::any::type_name::<T>()
79 )
80 }),
81 );
82 PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, T>::new(sql))
83 }
84}
85
86impl<'a, Target, TargetNull> From<&str>
88 for PostgresUpdateValue<'a, PostgresValue<'a>, String, Target, TargetNull>
89where
90 Target: DataType,
91 TargetNull: Nullability,
92{
93 fn from(value: &str) -> Self {
94 let postgres_value = SQL::param(Cow::Owned(PostgresValue::from(value.to_string())));
95 PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, String>::new(
96 postgres_value,
97 ))
98 }
99}
100
101impl<'a, T, Target, TargetNull> From<Placeholder>
103 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
104where
105 Target: DataType,
106 TargetNull: Nullability,
107{
108 fn from(placeholder: Placeholder) -> Self {
109 let chunk = SQLChunk::Param(Param {
110 placeholder,
111 value: None,
112 });
113 PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, T>::new(
114 core::iter::once(chunk).collect(),
115 ))
116 }
117}
118
119impl<'a, M, N, T, Target, TargetNull> From<TypedPlaceholder<M, N>>
120 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
121where
122 M: DataType,
123 N: Nullability,
124 Target: DataType + Assignable<M>,
125 TargetNull: Nullability + AcceptsNullability<N>,
126{
127 fn from(typed: TypedPlaceholder<M, N>) -> Self {
128 Placeholder::from(typed).into()
129 }
130}
131
132impl<'a, C, T, Target, TargetNull, Actual, ActualNull> From<Excluded<C>>
134 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
135where
136 C: SQLColumnInfo + Expr<'a, PostgresValue<'a>, SQLType = Actual, Nullable = ActualNull>,
137 Target: DataType + Assignable<Actual>,
138 TargetNull: Nullability + AcceptsNullability<ActualNull>,
139 Actual: DataType,
140 ActualNull: Nullability,
141{
142 fn from(excluded: Excluded<C>) -> Self {
143 use drizzle_core::ToSQL;
144 let sql = excluded.to_sql();
145 PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, T>::new(sql))
146 }
147}
148
149#[cfg(feature = "uuid")]
151impl<'a, Target, TargetNull> From<Uuid>
152 for PostgresUpdateValue<'a, PostgresValue<'a>, String, Target, TargetNull>
153where
154 Target: DataType,
155 TargetNull: Nullability,
156{
157 fn from(value: Uuid) -> Self {
158 let postgres_value = PostgresValue::Uuid(value);
159 let sql = SQL::param(postgres_value);
160 PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, String>::new(sql))
161 }
162}
163
164#[cfg(feature = "uuid")]
165impl<'a, Target, TargetNull> From<&'a Uuid>
166 for PostgresUpdateValue<'a, PostgresValue<'a>, String, Target, TargetNull>
167where
168 Target: DataType,
169 TargetNull: Nullability,
170{
171 fn from(value: &'a Uuid) -> Self {
172 let postgres_value = PostgresValue::Uuid(*value);
173 let sql = SQL::param(postgres_value);
174 PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, String>::new(sql))
175 }
176}
177
178impl<'a, T, Target, TargetNull, Actual, ActualNull, Sources>
179 From<SQLExpr<'a, PostgresValue<'a>, Actual, ActualNull, Scalar, Sources>>
180 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
181where
182 Target: DataType + Assignable<Actual>,
183 TargetNull: Nullability + AcceptsNullability<ActualNull>,
184 Actual: DataType,
185 ActualNull: Nullability,
186{
187 fn from(value: SQLExpr<'a, PostgresValue<'a>, Actual, ActualNull, Scalar, Sources>) -> Self {
188 Self::Value(ValueWrapper::<PostgresValue<'a>, T>::new(
189 value.into_expr_sql(),
190 ))
191 }
192}
193
194impl<'a, T, Target, TargetNull, L, R, Op, Actual, ActualNull>
195 From<ColumnBinOp<L, R, Op, PostgresDialect, Actual, ActualNull>>
196 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
197where
198 Target: DataType + Assignable<Actual>,
199 TargetNull: Nullability + AcceptsNullability<ActualNull>,
200 Actual: DataType,
201 ActualNull: Nullability,
202 ColumnBinOp<L, R, Op, PostgresDialect, Actual, ActualNull>: ToSQL<'a, PostgresValue<'a>>,
203{
204 fn from(value: ColumnBinOp<L, R, Op, PostgresDialect, Actual, ActualNull>) -> Self {
205 Self::Value(ValueWrapper::<PostgresValue<'a>, T>::new(value.into_sql()))
206 }
207}
208
209impl<'a, T, Target, TargetNull, E, Actual, ActualNull>
210 From<ColumnNeg<E, PostgresDialect, Actual, ActualNull>>
211 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
212where
213 Target: DataType + Assignable<Actual>,
214 TargetNull: Nullability + AcceptsNullability<ActualNull>,
215 Actual: DataType,
216 ActualNull: Nullability,
217 ColumnNeg<E, PostgresDialect, Actual, ActualNull>: ToSQL<'a, PostgresValue<'a>>,
218{
219 fn from(value: ColumnNeg<E, PostgresDialect, Actual, ActualNull>) -> Self {
220 Self::Value(ValueWrapper::<PostgresValue<'a>, T>::new(value.into_sql()))
221 }
222}