1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! # Complex queries
//! See [`Query`] for available methods.
//!
//! ```
//! use typed_sql::{Query, Table, ToSql};
//!
//! #[derive(Table)]
//! struct User {
//! id: i64,
//! name: String
//! }
//!
//! let stmt = User::table()
//! .select()
//! .filter(|user| user.id.neq(6).and(user.id.gt(3)))
//! .group_by(|user| user.name)
//! .order_by(|user| user.name.then(user.id.ascending()))
//! .limit(5);
//!
//! assert_eq!(
//! stmt.to_sql(),
//! "SELECT * FROM users \
//! WHERE users.id != 6 AND users.id > 3 \
//! GROUP BY users.name \
//! ORDER BY users.name,users.id ASC \
//! LIMIT 5;"
//! );
//! ```
//! ## Injections
//! Queries with user input strings are vulnerable to SQL injections
//! and therefore must be serialized with [`ToSql::to_sql_unchecked`].
//!
//! ```
//! use typed_sql::{Insertable, Query, Table, ToSql};
//!
//! #[derive(Table, Insertable)]
//! struct User {
//! name: String
//! }
//!
//! let stmt = User::table().insert(User { name: String::from("untrusted") });
//!
//! assert_eq!(
//! stmt.to_sql_unchecked(),
//! "INSERT INTO users(name) VALUES ('untrusted');"
//! );
//! ```
//!
//! To avoid this use prepared statements with [`Binding`].
//! ```
//! use typed_sql::{Binding, Query, Table, ToSql};
//!
//! #[derive(Binding, Table)]
//! struct User {
//! name: String
//! }
//!
//! let id_plan = User::prepare("idplan", |binds| {
//! User::table().update(|user| user.name.eq(binds.name))
//! });
//!
//! assert_eq!(
//! id_plan.to_sql(),
//! "PREPARE idplan AS UPDATE users SET users.name = $1;"
//! );
//!
//! let stmt = id_plan.execute(User { name: String::from("foo") });
//! assert_eq!(stmt.to_sql(), "EXECUTE idplan('foo');");
//! ```
pub use Fetch;
pub use ;
pub use ;
pub use Table;
pub use Binding;
pub use *;