#newtype #diesel #derive #automatic #connect #custom-derive #traits

diesel-derive-newtype

自动将新类型与 Diesel 连接,使用其包裹类型

12 个版本 (稳定)

2.2.0 2024年3月17日
2.1.2 2024年4月19日
2.1.1 2024年3月17日
2.1.0 2023年6月9日
0.1.1 2018年3月2日

#255数据库接口

Download history 3643/week @ 2024-04-27 4729/week @ 2024-05-04 5866/week @ 2024-05-11 5481/week @ 2024-05-18 4249/week @ 2024-05-25 5296/week @ 2024-06-01 4328/week @ 2024-06-08 3289/week @ 2024-06-15 4260/week @ 2024-06-22 3334/week @ 2024-06-29 3692/week @ 2024-07-06 3621/week @ 2024-07-13 2825/week @ 2024-07-20 3666/week @ 2024-07-27 3664/week @ 2024-08-03 3686/week @ 2024-08-10

每月14,419 次下载
17 个包中使用 (直接使用 6 个)

Apache-2.0/MIT

19KB
177

diesel-derive-newtype

在 Diesel 中轻松支持新类型。

Rust Crates.io Version

安装

diesel-derive-newtype 根据其主版本号支持 Diesel -- 0.x 到 1.x 支持相应的 diesel 版本,2.0 支持柴油 2.0,2.1 支持柴油 2.1。

新功能仅针对当前支持的 Diesel 版本开发。

[dependencies]
diesel-derive-newtype = "2.1.0"

对于 Diesel 2.0.x,你必须告诉 cargo 不要升级 diesel-derive-newtype

[dependencies]
diesel-derive-newtype = "~ 2.0.0"

对于 Diesel 1.x

[dependencies]
diesel-derive-newtype = "1.0"

#[派生(DieselNewType)]

此包公开一个自定义派生宏 DieselNewType,它为应用到的单字段元组结构体(NewType)实现了 ToSqlFromSqlFromSqlRowQueryableAsExpressionQueryId

此项目的目标是

  • derive(DieselNewType) 应该足以让你在 Diesel 中任何使用其底层类型的地方使用新类型。(可能成功)
  • 在使用你的新类型作为 Diesel 中的表达式元素时,应该得到与在 Rust 代码中相同的编译时保证(取决于你的需求,参见下面的 限制)。

示例

此实现

#[macro_use]
extern crate diesel_derive_newtype;

#[derive(DieselNewType)] // Doesn't need to be on its own line
#[derive(Debug, Hash, PartialEq, Eq)] // required by diesel
struct MyId(i64);

允许你在实体内部使用 MyId 结构体,就像它们是底层类型一样

table! {
    my_items {
        id -> Integer,
        val -> Integer,
    }
}

#[derive(Debug, PartialEq, Identifiable, Queryable)]
struct MyItem {
    id: MyId,
    val: u8,
}

哦哦。啊哈。

查看 测试 以获取更完整的示例。

限制

DieselNewtype 推导不会创建新的 数据库 类型,或者 Diesel 序列化类型。也就是说,如果你有 MyId(i64),这将使用 Diesel 的底层 BigInt 类型,这意味着尽管你的新类型可以在底层类型可以使用的任何地方使用,底层类型或任何其他具有相同底层类型的新类型也可以使用

在某个时候,所有东西最终都会变成线上的比特,所以如果我们不这样做,Diesel 就必须在其他地方这样做,这是合理的默认行为(它很容易调试),但我正在调查自动生成新的代理类型,以便无法使用元组或错误类型化结构体构造插入语句。

下面是这个类型漏洞的示例

#[derive(Debug, Hash, PartialEq, Eq, DieselNewType)]
struct OneId(i64);

#[derive(Debug, Hash, PartialEq, Eq, DieselNewType)]
struct OtherId(i64);

#[derive(Debug, Clone, PartialEq, Identifiable, Insertable, Queryable)]
#[diesel(table_name = my_entities)]
pub struct MyEntity {
    id: OneId,
    val: i32,
}

fn darn(conn: &Connection) {
    // shouldn't allow constructing the wrong type, but does
    let OtherId: Vec<OtherId> = my_entities
        .select(id)
        .filter(id.eq(OtherId(1)))  // shouldn't allow filtering by wrong type
        .execute(conn).unwrap();
}

请参阅 tests/should-not-compile.rs,了解我认为应该无法编译的内容。

我认为这个问题的根本原因在于 Diesel 实现了各种表达式方法,用于实现 AsExpression 的类型,基于 SQL 类型,而不关心 selfother 的 Rust 类型匹配。在一般情况下,这似乎是一个相当好的决定,但在这里有些不幸。

我希望找到一个解决方案,不需要手动为每个 *Expression 特性实现额外的边界,但到目前为止,你必须记住 Diesel 方法基本上会自动将你的数据转换为底层 SQL 类型。

发布

此工作流程使用

运行时注意,除非 diesel 有新版本发布,否则我们总是发布补丁版本

cargo readme > README.md
git diff --exit-code --quiet README.* || (git add README.* && git commit -m "chore: Update README")
cargo release patch

许可

diesel-derive-newtype 受以下任一许可的许可:

您可选择。

欢迎提交补丁和错误报告!

依赖关系

~275–720KB
~17K SLoC