Skip to main content

limbo_sqlite3_parser/to_sql_string/stmt/
update.rs

1use crate::{ast, to_sql_string::ToSqlString};
2
3impl ToSqlString for ast::Update {
4    fn to_sql_string<C: crate::to_sql_string::ToSqlContext>(&self, context: &C) -> String {
5        format!(
6            "{}UPDATE {}{}{} SET {}{}{}{}",
7            self.with.as_ref().map_or("".to_string(), |with| format!(
8                "{} ",
9                with.to_sql_string(context)
10            )),
11            self.or_conflict
12                .map_or("".to_string(), |conflict| format!("OR {} ", conflict)),
13            self.tbl_name.to_sql_string(context),
14            self.indexed
15                .as_ref()
16                .map_or("".to_string(), |indexed| format!(" {}", indexed)),
17            self.sets
18                .iter()
19                .map(|set| set.to_sql_string(context))
20                .collect::<Vec<_>>()
21                .join(", "),
22            self.from.as_ref().map_or("".to_string(), |from| format!(
23                " {}",
24                from.to_sql_string(context)
25            )),
26            self.where_clause
27                .as_ref()
28                .map_or("".to_string(), |expr| format!(
29                    " WHERE {}",
30                    expr.to_sql_string(context)
31                )),
32            self.returning
33                .as_ref()
34                .map_or("".to_string(), |returning| format!(
35                    " RETURNING {}",
36                    returning
37                        .iter()
38                        .map(|col| col.to_sql_string(context))
39                        .collect::<Vec<_>>()
40                        .join(", ")
41                ))
42        )
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use crate::to_sql_string_test;
49
50    // Basic UPDATE with a single column
51    to_sql_string_test!(
52        test_update_single_column,
53        "UPDATE employees SET salary = 55000;"
54    );
55
56    // UPDATE with multiple columns
57    to_sql_string_test!(
58        test_update_multiple_columns,
59        "UPDATE employees SET salary = 60000, name = 'John Smith';"
60    );
61
62    // UPDATE with a WHERE clause
63    to_sql_string_test!(
64        test_update_with_where,
65        "UPDATE employees SET salary = 60000 WHERE id = 1;"
66    );
67
68    // UPDATE with multiple WHERE conditions
69    to_sql_string_test!(
70        test_update_with_multi_where,
71        "UPDATE employees SET salary = 65000 WHERE department_id = 3 AND salary < 50000;"
72    );
73
74    // UPDATE with a subquery in SET
75    to_sql_string_test!(
76        test_update_with_subquery_set,
77        "UPDATE employees SET department_id = (SELECT id FROM departments WHERE name = 'Sales') WHERE id = 1;"
78    );
79
80    // UPDATE with a subquery in WHERE
81    to_sql_string_test!(
82        test_update_with_subquery_where,
83        "UPDATE employees SET salary = 70000 WHERE department_id IN (SELECT id FROM departments WHERE name = 'Marketing');"
84    );
85
86    // UPDATE with EXISTS clause
87    to_sql_string_test!(
88        test_update_with_exists,
89        "UPDATE employees SET salary = 75000 WHERE EXISTS (SELECT 1 FROM orders WHERE orders.employee_id = employees.id AND orders.status = 'pending');"
90    );
91
92    // UPDATE with FROM clause (join-like behavior)
93    to_sql_string_test!(
94        test_update_with_from,
95        "UPDATE employees SET salary = 80000 FROM departments WHERE employees.department_id = departments.id AND departments.name = 'Engineering';"
96    );
97
98    // UPDATE with RETURNING clause
99    to_sql_string_test!(
100        test_update_with_returning,
101        "UPDATE employees SET salary = 60000 WHERE id = 1 RETURNING id, name, salary;"
102    );
103
104    // UPDATE with expression in SET
105    to_sql_string_test!(
106        test_update_with_expression,
107        "UPDATE employees SET salary = salary * 1.1 WHERE department_id = 2;"
108    );
109
110    // UPDATE with NULL value
111    to_sql_string_test!(
112        test_update_with_null,
113        "UPDATE employees SET department_id = NULL WHERE id = 1;"
114    );
115
116    // UPDATE with schema-qualified table
117    to_sql_string_test!(
118        test_update_schema_qualified,
119        "UPDATE main.employees SET salary = 65000 WHERE id = 1;"
120    );
121
122    // UPDATE with CASE expression
123    to_sql_string_test!(
124        test_update_with_case,
125        "UPDATE employees SET salary = CASE WHEN salary < 50000 THEN 55000 ELSE salary * 1.05 END WHERE department_id = 3;"
126    );
127
128    // UPDATE with LIKE clause in WHERE
129    to_sql_string_test!(
130        test_update_with_like,
131        "UPDATE employees SET name = 'Updated' WHERE name LIKE 'J%';"
132    );
133
134    // UPDATE with ON CONFLICT (upsert-like behavior)
135    to_sql_string_test!(
136        test_update_with_on_conflict,
137        "INSERT INTO employees (id, name, salary) VALUES (1, 'John Doe', 50000) ON CONFLICT(id) DO UPDATE SET name = excluded.name, salary = excluded.salary;"
138    );
139}