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');");
//! ```

#[cfg(feature = "sqlx")]
pub mod fetch;
#[cfg(feature = "sqlx")]
pub use fetch::Fetch;

pub mod query;
pub use query::{Insertable, Join, Query, Queryable};

mod sql;
pub use sql::{CheckedSql, ToSql};

pub mod table;
pub use table::Table;

pub mod types;
pub use types::Binding;

pub use typed_sql_derive::*;