#sqlite #rusqlite #from-row #mapper #column-name

rusqlite-from-row

可推导特质,允许将 rusqlite 行转换为结构体

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数据库接口

Download history 1119/week @ 2024-04-20 905/week @ 2024-04-27 790/week @ 2024-05-04 817/week @ 2024-05-11 7/week @ 2024-05-18 15/week @ 2024-05-25 5/week @ 2024-06-01 8/week @ 2024-06-08 31/week @ 2024-06-15 26/week @ 2024-06-22 14/week @ 2024-06-29 1/week @ 2024-07-06 1/week @ 2024-07-20 46/week @ 2024-07-27 21/week @ 2024-08-03

每月 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 中来支持外连接。FromRowOption 实现仍要求所有列都存在,但如果所有列都是 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