Crate edgedb_composable_query

Source
Expand description

§edgedb-composable-query

Query arbitrary structs from EdgeDB. Compose queries of arbitrary complexity.

Beware: it’s very much a work-in-progress. Pre-0.1. It’s messy, there’re todo!()’s in the code, etc. I’m still figuring out the semantics. If you’re interested in this working for your use-cases, please try it and file the issues at: https://github.com/valyagolev/edgedb-composable-query/issues. But don’t use it seriously yet; it might panic, and will change the API.

Two major parts of the crate.

  1. A set of tools, around the EdgedbObject derivable trait, that allow you to query arbitrary rust structs from EdgeDB, converting types automatically. See examples below.
  2. A set of tools, around the composable::EdgedbComposableQuery derivable trait, that allow you express complex, composable queries through Rust structs and attributes. See docs and examples in the composable submodule.

§EdgedbObject Examples

If you have this schema:

module default {
type Inner {
    required req: str;
    opt: str;
}
type Outer {
    inner: Inner;

    some_field: str;
    required other_field: str;
}

Here’re some of the ways to use 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())
);

Re-exports§

pub use nonempty;

Modules§

composable
Express complex, composable queries through Rust structs and attributes.

Structs§

EdgedbJson
Wrapper around your serializable types to pass them as JSON query arguments
Ref
Basically a Uuid and an Option<T>. Use this instead of adding id: Uuid field to your structs.

Traits§

EdgedbObject
Struct that can be received from EdgeDB as an Object. Derive this trait for your structs.
EdgedbPrim
One of the primitive EdgeDB types, including JSON (see EdgedbJson). Implement this for your types if they are primitive-convertible.
EdgedbQueryArgs
A tuple of query arguments, currently each must be EdgedbPrim.
EdgedbSetValue
A value of a particular cardinality (typically it’s provided automatically for T, Option<T>, Vec<T> or NonEmpty<T>)
EdgedbValue
An object or a primitive. For sets, see EdgedbSetValue. Provided automatically in most cases.

Functions§

query
Entry-point for querying EdgedbObjects of arbitrary cardinality.

Type Aliases§

Result
currently anyhow::Result. TODO: make crate’s own Result type Result<T, Error>

Derive Macros§

EdgedbObject