2 个版本
0.0.4 | 2023年12月2日 |
---|---|
0.0.1 | 2023年11月13日 |
#1971 in Rust 模式
48KB
821 行
edgedb-composable-query
从 EdgeDB 中查询任意结构体。组合任意复杂性的查询。
注意:它还处于开发中。预0.1版本。代码比较混乱,代码中有 todo!() 的注释,等等。我仍在探索语义。如果您想尝试将其用于您的用例,请尝试它并在以下位置提交问题:https://github.com/valyagolev/edgedb-composable-query/issues。但请勿将其用于生产环境;它可能会崩溃,并且 API 将会发生变化。
该库的两大主要部分。
- 一套工具,围绕可衍生的
EdgedbObject
特性,允许您从 EdgeDB 中查询任意 Rust 结构体,并自动转换类型。以下是一些示例。 - 一套工具,围绕可衍生的
composable::EdgedbComposableQuery
特性,允许您通过 Rust 结构体和属性表达复杂、可组合的查询。请参阅 [composable] 子模块中的文档和示例。
EdgedbObject 示例
如果您有这个模式
module default {
type Inner {
required req: str;
opt: str;
}
type Outer {
inner: Inner;
some_field: str;
required other_field: str;
}
以下是使用 EdgedbObject
的一些方法
use edgedb_composable_query::{query, EdgedbObject, EdgedbSetValue, Ref};
#[derive(Debug, PartialEq, EdgedbObject)]
struct AdHocStruct {
a: String,
b: Option<String>,
}
#[derive(Debug, PartialEq, EdgedbObject)]
struct Inner {
req: String,
opt: Option<String>,
}
// typically you want to use Ref<T> to refer to a type
// Ref<T> is basically UUID and an Option<T>
#[derive(Debug, PartialEq, EdgedbObject)]
struct Outer {
inner: Option<Ref<Inner>>,
some_field: Option<String>,
other_field: String,
}
let conn = edgedb_tokio::create_client().await?;
assert_eq!(query::<i64, _>(&conn, "select 7*8", ()).await?, 56);
// use primitive params
assert_eq!(
query::<Vec<i64>, _>(&conn, "select {1 * <int32>$0, 2 * <int32>$0}", (22,)).await?,
vec![22, 44]
);
// ad-hoc objects:
assert_eq!(
query::<AdHocStruct, _>(&conn, "select { a := 'aaa', b := <str>{} }", ()).await?,
AdHocStruct {
a: "aaa".to_string(),
b: None
}
);
assert_eq!(
query::<AdHocStruct, _>(&conn, "select { a:= 'aaa', b:=<str>{'cc'} }", ()).await?,
AdHocStruct {
a: "aaa".to_string(),
b: Some("cc".to_string())
}
);
// cardinality mismatch:
assert!(
query::<AdHocStruct, _>(&conn, "select {a := 'aaa',b := <str>{'cc', 'dd'}}", ())
.await
.is_err()
);
// look up some objects
assert!(
dbg!(
query::<Vec<Inner>, _>(&conn, "select Inner {req, opt}", ())
.await?
).len()
> 0
);
// use ref if you need ids
assert!(
dbg!(
query::<Vec<Ref<Inner>>, _>(&conn, "select Inner {id, req, opt}", ())
.await?
).len()
> 0
);
// ref doesn't need the rest of the object
assert!(
dbg!(
query::<Vec<Ref<Inner>>, _>(&conn, "select Inner {id}", ())
.await?
).len()
> 0
);
// cardinality mismatch:
assert!(
query::<Ref<Inner>, _>(&conn, "select Inner {id}", ())
.await
.is_err()
);
// you can query things with refs in them:
let vs = query::<Vec<Outer>, _>(&conn, "select Outer {inner, some_field, other_field}", ())
.await?;
assert!(vs.len() > 0);
// refs picked up only ids here
assert!(
vs.iter()
.filter_map(|v| v.inner.as_ref())
.all(|inner_ref| inner_ref.known_value.is_none())
);
// if you want the whole object with Ref, don't forget to provide 'id' selector
let vs = query::<Vec<Outer>, _>(&conn, "
select Outer {
inner: { id, req, opt },
some_field,
other_field
}
", ())
.await?;
assert!(vs.len() > 0);
// refs picked up the whole objects
assert!(
vs.iter()
.filter_map(|v| v.inner.as_ref())
.all(|inner_ref| inner_ref.known_value.is_some())
);
依赖项
~17–29MB
~556K SLoC