5 releases
0.2.1 | Jul 15, 2023 |
---|---|
0.2.0 | May 24, 2021 |
0.1.2 | May 23, 2021 |
0.1.1 | May 23, 2021 |
0.1.0 | May 23, 2021 |
#628 in Rust patterns
41KB
1K
SLoC
typed-sql
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;"
);
lib.rs
:
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');");
Dependencies
~9–20MB
~305K SLoC