grafbase_sql_ast/ast/update.rs
1use crate::ast::{Column, ConditionTree, Expression, Query, Table};
2
3type Type<'a> = Column<'a>;
4
5/// A builder for an `UPDATE` statement.
6#[derive(Debug, PartialEq, Clone)]
7pub struct Update<'a> {
8 pub(crate) table: Table<'a>,
9 pub(crate) columns: Vec<Column<'a>>,
10 pub(crate) values: Vec<Expression<'a>>,
11 pub(crate) conditions: Option<ConditionTree<'a>>,
12 pub(crate) returning: Option<Vec<Type<'a>>>,
13}
14
15impl<'a> From<Update<'a>> for Query<'a> {
16 fn from(update: Update<'a>) -> Self {
17 Query::Update(Box::new(update))
18 }
19}
20
21impl<'a> Update<'a> {
22 /// Creates the basis for an `UPDATE` statement to the given table.
23 pub fn table<T>(table: T) -> Self
24 where
25 T: Into<Table<'a>>,
26 {
27 Self {
28 table: table.into(),
29 columns: Vec::new(),
30 values: Vec::new(),
31 conditions: None,
32 returning: None,
33 }
34 }
35
36 /// Add another column value assignment to the query
37 ///
38 /// ```rust
39 /// # use grafbase_sql_ast::{ast::*, renderer::{Renderer, self}};
40 /// # fn main() {
41 /// let mut query = Update::table("users");
42 /// query.set("foo", 10);
43 /// query.set("bar", false);
44 ///
45 /// let (sql, params) = renderer::Postgres::build(query);
46 /// assert_eq!(r#"UPDATE "users" SET "foo" = $1, "bar" = $2"#, sql);
47 ///
48 /// assert_eq!(
49 /// vec![
50 /// Value::from(10),
51 /// Value::from(false),
52 /// ],
53 /// params,
54 /// );
55 /// # }
56 /// ```
57 pub fn set<K, V>(&mut self, column: K, value: V)
58 where
59 K: Into<Column<'a>>,
60 V: Into<Expression<'a>>,
61 {
62 self.columns.push(column.into());
63 self.values.push(value.into());
64 }
65
66 /// Adds `WHERE` conditions to the query. See
67 /// [Comparable](trait.Comparable.html#required-methods) for more examples.
68 ///
69 /// ```rust
70 /// # use grafbase_sql_ast::{ast::*, renderer::{Renderer, self}};
71 /// # fn main() {
72 /// let mut query = Update::table("users");
73 /// query.set("foo", 1);
74 /// query.so_that("bar".equals(false));
75 ///
76 /// let (sql, params) = renderer::Postgres::build(query);
77 ///
78 /// assert_eq!(r#"UPDATE "users" SET "foo" = $1 WHERE "bar" = $2"#, sql);
79 ///
80 /// assert_eq!(
81 /// vec![
82 /// Value::from(1),
83 /// Value::from(false),
84 /// ],
85 /// params,
86 /// );
87 /// # }
88 /// ```
89 ///
90 /// We can also use a nested `SELECT` in the conditions.
91 ///
92 /// ```rust
93 /// # use grafbase_sql_ast::{ast::*, renderer::{Renderer, self}};
94 /// # fn main() {
95 /// let mut select = Select::from_table("bars");
96 /// select.column("id");
97 /// select.so_that("uniq_val".equals(3));
98 ///
99 /// let mut query = Update::table("users");
100 /// query.set("foo", 1);
101 /// query.so_that("bar".equals(select));
102 ///
103 /// let (sql, params) = renderer::Postgres::build(query);
104 ///
105 /// assert_eq!(
106 /// r#"UPDATE "users" SET "foo" = $1 WHERE "bar" = (SELECT "id" FROM "bars" WHERE "uniq_val" = $2)"#,
107 /// sql
108 /// );
109 ///
110 /// assert_eq!(
111 /// vec![
112 /// Value::from(1),
113 /// Value::from(3),
114 /// ],
115 /// params,
116 /// );
117 /// # }
118 /// ```
119 pub fn so_that<T>(&mut self, conditions: T)
120 where
121 T: Into<ConditionTree<'a>>,
122 {
123 self.conditions = Some(conditions.into());
124 }
125
126 /// Sets the returned columns.
127 ///
128 /// ```rust
129 /// # use grafbase_sql_ast::{ast::*, renderer::{Renderer, self}};
130 /// # fn main() {
131 /// let mut update = Update::table("users");
132 /// update.set("foo", 10);
133 /// update.returning(vec!["id"]);
134 ///
135 /// let (sql, _) = renderer::Postgres::build(update);
136 ///
137 /// assert_eq!(r#"UPDATE "users" SET "foo" = $1 RETURNING "id""#, sql);
138 /// # }
139 /// ```
140 #[cfg(feature = "postgresql")]
141 pub fn returning<K, I>(&mut self, columns: I)
142 where
143 K: Into<Column<'a>>,
144 I: IntoIterator<Item = K>,
145 {
146 self.returning = Some(columns.into_iter().map(|k| k.into()).collect());
147 }
148}