6 个版本

0.3.1 2024年2月20日
0.3.0 2024年1月29日
0.2.0 2023年12月11日
0.1.1 2023年12月11日

#238 in 数据库接口

Download history 10/week @ 2024-04-07 11/week @ 2024-04-14 137/week @ 2024-04-21 9/week @ 2024-04-28 129/week @ 2024-05-05 54/week @ 2024-05-12 54/week @ 2024-05-19 34/week @ 2024-05-26 159/week @ 2024-06-02 22/week @ 2024-06-09 58/week @ 2024-06-16 21/week @ 2024-06-23 139/week @ 2024-06-30 106/week @ 2024-07-07 137/week @ 2024-07-14 31/week @ 2024-07-21

413 每月下载
3 crates 中使用

MIT 许可证

175KB
3K SLoC

aykroyd: Rust 的零开销高效数据访问。

Aykroyd 是一个专注于开发者用户体验的微型 ORM,对性能的承诺坚定不移。您的数据库不再需要隐藏在抽象层或重复的样板代码之后。

数据库查询由一个实现 StatementQuery(以及可能 QueryOne)的普通 Rust 结构体表示。 StatementQuery 特征共享两个共同的父特征

  • QueryText,它提供了查询文本的访问权限,和
  • ToParams,我们可以使用它将结构体转换为数据库参数。

使用这些特征,数据库客户端可以准备查询文本,然后在数据库上运行它,传递所需的参数。

此外,Query 特征有一个关联类型 Row,它必须实现

  • FromRow,以便从数据库行反序列化。

所有这些特征都可以自动推导,因此常规的数据库访问代码可以简化为简单的结构定义。这些结构体逻辑上绑定查询文本到输入参数和输出行类型。

绑定不是魔法,没有对数据库的验证。 QueryStatement 实现是开发者的断言,这是您明智地验证的。建议编写一系列自动化测试,这些测试可以针对任何数据库层运行。

use aykroyd::{FromRow, Query, Statement};

#[derive(Statement)]
#[aykroyd(text = "
    INSERT INTO pets (name, species) VALUES ($1, $2)
")]
struct InsertPet<'a> {
    name: &'a str,
    species: &'a str,
}

#[derive(FromRow)]
struct Pet {
    id: i32,
    name: String,
    species: String,
}

#[derive(Query)]
#[aykroyd(row(Pet), text = "
    SELECT id, name, species FROM pets
")]
struct GetAllPets;

一旦您有了 StatementQuery,您就需要一个数据库连接来运行它。Aykroyd 支持以下数据库客户端 Crates

DB 后端 Crates 功能 同步/异步 客户端
PostgreSQL postgres postgres 同步 aykroyd::postgres::客户端
PostgreSQL tokio-postgres tokio-postgres 异步 aykroyd::tokio_postgres::客户端
MySQL/MariaDB mysql mysql 同步 aykroyd::mysql::客户端
SQLite rusqlite rusqlite 同步 aykroyd::rusqlite::客户端

有关更多详细信息,请参阅 文档

示例

以下是使用各种客户端端到端的样子。

同步

同步 PostgreSQL 客户端的示例,在编译时带有 crate 功能 postgres 可用。

use postgres::NoTls;
use aykroyd::postgres::Client;

fn try_main() -> Result<(), Error> {
    // Connect to the database
    let mut client =
        Client::connect("host=localhost user=postgres", NoTls)?;

    // Execute a statement, returning the number of rows modified.
    let insert_count = client.execute(&InsertPet {
        name: "Dan",
        species: "Felis synchronous",
    })?;
    assert_eq!(insert_count, 1);

    // Run a query and map the result objects.
    let rows = client.query(&GetAllPets)?;
    assert_eq!(rows.len(), 1);
    assert_eq!(rows[0].name, "Dan");

    Ok(())
}

异步

异步 PostgreSQL 客户端的示例,在编译时带有 crate 功能 tokio-postgres 可用。

use tokio_postgres::NoTls;
use aykroyd::tokio_postgres::connect;

#[tokio::main]
async fn main() -> Result<(), Error> {
    // Connect to the database
    let (mut client, conn) =
        connect("host=localhost user=postgres", NoTls).await?;

    // As with tokio_postgres, you need to spawn a task for the connection.
    tokio::spawn(async move {
        if let Err(e) = conn.await {
            eprintln!("connection error: {e}");
        }
    });

    // Execute a statement, returning the number of rows modified.
    let insert_count = client.execute(&InsertPet {
        name: "Dan",
        species: "Felis asynchronous",
    }).await?;
    assert_eq!(insert_count, 1);

    // Run a query and map the result objects.
    let rows = client.query(&GetAllPets).await?;
    assert_eq!(rows.len(), 1);
    assert_eq!(rows[0].name, "Dan");

    Ok(())
}

更多细节

请参阅示例项目目录 aykroyd-example/ 了解更多细节。

贡献

非常希望得到您的帮助。加入 邮件列表 并打个招呼,查看 问题追踪器 看看是否有任何感兴趣的地方。请参阅 CONTRIBUTING.md 文件获取更多信息。

依赖

~0–15MB
~211K SLoC