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)]
28#[allow(clippy::large_enum_variant)]
29pub enum PostgresUpdateValue<
30 'a,
31 V: SQLParam,
32 T,
33 Target: DataType = Any,
34 TargetNull: Nullability = Null,
35> {
36 #[default]
38 Skip,
39 Null,
41 Value(ValueWrapper<'a, V, (T, Target, TargetNull)>),
43}
44
45impl<V: SQLParam, T, Target: DataType, TargetNull: Nullability>
46 PostgresUpdateValue<'_, V, T, Target, TargetNull>
47{
48 pub const fn is_skip(&self) -> bool {
50 matches!(self, Self::Skip)
51 }
52}
53
54impl<'a, T, Target, TargetNull> From<T>
61 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
62where
63 T: TryInto<PostgresValue<'a>>,
64 Target: DataType,
65 TargetNull: Nullability,
66{
67 fn from(value: T) -> Self {
68 let sql = SQL::from(
71 TryInto::<PostgresValue<'a>>::try_into(value).unwrap_or_else(|_| {
72 panic!(
73 "could not convert a `{}` to a PostgreSQL value",
74 core::any::type_name::<T>()
75 )
76 }),
77 );
78 PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, T>::new(sql))
79 }
80}
81
82impl<'a, Target, TargetNull> From<&str>
84 for PostgresUpdateValue<'a, PostgresValue<'a>, String, Target, TargetNull>
85where
86 Target: DataType,
87 TargetNull: Nullability,
88{
89 fn from(value: &str) -> Self {
90 let postgres_value = SQL::param(Cow::Owned(PostgresValue::from(value.to_string())));
91 PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, String>::new(
92 postgres_value,
93 ))
94 }
95}
96
97impl<'a, T, Target, TargetNull> From<Placeholder>
99 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
100where
101 Target: DataType,
102 TargetNull: Nullability,
103{
104 fn from(placeholder: Placeholder) -> Self {
105 let chunk = SQLChunk::Param(Param {
106 placeholder,
107 value: None,
108 });
109 PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, T>::new(
110 core::iter::once(chunk).collect(),
111 ))
112 }
113}
114
115impl<'a, M, N, T, Target, TargetNull> From<TypedPlaceholder<M, N>>
116 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
117where
118 M: DataType,
119 N: Nullability,
120 Target: DataType + Assignable<M>,
121 TargetNull: Nullability + AcceptsNullability<N>,
122{
123 fn from(typed: TypedPlaceholder<M, N>) -> Self {
124 Placeholder::from(typed).into()
125 }
126}
127
128impl<'a, C, T, Target, TargetNull, Actual, ActualNull> From<Excluded<C>>
130 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
131where
132 C: SQLColumnInfo + Expr<'a, PostgresValue<'a>, SQLType = Actual, Nullable = ActualNull>,
133 Target: DataType + Assignable<Actual>,
134 TargetNull: Nullability + AcceptsNullability<ActualNull>,
135 Actual: DataType,
136 ActualNull: Nullability,
137{
138 fn from(excluded: Excluded<C>) -> Self {
139 use drizzle_core::ToSQL;
140 let sql = excluded.to_sql();
141 PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, T>::new(sql))
142 }
143}
144
145#[cfg(feature = "uuid")]
147impl<'a, Target, TargetNull> From<Uuid>
148 for PostgresUpdateValue<'a, PostgresValue<'a>, String, Target, TargetNull>
149where
150 Target: DataType,
151 TargetNull: Nullability,
152{
153 fn from(value: Uuid) -> Self {
154 let postgres_value = PostgresValue::Uuid(value);
155 let sql = SQL::param(postgres_value);
156 PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, String>::new(sql))
157 }
158}
159
160#[cfg(feature = "uuid")]
161impl<'a, Target, TargetNull> From<&'a Uuid>
162 for PostgresUpdateValue<'a, PostgresValue<'a>, String, Target, TargetNull>
163where
164 Target: DataType,
165 TargetNull: Nullability,
166{
167 fn from(value: &'a Uuid) -> Self {
168 let postgres_value = PostgresValue::Uuid(*value);
169 let sql = SQL::param(postgres_value);
170 PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, String>::new(sql))
171 }
172}
173
174impl<'a, T, Target, TargetNull, Actual, ActualNull>
175 From<SQLExpr<'a, PostgresValue<'a>, Actual, ActualNull, Scalar>>
176 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
177where
178 Target: DataType + Assignable<Actual>,
179 TargetNull: Nullability + AcceptsNullability<ActualNull>,
180 Actual: DataType,
181 ActualNull: Nullability,
182{
183 fn from(value: SQLExpr<'a, PostgresValue<'a>, Actual, ActualNull, Scalar>) -> Self {
184 Self::Value(ValueWrapper::<PostgresValue<'a>, T>::new(
185 value.into_expr_sql(),
186 ))
187 }
188}
189
190impl<'a, T, Target, TargetNull, L, R, Op, Actual, ActualNull>
191 From<ColumnBinOp<L, R, Op, PostgresDialect, Actual, ActualNull>>
192 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
193where
194 Target: DataType + Assignable<Actual>,
195 TargetNull: Nullability + AcceptsNullability<ActualNull>,
196 Actual: DataType,
197 ActualNull: Nullability,
198 ColumnBinOp<L, R, Op, PostgresDialect, Actual, ActualNull>: ToSQL<'a, PostgresValue<'a>>,
199{
200 fn from(value: ColumnBinOp<L, R, Op, PostgresDialect, Actual, ActualNull>) -> Self {
201 Self::Value(ValueWrapper::<PostgresValue<'a>, T>::new(value.into_sql()))
202 }
203}
204
205impl<'a, T, Target, TargetNull, E, Actual, ActualNull>
206 From<ColumnNeg<E, PostgresDialect, Actual, ActualNull>>
207 for PostgresUpdateValue<'a, PostgresValue<'a>, T, Target, TargetNull>
208where
209 Target: DataType + Assignable<Actual>,
210 TargetNull: Nullability + AcceptsNullability<ActualNull>,
211 Actual: DataType,
212 ActualNull: Nullability,
213 ColumnNeg<E, PostgresDialect, Actual, ActualNull>: ToSQL<'a, PostgresValue<'a>>,
214{
215 fn from(value: ColumnNeg<E, PostgresDialect, Actual, ActualNull>) -> Self {
216 Self::Value(ValueWrapper::<PostgresValue<'a>, T>::new(value.into_sql()))
217 }
218}