diesel/query_builder/functions.rs
1use super::delete_statement::DeleteStatement;
2use super::insert_statement::{Insert, InsertOrIgnore, Replace};
3use super::{
4 IncompleteInsertStatement, IntoUpdateTarget, SelectStatement, SqlQuery, UpdateStatement,
5};
6use dsl::Select;
7use expression::Expression;
8use query_dsl::methods::SelectDsl;
9
10/// Creates an `UPDATE` statement.
11///
12/// When a table is passed to `update`, every row in the table will be updated.
13/// You can narrow this scope by calling [`filter`] on the table before passing it in,
14/// which will result in `UPDATE your_table SET ... WHERE args_to_filter`.
15///
16/// Passing a type which implements `Identifiable` is the same as passing
17/// `some_table.find(some_struct.id())`.
18///
19/// [`filter`]: query_builder/struct.UpdateStatement.html#method.filter
20///
21/// # Examples
22///
23/// ```rust
24/// # #[macro_use] extern crate diesel;
25/// # include!("../doctest_setup.rs");
26/// #
27/// # #[cfg(feature = "postgres")]
28/// # fn main() {
29/// # use schema::users::dsl::*;
30/// # let connection = establish_connection();
31/// let updated_row = diesel::update(users.filter(id.eq(1)))
32/// .set(name.eq("James"))
33/// .get_result(&connection);
34/// // On backends that support it, you can call `get_result` instead of `execute`
35/// // to have `RETURNING *` automatically appended to the query. Alternatively, you
36/// // can explicitly return an expression by using the `returning` method before
37/// // getting the result.
38/// assert_eq!(Ok((1, "James".to_string())), updated_row);
39/// # }
40/// # #[cfg(not(feature = "postgres"))]
41/// # fn main() {}
42/// ```
43///
44/// To update multiple columns, give [`set`] a tuple argument:
45///
46/// [`set`]: query_builder/struct.UpdateStatement.html#method.set
47///
48/// ```rust
49/// # #[macro_use] extern crate diesel;
50/// # include!("../doctest_setup.rs");
51/// #
52/// # table! {
53/// # users {
54/// # id -> Integer,
55/// # name -> VarChar,
56/// # surname -> VarChar,
57/// # }
58/// # }
59/// #
60/// # #[cfg(feature = "postgres")]
61/// # fn main() {
62/// # use users::dsl::*;
63/// # let connection = establish_connection();
64/// # connection.execute("DROP TABLE users").unwrap();
65/// # connection.execute("CREATE TABLE users (
66/// # id SERIAL PRIMARY KEY,
67/// # name VARCHAR,
68/// # surname VARCHAR)").unwrap();
69/// # connection.execute("INSERT INTO users(name, surname) VALUES('Sean', 'Griffin')").unwrap();
70///
71/// let updated_row = diesel::update(users.filter(id.eq(1)))
72/// .set((name.eq("James"), surname.eq("Bond")))
73/// .get_result(&connection);
74///
75/// assert_eq!(Ok((1, "James".to_string(), "Bond".to_string())), updated_row);
76/// # }
77/// # #[cfg(not(feature = "postgres"))]
78/// # fn main() {}
79/// ```
80pub fn update<T: IntoUpdateTarget>(source: T) -> UpdateStatement<T::Table, T::WhereClause> {
81 UpdateStatement::new(source.into_update_target())
82}
83
84/// Creates a `DELETE` statement.
85///
86/// When a table is passed to `delete`,
87/// every row in the table will be deleted.
88/// This scope can be narrowed by calling [`filter`]
89/// on the table before it is passed in.
90///
91/// [`filter`]: query_builder/struct.DeleteStatement.html#method.filter
92///
93/// # Examples
94///
95/// ### Deleting a single record:
96///
97/// ```rust
98/// # #[macro_use] extern crate diesel;
99/// # include!("../doctest_setup.rs");
100/// #
101/// # fn main() {
102/// # delete();
103/// # }
104/// #
105/// # fn delete() -> QueryResult<()> {
106/// # use schema::users::dsl::*;
107/// # let connection = establish_connection();
108/// # let get_count = || users.count().first::<i64>(&connection);
109/// let old_count = get_count();
110/// diesel::delete(users.filter(id.eq(1))).execute(&connection)?;
111/// assert_eq!(old_count.map(|count| count - 1), get_count());
112/// # Ok(())
113/// # }
114/// ```
115///
116/// ### Deleting a whole table:
117///
118/// ```rust
119/// # #[macro_use] extern crate diesel;
120/// # include!("../doctest_setup.rs");
121/// #
122/// # fn main() {
123/// # delete();
124/// # }
125/// #
126/// # fn delete() -> QueryResult<()> {
127/// # use schema::users::dsl::*;
128/// # let connection = establish_connection();
129/// # let get_count = || users.count().first::<i64>(&connection);
130/// diesel::delete(users).execute(&connection)?;
131/// assert_eq!(Ok(0), get_count());
132/// # Ok(())
133/// # }
134/// ```
135pub fn delete<T: IntoUpdateTarget>(source: T) -> DeleteStatement<T::Table, T::WhereClause> {
136 let target = source.into_update_target();
137 DeleteStatement::new(target.table, target.where_clause)
138}
139
140/// Creates an `INSERT` statement for the target table.
141///
142/// You may add data by calling [`values()`] or [`default_values()`]
143/// as shown in the examples.
144///
145/// [`values()`]: query_builder/struct.IncompleteInsertStatement.html#method.values
146/// [`default_values()`]: query_builder/struct.IncompleteInsertStatement.html#method.default_values
147///
148/// Backends that support the `RETURNING` clause, such as PostgreSQL,
149/// can return the inserted rows by calling [`.get_results`] instead of [`.execute`].
150///
151/// [`.get_results`]: query_dsl/trait.RunQueryDsl.html#method.get_results
152/// [`.execute`]: query_dsl/trait.RunQueryDsl.html#tymethod.execute
153///
154/// # Examples
155///
156/// ```rust
157/// # #[macro_use] extern crate diesel;
158/// # include!("../doctest_setup.rs");
159/// #
160/// # fn main() {
161/// # use schema::users::dsl::*;
162/// # let connection = establish_connection();
163/// let rows_inserted = diesel::insert_into(users)
164/// .values(&name.eq("Sean"))
165/// .execute(&connection);
166///
167/// assert_eq!(Ok(1), rows_inserted);
168///
169/// let new_users = vec![
170/// name.eq("Tess"),
171/// name.eq("Jim"),
172/// ];
173///
174/// let rows_inserted = diesel::insert_into(users)
175/// .values(&new_users)
176/// .execute(&connection);
177///
178/// assert_eq!(Ok(2), rows_inserted);
179/// # }
180/// ```
181///
182/// ### Using a tuple for values
183///
184/// ```rust
185/// # #[macro_use] extern crate diesel;
186/// # include!("../doctest_setup.rs");
187/// #
188/// # fn main() {
189/// # use schema::users::dsl::*;
190/// # let connection = establish_connection();
191/// # diesel::delete(users).execute(&connection).unwrap();
192/// let new_user = (id.eq(1), name.eq("Sean"));
193/// let rows_inserted = diesel::insert_into(users)
194/// .values(&new_user)
195/// .execute(&connection);
196///
197/// assert_eq!(Ok(1), rows_inserted);
198///
199/// let new_users = vec![
200/// (id.eq(2), name.eq("Tess")),
201/// (id.eq(3), name.eq("Jim")),
202/// ];
203///
204/// let rows_inserted = diesel::insert_into(users)
205/// .values(&new_users)
206/// .execute(&connection);
207///
208/// assert_eq!(Ok(2), rows_inserted);
209/// # }
210/// ```
211///
212/// ### Using struct for values
213///
214/// ```rust
215/// # #[macro_use] extern crate diesel;
216/// # include!("../doctest_setup.rs");
217/// # use schema::users;
218/// #
219/// #[derive(Insertable)]
220/// #[table_name = "users"]
221/// struct NewUser<'a> {
222/// name: &'a str,
223/// }
224///
225/// # fn main() {
226/// # use schema::users::dsl::*;
227/// # let connection = establish_connection();
228/// // Insert one record at a time
229///
230/// let new_user = NewUser { name: "Ruby Rhod" };
231///
232/// diesel::insert_into(users)
233/// .values(&new_user)
234/// .execute(&connection)
235/// .unwrap();
236///
237/// // Insert many records
238///
239/// let new_users = vec![
240/// NewUser { name: "Leeloo Multipass", },
241/// NewUser { name: "Korben Dallas", },
242/// ];
243///
244/// let inserted_names = diesel::insert_into(users)
245/// .values(&new_users)
246/// .execute(&connection)
247/// .unwrap();
248/// # }
249/// ```
250///
251/// ### Insert from select
252///
253/// When inserting from a select statement,
254/// the column list can be specified with [`.into_columns`].
255/// (See also [`SelectStatement::insert_into`], which generally
256/// reads better for select statements)
257///
258/// [`SelectStatement::insert_into`]: prelude/trait.Insertable.html#method.insert_into
259/// [`.into_columns`]: query_builder/struct.InsertStatement.html#method.into_columns
260///
261/// ```rust
262/// # #[macro_use] extern crate diesel;
263/// # include!("../doctest_setup.rs");
264/// #
265/// # fn main() {
266/// # run_test().unwrap();
267/// # }
268/// #
269/// # fn run_test() -> QueryResult<()> {
270/// # use schema::{posts, users};
271/// # let conn = establish_connection();
272/// # diesel::delete(posts::table).execute(&conn)?;
273/// let new_posts = users::table
274/// .select((
275/// users::name.concat("'s First Post"),
276/// users::id,
277/// ));
278/// diesel::insert_into(posts::table)
279/// .values(new_posts)
280/// .into_columns((posts::title, posts::user_id))
281/// .execute(&conn)?;
282///
283/// let inserted_posts = posts::table
284/// .select(posts::title)
285/// .load::<String>(&conn)?;
286/// let expected = vec!["Sean's First Post", "Tess's First Post"];
287/// assert_eq!(expected, inserted_posts);
288/// # Ok(())
289/// # }
290/// ```
291///
292/// ### With return value
293///
294/// ```rust
295/// # #[macro_use] extern crate diesel;
296/// # include!("../doctest_setup.rs");
297/// #
298/// # #[cfg(feature = "postgres")]
299/// # fn main() {
300/// # use schema::users::dsl::*;
301/// # let connection = establish_connection();
302/// let inserted_names = diesel::insert_into(users)
303/// .values(&vec![
304/// name.eq("Diva Plavalaguna"),
305/// name.eq("Father Vito Cornelius"),
306/// ])
307/// .returning(name)
308/// .get_results(&connection);
309/// assert_eq!(Ok(vec!["Diva Plavalaguna".to_string(), "Father Vito Cornelius".to_string()]), inserted_names);
310/// # }
311/// # #[cfg(not(feature = "postgres"))]
312/// # fn main() {}
313/// ```
314pub fn insert_into<T>(target: T) -> IncompleteInsertStatement<T, Insert> {
315 IncompleteInsertStatement::new(target, Insert)
316}
317
318/// Creates an `INSERT [OR] IGNORE` statement.
319///
320/// If a constraint violation fails, the database will ignore the offending
321/// row and continue processing any subsequent rows. This function is only
322/// available with MySQL and SQLite.
323///
324/// With PostgreSQL, similar functionality is provided by [`on_conflict_do_nothing`].
325///
326/// [`on_conflict_do_nothing`]: query_builder/insert_statement/struct.InsertStatement.html#method.on_conflict_do_nothing
327///
328/// # Example
329///
330/// ```rust
331/// # #[macro_use] extern crate diesel;
332/// # include!("../doctest_setup.rs");
333/// #
334/// # fn main() {
335/// # run_test().unwrap();
336/// # }
337/// #
338/// # #[cfg(not(feature = "postgres"))]
339/// # fn run_test() -> QueryResult<()> {
340/// # use schema::users::dsl::*;
341/// # use diesel::{delete, insert_or_ignore_into};
342/// #
343/// # let connection = establish_connection();
344/// # diesel::delete(users).execute(&connection)?;
345/// insert_or_ignore_into(users)
346/// .values((id.eq(1), name.eq("Jim")))
347/// .execute(&connection)?;
348///
349/// insert_or_ignore_into(users)
350/// .values(&vec![
351/// (id.eq(1), name.eq("Sean")),
352/// (id.eq(2), name.eq("Tess")),
353/// ])
354/// .execute(&connection)?;
355///
356/// let names = users.select(name).order(id).load::<String>(&connection)?;
357/// assert_eq!(vec![String::from("Jim"), String::from("Tess")], names);
358/// # Ok(())
359/// # }
360/// #
361/// # #[cfg(feature = "postgres")]
362/// # fn run_test() -> QueryResult<()> {
363/// # Ok(())
364/// # }
365/// ```
366pub fn insert_or_ignore_into<T>(target: T) -> IncompleteInsertStatement<T, InsertOrIgnore> {
367 IncompleteInsertStatement::new(target, InsertOrIgnore)
368}
369
370/// Creates a bare select statement, with no from clause. Primarily used for
371/// testing diesel itself, but likely useful for third party crates as well. The
372/// given expressions must be selectable from anywhere.
373pub fn select<T>(expression: T) -> Select<SelectStatement<()>, T>
374where
375 T: Expression,
376 SelectStatement<()>: SelectDsl<T>,
377{
378 SelectStatement::simple(()).select(expression)
379}
380
381/// Creates a `REPLACE` statement.
382///
383/// If a constraint violation fails, the database will attempt to replace the
384/// offending row instead. This function is only available with MySQL and
385/// SQLite.
386///
387/// # Example
388///
389/// ```rust
390/// # #[macro_use] extern crate diesel;
391/// # include!("../doctest_setup.rs");
392/// #
393/// # #[cfg(not(feature = "postgres"))]
394/// # fn main() {
395/// # use schema::users::dsl::*;
396/// # use diesel::{insert_into, replace_into};
397/// #
398/// # let conn = establish_connection();
399/// # conn.execute("DELETE FROM users").unwrap();
400/// replace_into(users)
401/// .values(&vec![
402/// (id.eq(1), name.eq("Sean")),
403/// (id.eq(2), name.eq("Tess")),
404/// ])
405/// .execute(&conn)
406/// .unwrap();
407///
408/// replace_into(users)
409/// .values((id.eq(1), name.eq("Jim")))
410/// .execute(&conn)
411/// .unwrap();
412///
413/// let names = users.select(name).order(id).load::<String>(&conn);
414/// assert_eq!(Ok(vec!["Jim".into(), "Tess".into()]), names);
415/// # }
416/// # #[cfg(feature = "postgres")] fn main() {}
417pub fn replace_into<T>(target: T) -> IncompleteInsertStatement<T, Replace> {
418 IncompleteInsertStatement::new(target, Replace)
419}
420
421/// Construct a full SQL query using raw SQL.
422///
423/// This function exists for cases where a query needs to be written that is not
424/// supported by the query builder. Unlike most queries in Diesel, `sql_query`
425/// will deserialize its data by name, not by index. That means that you cannot
426/// deserialize into a tuple, and structs which you deserialize from this
427/// function will need to have `#[derive(QueryableByName)]`
428///
429/// # Safety
430///
431/// The implementation of `QueryableByName` will assume that columns with a
432/// given name will have a certain type. The compiler will be unable to verify
433/// that the given type is correct. If your query returns a column of an
434/// unexpected type, the result may have the wrong value, or return an error.
435///
436/// # Example
437///
438/// ```rust
439/// # #[macro_use] extern crate diesel;
440/// # include!("../doctest_setup.rs");
441/// #
442/// # use schema::users;
443/// #
444/// # #[derive(QueryableByName, Debug, PartialEq)]
445/// # #[table_name="users"]
446/// # struct User {
447/// # id: i32,
448/// # name: String,
449/// # }
450/// #
451/// # fn main() {
452/// # use diesel::sql_query;
453/// #
454/// # let connection = establish_connection();
455/// let users = sql_query("SELECT * FROM users ORDER BY id")
456/// .load(&connection);
457/// let expected_users = vec![
458/// User { id: 1, name: "Sean".into() },
459/// User { id: 2, name: "Tess".into() },
460/// ];
461/// assert_eq!(Ok(expected_users), users);
462/// # }
463/// ```
464pub fn sql_query<T: Into<String>>(query: T) -> SqlQuery {
465 SqlQuery::new(query.into())
466}