edgedb-rust
edgedb-rust copied to clipboard
Derive `QueryArgs` for structs to provide named query arguments
Hello!
Would it be possible to execute queries like this :
#[derive(Queryable)]
struct MusicOutput {
pub id: Uuid,
pub name: String
}
let parameters = HashMap::from([
("artist", "John 5"),
]);
let music_output: Result<MusicOutput, _> = conn.query_required_single(
"select (
insert Artist {
name := <str>$artist
} unless conflict on .name else (select Artist)
) {id, name}", ¶meters).await;
The problem with using HashMap
is that arguments can be of different types. So dynamic typing should be used. I.e. edgedb_protocol::value::Value
type. Unforutately, we don't have a nice constructor for that at least yet.
The plan in, however, to make a derive:
#[derive(QueryArgs)]
struct Artist {
name: String,
}
But this is still on our todo list. For now, tuples are what is the easiest to use as query arguments.
Before edgedb-rust
offers a convenient way to construct named parameters from your struct, you can use named parameters with Client.query
by:
- Construct a
edgedb_protocol::value::Value::Object
from your map ofMap<String, Value>
. - Pass that
Value::Object
toClient.query_xxx
To construct edgedb_protocol::value::Value::Object
from a map, you can reference https://github.com/edgedb/edgedb-rust/blob/releases/edgedb-protocol/v0.6.0/edgedb-protocol/src/value.rs#L100. Note that, the example is to build SparseObject
, we just learn it to build Value:Object
.
You can take a look at my examples:
https://github.com/hongquan/QuanWeb/blob/2bcb09b4e62dd7742e8ebb9fee809a7e9970111c/src/stores/blog.rs#L123-L157
https://github.com/hongquan/QuanWeb/blob/2bcb09b4e62dd7742e8ebb9fee809a7e9970111c/src/api/structs.rs#L168-L206
Also: https://quan.hoabinh.vn/post/2023/8/querying-edgedb-with-name-parameters-in-rust
https://github.com/edgedb/edgedb-rust/pull/304 should solve this
Am I wrong, or do the QueryArgs docs (incorrectly) imply this is already possible with a derive macro?
You can derive it for a structure in this case it’s treated as a named tuple (i.e. query should include named arguments rather than numeric ones).
@KevinMGranger But such a derive macro doesn't exist yet.
I don't really understand what docs are trying to say here. I think they are saying that you could implement this trait to use named parameters.
Regardless, as @hongquan points out derive macro does not exist yet.
For anyone finding this thread in the future, named_args! is currently recommended way to pass named params into client.query_xxx()
:
let query = "SELECT (<str>$my_str, <int64>$my_int)";
let args = edgedb_protocol::named_args! {
"my_str" => "Hello world!".to_string(),
"my_int" => Value::Int64(42),
};
let res = client.query(query, &args).await.unwrap();
This issue will remain open to track derive macro for QueryArgs
on structs, as outlined by this comment.