Skip to main content

drizzle_postgres/values/
update.rs

1//! Update value types for PostgreSQL
2//!
3//! Mirrors the `PostgresInsertValue` pattern but simplified for UPDATE operations.
4//! All UPDATE fields are optional (Skip = don't include in SET clause).
5
6use super::PostgresValue;
7use super::insert::ValueWrapper;
8use drizzle_core::{
9    param::Param, placeholder::Placeholder, sql::SQL, sql::SQLChunk, traits::SQLParam,
10};
11use std::borrow::Cow;
12
13#[cfg(feature = "uuid")]
14use uuid::Uuid;
15
16/// Represents a value for UPDATE operations that can be skipped, null, or a SQL expression.
17#[derive(Debug, Clone, Default)]
18#[allow(clippy::large_enum_variant)]
19pub enum PostgresUpdateValue<'a, V: SQLParam, T> {
20    /// Don't include this column in the SET clause
21    #[default]
22    Skip,
23    /// Explicitly set column = NULL
24    Null,
25    /// Set column to a SQL expression (value, placeholder, etc.)
26    Value(ValueWrapper<'a, V, T>),
27}
28
29impl<'a, V: SQLParam, T> PostgresUpdateValue<'a, V, T> {
30    /// Returns true if this is `Skip`
31    pub fn is_skip(&self) -> bool {
32        matches!(self, Self::Skip)
33    }
34}
35
36// Generic conversion from any type T to UpdateValue
37impl<'a, T> From<T> for PostgresUpdateValue<'a, PostgresValue<'a>, T>
38where
39    T: TryInto<PostgresValue<'a>>,
40{
41    fn from(value: T) -> Self {
42        let sql = value
43            .try_into()
44            .map(|v: PostgresValue<'a>| SQL::from(v))
45            .unwrap_or_else(|_| SQL::from(PostgresValue::Null));
46        PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, T>::new(sql))
47    }
48}
49
50// Specific conversion for &str to String UpdateValue
51impl<'a> From<&str> for PostgresUpdateValue<'a, PostgresValue<'a>, String> {
52    fn from(value: &str) -> Self {
53        let postgres_value = SQL::param(Cow::Owned(PostgresValue::from(value.to_string())));
54        PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, String>::new(
55            postgres_value,
56        ))
57    }
58}
59
60// Placeholder conversion
61impl<'a, T> From<Placeholder> for PostgresUpdateValue<'a, PostgresValue<'a>, T> {
62    fn from(placeholder: Placeholder) -> Self {
63        let chunk = SQLChunk::Param(Param {
64            placeholder,
65            value: None,
66        });
67        PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, T>::new(
68            std::iter::once(chunk).collect(),
69        ))
70    }
71}
72
73// UUID conversion for String UpdateValue (for text columns)
74#[cfg(feature = "uuid")]
75impl<'a> From<Uuid> for PostgresUpdateValue<'a, PostgresValue<'a>, String> {
76    fn from(value: Uuid) -> Self {
77        let postgres_value = PostgresValue::Uuid(value);
78        let sql = SQL::param(postgres_value);
79        PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, String>::new(sql))
80    }
81}
82
83#[cfg(feature = "uuid")]
84impl<'a> From<&'a Uuid> for PostgresUpdateValue<'a, PostgresValue<'a>, String> {
85    fn from(value: &'a Uuid) -> Self {
86        let postgres_value = PostgresValue::Uuid(*value);
87        let sql = SQL::param(postgres_value);
88        PostgresUpdateValue::Value(ValueWrapper::<PostgresValue<'a>, String>::new(sql))
89    }
90}