dynamodb_expression/update/
delete.rs

1use core::fmt::{self, Write};
2
3use crate::{
4    path::Path,
5    value::{self, ValueOrRef},
6};
7
8use super::Update;
9
10/// Represents a [`DELETE` statement for an update expression][1], for removing
11/// one or more items from a value that is a [set][2].
12///
13/// Prefer [`Path::delete`] over this.
14///
15/// See also: [`Update`]
16///
17/// [1]: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.DELETE
18/// [2]: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes.SetTypes
19/// [`Update`]: crate::update::Update
20#[must_use = "Use in an update expression with `Update::from(delete)`"]
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct Delete {
23    pub(crate) actions: Vec<DeleteAction>,
24}
25
26impl Delete {
27    /// Creates a [`Delete`] for the specified [`Path`] and items in that [set][1].
28    ///
29    /// Prefer [`Path::delete`] over this.
30    ///
31    /// [1]: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes.SetTypes
32    pub fn new<P, S>(path: P, subset: S) -> Self
33    where
34        P: Into<Path>,
35        S: Into<value::Set>,
36    {
37        Self {
38            actions: vec![DeleteAction::new(path, subset)],
39        }
40    }
41
42    /// Add an additional [`Update`] statement to this `ADD` statement.
43    ///
44    /// ```
45    /// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
46    /// use dynamodb_expression::{value::NumSet, Num, Path};
47    /// # use pretty_assertions::assert_eq;
48    ///
49    /// let update = "foo"
50    ///     .parse::<Path>()?
51    ///     .delete(NumSet::from([7]))
52    ///     .and("bar".parse::<Path>()?.set("a value"))
53    ///     .and("baz".parse::<Path>()?.remove());
54    /// assert_eq!(r#"SET bar = "a value" REMOVE baz DELETE foo [7]"#, update.to_string());
55    /// #
56    /// # Ok(())
57    /// # }
58    /// ```
59    pub fn and<T>(self, other: T) -> Update
60    where
61        T: Into<Update>,
62    {
63        Update::from(self).and(other)
64    }
65}
66
67impl fmt::Display for Delete {
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        f.write_str("DELETE ")?;
70
71        let mut first = true;
72        self.actions.iter().try_for_each(|action| {
73            if first {
74                first = false;
75            } else {
76                f.write_str(", ")?;
77            }
78
79            action.fmt(f)
80        })
81    }
82}
83
84impl From<DeleteAction> for Delete {
85    fn from(action: DeleteAction) -> Self {
86        Self {
87            actions: vec![action],
88        }
89    }
90}
91
92#[must_use = "Use in an update expression with `Update::from(delete)`"]
93#[derive(Debug, Clone, PartialEq, Eq)]
94pub struct DeleteAction {
95    pub(crate) path: Path,
96    pub(crate) subset: ValueOrRef,
97}
98
99impl DeleteAction {
100    /// Creates a [`DeleteAction`] for the specified [`Path`] and items in that [set][1].
101    ///
102    /// Prefer [`Path::delete`] over this.
103    ///
104    /// [1]: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes.SetTypes
105    pub fn new<P, S>(path: P, subset: S) -> Self
106    where
107        P: Into<Path>,
108        S: Into<value::Set>,
109    {
110        Self {
111            path: path.into(),
112            subset: subset.into().into(),
113        }
114    }
115
116    /// Add an additional [`Update`] statement to this `ADD` statement.
117    ///
118    /// ```
119    /// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
120    /// use dynamodb_expression::{update::DeleteAction, value::NumSet, Num, Path};
121    /// # use pretty_assertions::assert_eq;
122    ///
123    /// let update = DeleteAction::new("foo".parse::<Path>()?, NumSet::from([7]))
124    ///     .and("bar".parse::<Path>()?.set("a value"))
125    ///     .and("baz".parse::<Path>()?.remove());
126    /// assert_eq!(r#"SET bar = "a value" REMOVE baz DELETE foo [7]"#, update.to_string());
127    /// #
128    /// # Ok(())
129    /// # }
130    /// ```
131    pub fn and<T>(self, other: T) -> Update
132    where
133        T: Into<Update>,
134    {
135        Update::from(self).and(other)
136    }
137}
138
139impl fmt::Display for DeleteAction {
140    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141        self.path.fmt(f)?;
142        f.write_char(' ')?;
143        self.subset.fmt(f)
144    }
145}