5 个版本
0.2.1 | 2023年7月15日 |
---|---|
0.2.0 | 2021年5月24日 |
0.1.2 | 2021年5月23日 |
0.1.1 | 2021年5月23日 |
0.1.0 | 2021年5月23日 |
#639 in Rust 模式
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
:
复杂查询
有关可用方法的详细信息,请参阅 Query
。
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;"
);
注入
包含用户输入字符串的查询容易受到 SQL 注入攻击,因此必须使用 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');"
);
为了避免这种情况,请使用带有 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');");
依赖项
~10–21MB
~312K SLoC