Trait trustfall_core::interpreter::Adapter
source · pub trait Adapter<'vertex> {
type Vertex: Clone + Debug + 'vertex;
// Required methods
fn resolve_starting_vertices(
&self,
edge_name: &Arc<str>,
parameters: &EdgeParameters,
resolve_info: &ResolveInfo
) -> VertexIterator<'vertex, Self::Vertex>;
fn resolve_property<V: AsVertex<Self::Vertex> + 'vertex>(
&self,
contexts: ContextIterator<'vertex, V>,
type_name: &Arc<str>,
property_name: &Arc<str>,
resolve_info: &ResolveInfo
) -> ContextOutcomeIterator<'vertex, V, FieldValue>;
fn resolve_neighbors<V: AsVertex<Self::Vertex> + 'vertex>(
&self,
contexts: ContextIterator<'vertex, V>,
type_name: &Arc<str>,
edge_name: &Arc<str>,
parameters: &EdgeParameters,
resolve_info: &ResolveEdgeInfo
) -> ContextOutcomeIterator<'vertex, V, VertexIterator<'vertex, Self::Vertex>>;
fn resolve_coercion<V: AsVertex<Self::Vertex> + 'vertex>(
&self,
contexts: ContextIterator<'vertex, V>,
type_name: &Arc<str>,
coerce_to_type: &Arc<str>,
resolve_info: &ResolveInfo
) -> ContextOutcomeIterator<'vertex, V, bool>;
}
Expand description
Trustfall data providers implement this trait to enable querying their data sets.
The most straightforward way to implement this trait is to use
the trustfall_stubgen
code-generator tool tool to auto-generate stubs
customized to match your dataset’s schema, then fill in the blanks denoted by todo!()
.
If you prefer to implement the trait without code generation, consider implementing
BasicAdapter
instead. That’s a simpler version
of this trait and can be faster to implement without a significant loss of functionality:
- Both traits support the same set of queries. Under the hood,
BasicAdapter
itself implementsAdapter
. - If you need optimizations like batching or caching, you can implement them within
BasicAdapter
as well. - If you need more advanced optimizations such as predicate pushdown, or need to access Trustfall’s static analysis capabilities, implement this trait directly instead.
Required Associated Types§
Required Methods§
sourcefn resolve_starting_vertices(
&self,
edge_name: &Arc<str>,
parameters: &EdgeParameters,
resolve_info: &ResolveInfo
) -> VertexIterator<'vertex, Self::Vertex>
fn resolve_starting_vertices( &self, edge_name: &Arc<str>, parameters: &EdgeParameters, resolve_info: &ResolveInfo ) -> VertexIterator<'vertex, Self::Vertex>
Produce an iterator of vertices for the specified starting edge.
Starting edges are the entry points for querying according to a schema. Each query starts at such an edge, and such starting edges are defined directly on the root query type of the schema.
Example
Consider this query which gets the URLs of the posts currently on the front page of HackerNews: playground
query {
FrontPage {
url @output
}
}
The HackerNews schema defines FrontPage
as a starting edge
that points to vertices of type Item
.
As part of executing this query, Trustfall will call this method
with edge_name = "FrontPage"
. Here’s the implementation of this method
in the HackerNews example adapter.
Preconditions and postconditions
The caller guarantees that:
- The specified edge is a starting edge in the schema being queried.
- Any parameters the edge requires per the schema have values provided.
sourcefn resolve_property<V: AsVertex<Self::Vertex> + 'vertex>(
&self,
contexts: ContextIterator<'vertex, V>,
type_name: &Arc<str>,
property_name: &Arc<str>,
resolve_info: &ResolveInfo
) -> ContextOutcomeIterator<'vertex, V, FieldValue>
fn resolve_property<V: AsVertex<Self::Vertex> + 'vertex>( &self, contexts: ContextIterator<'vertex, V>, type_name: &Arc<str>, property_name: &Arc<str>, resolve_info: &ResolveInfo ) -> ContextOutcomeIterator<'vertex, V, FieldValue>
Resolve a property required by the query that’s being evaluated.
Each DataContext
in the contexts
parameter has an active vertex
DataContext::active_vertex()
. This call is asking for the value of
the specified property on each such active vertex,
for each active vertex in the input iterator.
The most ergonomic way to implement this method is usually via
the resolve_property_with()
helper method together with
the field_property!()
and accessor_property!()
macros.
Example
Consider this query which gets the URLs of the posts currently on the front page of HackerNews: playground
query {
FrontPage {
url @output
}
}
Our HackerNews schema defines FrontPage
as a starting edge
that points to vertices of type Item
, and defines url
as a property on the Item
type.
As part of executing this query, Trustfall will call this method
with type_name = "Item"
and property_name = "url"
.
This is how Trustfall looks up the URLs of the items returned by this query.
Here’s the implementation of this method in the HackerNews example adapter.
Preconditions and postconditions
The active vertex may be None
, or a Some(v)
whose v
is of Rust type &Self::Vertex
and represents a vertex whose type in the Trustfall schema is given by
this function’s type_name
parameter.
The caller guarantees that:
type_name
is a type or interface defined in the schema.property_name
is either a property field ontype_name
defined in the schema, or the special value"__typename"
requesting the name of the vertex’s type.- When the active vertex is
Some(...)
, its represents a vertex of typetype_name
: either its type is exactlytype_name
, ortype_name
is an interface implemented by the vertex’s type.
The returned iterator must satisfy these properties:
- Produce
(context, property_value)
tuples with the property’s value for that context. - Produce contexts in the same order as the input
contexts
iterator produced them. - Produce property values whose type matches the property’s type defined in the schema.
- When a context’s active vertex is
None
, its property value isFieldValue::Null
.
sourcefn resolve_neighbors<V: AsVertex<Self::Vertex> + 'vertex>(
&self,
contexts: ContextIterator<'vertex, V>,
type_name: &Arc<str>,
edge_name: &Arc<str>,
parameters: &EdgeParameters,
resolve_info: &ResolveEdgeInfo
) -> ContextOutcomeIterator<'vertex, V, VertexIterator<'vertex, Self::Vertex>>
fn resolve_neighbors<V: AsVertex<Self::Vertex> + 'vertex>( &self, contexts: ContextIterator<'vertex, V>, type_name: &Arc<str>, edge_name: &Arc<str>, parameters: &EdgeParameters, resolve_info: &ResolveEdgeInfo ) -> ContextOutcomeIterator<'vertex, V, VertexIterator<'vertex, Self::Vertex>>
Resolve the neighboring vertices across an edge.
Each DataContext
in the contexts
parameter has an active vertex
DataContext::active_vertex()
. This call is asking for
the iterator of neighboring vertices of the active vertex along a specified edge,
for each active vertex in the input iterator.
The most ergonomic way to implement this method is usually via
the resolve_neighbors_with()
helper method.
Example
Consider this query which gets the usernames and karma points of the users who submitted the latest stories on HackerNews: playground
query {
Latest {
byUser {
id @output
karma @output
}
}
}
Our HackerNews schema defines Latest
as a starting edge
that points to vertices of type Story
.
In turn, Story
has an edge called byUser
that points to User
vertices.
As part of executing this query, Trustfall will call this method
with type_name = "Story"
and edge_name = "byUser"
.
This is how Trustfall looks up the user vertices representing the submitters
of the latest HackerNews stories.
Here’s the implementation of this method in the HackerNews example adapter.
Preconditions and postconditions
The active vertex may be None
, or a Some(v)
whose v
is of Rust type &Self::Vertex
and represents a vertex whose type in the Trustfall schema is given by
this function’s type_name
parameter.
If the schema this adapter covers has no edges aside from starting edges,
then this method will never be called and may be implemented as unreachable!()
.
The caller guarantees that:
type_name
is a type or interface defined in the schema.edge_name
is an edge field ontype_name
defined in the schema.- Each parameter required by the edge has a value of appropriate type, per the schema.
- When the active vertex is
Some(...)
, its represents a vertex of typetype_name
: either its type is exactlytype_name
, ortype_name
is an interface implemented by the vertex’s type.
The returned iterator must satisfy these properties:
- Produce
(context, neighbors)
tuples with an iterator of neighbor vertices for that edge. - Produce contexts in the same order as the input
contexts
iterator produced them. - Each neighboring vertex is of the type specified for that edge in the schema.
- When a context’s active vertex is None, it has an empty neighbors iterator.
sourcefn resolve_coercion<V: AsVertex<Self::Vertex> + 'vertex>(
&self,
contexts: ContextIterator<'vertex, V>,
type_name: &Arc<str>,
coerce_to_type: &Arc<str>,
resolve_info: &ResolveInfo
) -> ContextOutcomeIterator<'vertex, V, bool>
fn resolve_coercion<V: AsVertex<Self::Vertex> + 'vertex>( &self, contexts: ContextIterator<'vertex, V>, type_name: &Arc<str>, coerce_to_type: &Arc<str>, resolve_info: &ResolveInfo ) -> ContextOutcomeIterator<'vertex, V, bool>
Attempt to coerce vertices to a subtype, as required by the query that’s being evaluated.
Each DataContext
in the contexts
parameter has an active vertex
DataContext::active_vertex()
. This call is asking whether the active vertex
happens to be an instance of a subtype, for each active vertex in the input iterator.
The most ergonomic ways to implement this method usually rely on
the resolve_coercion_using_schema()
or resolve_coercion_with()
helper methods.
Example
Consider this query which gets the titles of all stories on the front page of HackerNews, while discarding non-story items such as job postings and polls: playground
query {
FrontPage {
... on Story {
title @output
}
}
}
Our HackerNews schema defines FrontPage
as a starting edge
that points to vertices of type Item
.
It also defines Story
as a subtype of Item
.
After resolving the FrontPage
starting edge, Trustfall will need to determine which
of the resulting Item
vertices are actually of type Story
.
This is when Trustfall will call this method
with type_name = "Item"
and coerce_to_type = "Story"
.
Here’s the implementation of this method in the HackerNews example adapter.
Preconditions and postconditions
The active vertex may be None
, or a Some(v)
whose v
is of Rust type &Self::Vertex
and represents a vertex whose type in the Trustfall schema is given by
this function’s type_name
parameter.
If this adapter’s schema contains no subtyping, then no type coercions are possible:
this method will never be called and may be implemented as unreachable!()
.
The caller guarantees that:
type_name
is an interface defined in the schema.coerce_to_type
is a type or interface that implementstype_name
in the schema.- When the active vertex is
Some(...)
, its represents a vertex of typetype_name
: either its type is exactlytype_name
, ortype_name
is an interface implemented by the vertex’s type.
The returned iterator must satisfy these properties:
- Produce
(context, can_coerce)
tuples showing if the coercion succeded for that context. - Produce contexts in the same order as the input
contexts
iterator produced them. - Each neighboring vertex is of the type specified for that edge in the schema.
- When a context’s active vertex is
None
, its coercion outcome isfalse
.