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 模式

MIT 许可证

41KB
1K SLoC

typed-sql

Latest Version Rust Documentation LICENSE

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