6 个版本
0.2.4 | 2024年5月1日 |
---|---|
0.2.3 | 2024年3月14日 |
0.2.2 | 2024年1月2日 |
0.2.1 | 2023年11月29日 |
0.1.0 | 2023年5月28日 |
#522 在 数据库接口 中
每月 68 次下载
10KB
73 行
rusqlite-from-row
通过推导 FromRow
在结构体和 rusqlite 行之间生成映射。
[dependencies]
rusqlite_from_row = "0.2.4"
用法
推导 FromRow
并执行一个查询,该查询选择具有相同名称和类型的列。
use rusqlite_from_row::FromRow;
#[derive(FromRow)]
struct Todo {
todo_id: i32,
text: String,
author_id: i32,
}
let row = connection.query_row("SELECT todo_id, text, author_id FROM todos", [], Todo::try_from_row).unwrap();
嵌套、连接和平铺
您可能希望将两个表之间的连接表示为嵌套结构体。这可以通过在嵌套字段上使用 #[from_row)]
来实现。这将委托该字段的创建到 FromRow::from_row
,而不是到 FromSql
。
由于在连接表时可能存在命名冲突,因此可以指定一个 prefix = ".."
以唯一检索列。此前缀应与在 select 中重命名列时指定的前缀匹配,如 select <column> as <prefix><column>
。支持嵌套前缀。
还可以使用不带值的 #[from_row)]
。在这种情况下,将使用下划线之后的字段名。
可以通过将平铺类型包装在 Option
中来支持外连接。FromRow
的 Option
实现仍要求所有列都存在,但如果所有列都是 SQL null
值,则会产生一个 None
。
use rusqlite_from_row::FromRow;
#[derive(FromRow)]
struct Todo {
id: i32,
name: String,
text: String,
#[from_row(flatten, prefix = "user_")]
author: User
#[from_row(flatten, prefix)]
editor: User
}
#[derive(FromRow)]
struct User {
id: i32,
name: String
}
// Rename all `User` fields to have `user_` or `editor_` prefixes.
let row = client
.query_one(
"
SELECT
t.id,
t.name,
t.text,
u.name as user_name,
u.id as user_id,
e.name as editor_name,
e.id as editor_id
FROM
todos t
JOIN
user u ON t.author_id = u.id
JOIN
user e ON t.editor_id = e.id
",
[],
Todo::try_from_row,
)
.unwrap();
重命名和转换
如果一个结构体包含一个与SQL列名不同的字段名,您可以使用 #[from_row(rename = "..")]
属性。
通常情况下,如果您有一个自定义包装类型,如 struct DbId(i32)
,您需要实现 FromSql
才能在查询中使用它。一个简单的替代方法是,为 DbId
实现 From<i32>
或 TryFrom<i32>
,并使用 #[from_row(from = "i32")]
或 #[from_row(try_from = "i32")]
注解字段。
这将委托SQL转换给 <i32 as FromSql>
,然后将其转换为 DbId
。
use rusqlite_from_row::FromRow;
struct DbId(i32);
impl From<i32> for DbId {
fn from(value: i32) -> Self {
Self(value)
}
}
#[derive(FromRow)]
struct Todo {
// If the sqlite column is named `todo_id`.
#[from_row(rename = "todo_id", from = "i32")]
id: i32,
// If the sqlite column is `TEXT`, it will be decoded to `String`,
// using `FromSql` and then converted to `Vec<u8>` using `std::convert::From`.
#[from_row(from = "String")]
todo: Vec<u8>
}
依赖项
~22MB
~434K SLoC