23 个版本
0.2.1 | 2024 年 5 月 25 日 |
---|---|
0.2.0 | 2024 年 2 月 16 日 |
0.1.11-alpha | 2023 年 10 月 14 日 |
0.1.8-alpha | 2023 年 9 月 27 日 |
0.1.0 | 2023 年 11 月 27 日 |
#1546 在 过程宏 中
1,608 每月下载量
在 2 个 Crates 中使用(通过 scyllax)
57KB
1K SLoC
scyllax (sɪl-æks)
Scylla 的一个受 SQLx 和 Discord 启发的查询系统。
示例
1. 模型定义
在您编写任何查询之前,您必须定义一个模型。
#[entity]
pub struct PersonEntity {
#[entity(primary_key)]
pub id: uuid::Uuid,
pub email: String,
pub created_at: i64,
}
2. 读取查询
使用 read_query
属性,定义选择查询很容易。
#[read_query(
query = "select * from person where id = :id limit 1",
return_type = "PersonEntity"
)]
pub struct GetPersonById {
pub id: Uuid,
}
3. 插入/更新查询
使用 upsert_query
属性,定义插入/更新查询很容易。
#[entity]
#[upsert_query(table = "person", name = UpsertPerson)]
pub struct PersonEntity {
#[entity(primary_key)]
pub id: uuid::Uuid,
pub email: String,
pub created_at: i64,
}
4. 查询集合
Scylla 要求在执行之前准备查询。为了在启动时准备(并检查)所有查询,创建一个查询集合并将其传递给 Executor。
create_query_collection!(
PersonQueries,
[
GetPersonById,
GetPersonByEmail
],
[
DeletePersonById,
UpsertPerson
]
);
let executor = Executor::<PersonQueries>::new(Arc::new(session)).await;
let user = executor.execute_read(GetPersonByEmail {
email: "[email protected]".to_string(),
}).await?;
println!("{user:#?}");
特性
- 读取查询
- 写入查询 (https://github.com/trufflehq/scyllax/pull/1)
- 请求合并
- 编译时选择查询验证
- 确保结构体上存在 where 约束
- 确保 where 约束与结构体的类型相同
- 运行时查询验证(结构体与模式匹配)
待办事项
- 移除
anyhow
,更精细的错误
用法
请参阅 示例 了解更多详情。
参考资料
#[read_request(
query = "select * from foo where id = ? limit 1",
entity_type = "Foo"
)]
struct GetFooById {
#[shard_key]
id: i64
}
handle.execute_read(GetFooById { ... }).await
Jake 的消息
尽管如此,与 Scylla Rust 封装不同,我们不需要字段以正确顺序排列,以便我们的东西工作。我们做了两件聪明的事情
SELECT *
实际上是一个谎言。永远不要在预处理语句中使用SELECT *
,绝对不要。CQL 由于客户端与服务器之间可能存在的模式不同步条件,在执行SELECT *
时存在协议级别的错误,这可能导致模式更改时的数据损坏。因此,我们不是这样做,我们查看实体类型结构体,并将SELECT *
转换为SELECT col_a, col_b, col_c
。这意味着如果某列存在于模式中,但不在我们将反序列化的结构体中,我们实际上不会查询它。这个错误的本质是,当向表中添加新列时,数据库可能会开始返回该列的数据,而客户端却对此一无所知。在病态情况下,这可能导致数据反序列化错位。请参阅https://docs.datastax.com/en/developer/java-driver/3.0/manual/statements/prepared/#avoid-preparing-select-queries - 虽然这看起来在本地协议 v5 中已经最终修复,但我不确定 Scylla 是否还在使用它。
- 对于查询参数的绑定,我们基本上解析 SQL 语句并找出所有的绑定位置,然后生成将字段按正确顺序绑定的代码(因为它们在电线级别上需要按查询中定义的顺序指定。)我们通过编译时的 proc 宏生成执行查询序列化的代码,因此我们不会产生重新排序的运行时开销。
在启动时,我们准备一切,并在代码中对结构体进行类型检查,以检查与数据库中的内容是否一致。手动注册一切是可以的。你可以让它编译时失败,如果你尝试使用未注册的查询。
依赖关系
~2–2.8MB
~53K SLoC