Skip to main content

juniper/executor/
mod.rs

1//! Resolve the document to values
2
3use std::{
4    borrow::Cow,
5    cmp::Ordering,
6    collections::HashMap,
7    fmt::{Debug, Display},
8    sync::{Arc, RwLock},
9};
10
11use arcstr::ArcStr;
12use fnv::FnvHashMap;
13use futures::Stream;
14
15use crate::{
16    GraphQLError,
17    ast::{
18        Definition, Document, Fragment, FromInputValue, InputValue, Operation, OperationType,
19        Selection, ToInputValue, Type,
20    },
21    parser::{SourcePosition, Spanning},
22    schema::{
23        meta::{
24            Argument, DeprecationStatus, EnumMeta, EnumValue, Field, InputObjectMeta,
25            InterfaceMeta, ListMeta, MetaType, NullableMeta, ObjectMeta, PlaceholderMeta,
26            ScalarMeta, UnionMeta,
27        },
28        model::{RootNode, SchemaType, TypeType},
29    },
30    types::{
31        async_await::{GraphQLTypeAsync, GraphQLValueAsync},
32        base::{GraphQLType, GraphQLValue},
33        name::Name,
34        subscriptions::{GraphQLSubscriptionType, GraphQLSubscriptionValue},
35    },
36    value::{DefaultScalarValue, ParseScalarValue, ScalarValue, Value},
37};
38
39pub use self::{
40    look_ahead::{
41        Applies, LookAheadArgument, LookAheadChildren, LookAheadList, LookAheadObject,
42        LookAheadSelection, LookAheadValue,
43    },
44    owned_executor::OwnedExecutor,
45};
46
47mod look_ahead;
48mod owned_executor;
49
50#[expect(missing_docs, reason = "self-explanatory")]
51#[derive(Clone)]
52pub enum FieldPath<'a> {
53    Root(SourcePosition),
54    Field(&'a str, SourcePosition, Arc<FieldPath<'a>>),
55}
56
57/// Query execution engine
58///
59/// The executor helps drive the query execution in a schema. It keeps track
60/// of the current field stack, context, variables, and errors.
61pub struct Executor<'r, 'a, CtxT, S = DefaultScalarValue>
62where
63    CtxT: 'a,
64    S: 'a,
65{
66    fragments: &'r HashMap<&'a str, Fragment<'a, S>>,
67    variables: &'r Variables<S>,
68    current_selection_set: Option<&'r [Selection<'a, S>]>,
69    parent_selection_set: Option<&'r [Selection<'a, S>]>,
70    current_type: TypeType<'a, S>,
71    schema: &'a SchemaType<S>,
72    context: &'a CtxT,
73    errors: &'r RwLock<Vec<ExecutionError<S>>>,
74    field_path: Arc<FieldPath<'a>>,
75}
76
77/// Error type for errors that occur during query execution
78///
79/// All execution errors contain the source position in the query of the field
80/// that failed to resolve. It also contains the field stack.
81#[derive(Clone, Debug, PartialEq)]
82pub struct ExecutionError<S> {
83    location: SourcePosition,
84    path: Vec<String>,
85    error: FieldError<S>,
86}
87
88impl<S> Eq for ExecutionError<S> where Self: PartialEq {}
89
90impl<S> ExecutionError<S> {
91    /// Construct a new execution error occuring at the beginning of the query
92    pub fn at_origin(error: FieldError<S>) -> ExecutionError<S> {
93        ExecutionError {
94            location: SourcePosition::new_origin(),
95            path: Vec::new(),
96            error,
97        }
98    }
99}
100
101impl<S> PartialOrd for ExecutionError<S>
102where
103    Self: PartialEq,
104{
105    fn partial_cmp(&self, other: &ExecutionError<S>) -> Option<Ordering> {
106        Some(self.cmp(other))
107    }
108}
109
110impl<S> Ord for ExecutionError<S>
111where
112    Self: Eq,
113{
114    fn cmp(&self, other: &ExecutionError<S>) -> Ordering {
115        (&self.location, &self.path, &self.error.message).cmp(&(
116            &other.location,
117            &other.path,
118            &other.error.message,
119        ))
120    }
121}
122
123/// Error type for errors that occur during field resolution
124///
125/// Field errors are represented by a human-readable error message and an
126/// optional `Value` structure containing additional information.
127///
128/// They can be converted to from any type that implements `std::fmt::Display`,
129/// which makes error chaining with the `?` operator a breeze:
130///
131/// ```rust
132/// # use juniper::{FieldError, ScalarValue};
133/// fn get_string(data: Vec<u8>) -> Result<String, FieldError>
134/// {
135///     let s = String::from_utf8(data)?;
136///     Ok(s)
137/// }
138/// ```
139#[derive(Clone, Debug, PartialEq)]
140pub struct FieldError<S = DefaultScalarValue> {
141    message: String,
142    extensions: Value<S>,
143}
144
145impl<T: Display, S> From<T> for FieldError<S> {
146    fn from(e: T) -> Self {
147        Self {
148            message: e.to_string(),
149            extensions: Value::Null,
150        }
151    }
152}
153
154impl<S> FieldError<S> {
155    /// Construct a new [`FieldError`] with additional data.
156    ///
157    /// You can use the [`graphql_value!`] macro for construction:
158    /// ```rust
159    /// use juniper::{graphql_value, FieldError};
160    ///
161    /// # let _: FieldError =
162    /// FieldError::new(
163    ///     "Could not open connection to the database",
164    ///     graphql_value!({"internal_error": "Connection refused"}),
165    /// );
166    /// ```
167    ///
168    /// The `extensions` parameter will be added to the `"extensions"` field of
169    /// the `"errors"` object in response:
170    /// ```json
171    /// {
172    ///   "errors": [
173    ///     "message": "Could not open connection to the database",
174    ///     "locations": [{"line": 2, "column": 4}],
175    ///     "extensions": {
176    ///       "internal_error": "Connection refused"
177    ///     }
178    ///   ]
179    /// }
180    /// ```
181    ///
182    /// If the argument is [`Value::Null`], then no extra data will be included.
183    ///
184    /// [`graphql_value!`]: macro@crate::graphql_value
185    #[must_use]
186    pub fn new<T: Display>(e: T, extensions: Value<S>) -> Self {
187        Self {
188            message: e.to_string(),
189            extensions,
190        }
191    }
192
193    /// Returns `"message"` field of this [`FieldError`].
194    #[must_use]
195    pub fn message(&self) -> &str {
196        &self.message
197    }
198
199    /// Returns `"extensions"` field of this [`FieldError`].
200    ///
201    /// If there is no `"extensions"`, then [`Value::Null`] will be returned.
202    #[must_use]
203    pub fn extensions(&self) -> &Value<S> {
204        &self.extensions
205    }
206
207    /// Maps the [`ScalarValue`] type of this [`FieldError`] into the specified
208    /// one.
209    #[must_use]
210    pub fn map_scalar_value<T>(self) -> FieldError<T>
211    where
212        S: ScalarValue,
213        T: ScalarValue,
214    {
215        FieldError {
216            message: self.message,
217            extensions: self.extensions.map_scalar_value(),
218        }
219    }
220
221    /// Maps the [`FieldError::message`] with the given function.
222    #[must_use]
223    pub fn map_message(self, f: impl FnOnce(String) -> String) -> Self {
224        Self {
225            message: f(self.message),
226            extensions: self.extensions,
227        }
228    }
229}
230
231/// The result of resolving the value of a field of type `T`
232pub type FieldResult<T, S = DefaultScalarValue> = Result<T, FieldError<S>>;
233
234/// The result of resolving an unspecified field
235pub type ExecutionResult<S = DefaultScalarValue> = Result<Value<S>, FieldError<S>>;
236
237/// Boxed `Stream` yielding `Result<Value<S>, ExecutionError<S>>`
238pub type ValuesStream<'a, S = DefaultScalarValue> =
239    std::pin::Pin<Box<dyn Stream<Item = Result<Value<S>, ExecutionError<S>>> + Send + 'a>>;
240
241/// The map of variables used for substitution during query execution
242pub type Variables<S = DefaultScalarValue> = HashMap<String, InputValue<S>>;
243
244/// Custom error handling trait to enable error types other than [`FieldError`]
245/// to be specified as return value.
246///
247/// Any custom error type should implement this trait to convert itself into a
248/// [`FieldError`].
249pub trait IntoFieldError<S = DefaultScalarValue> {
250    /// Performs the custom conversion into a [`FieldError`].
251    #[must_use]
252    fn into_field_error(self) -> FieldError<S>;
253}
254
255impl<S1: ScalarValue, S2: ScalarValue> IntoFieldError<S2> for FieldError<S1> {
256    fn into_field_error(self) -> FieldError<S2> {
257        self.map_scalar_value()
258    }
259}
260
261impl<S> IntoFieldError<S> for std::convert::Infallible {
262    fn into_field_error(self) -> FieldError<S> {
263        match self {}
264    }
265}
266
267impl<S> IntoFieldError<S> for &str {
268    fn into_field_error(self) -> FieldError<S> {
269        FieldError::<S>::from(self)
270    }
271}
272
273impl<S> IntoFieldError<S> for String {
274    fn into_field_error(self) -> FieldError<S> {
275        FieldError::<S>::from(self)
276    }
277}
278
279impl<S> IntoFieldError<S> for Cow<'_, str> {
280    fn into_field_error(self) -> FieldError<S> {
281        FieldError::<S>::from(self)
282    }
283}
284
285impl<S> IntoFieldError<S> for Box<str> {
286    fn into_field_error(self) -> FieldError<S> {
287        FieldError::<S>::from(self)
288    }
289}
290
291#[doc(hidden)]
292pub trait IntoResolvable<'a, S, T, C>
293where
294    T: GraphQLValue<S>,
295    S: ScalarValue,
296{
297    type Type;
298
299    #[doc(hidden)]
300    fn into_resolvable(self, ctx: &'a C) -> FieldResult<Option<(&'a T::Context, T)>, S>;
301}
302
303impl<'a, S, T, C> IntoResolvable<'a, S, T, C> for T
304where
305    T: GraphQLValue<S>,
306    S: ScalarValue,
307    T::Context: FromContext<C>,
308{
309    type Type = T;
310
311    fn into_resolvable(self, ctx: &'a C) -> FieldResult<Option<(&'a T::Context, T)>, S> {
312        Ok(Some((FromContext::from(ctx), self)))
313    }
314}
315
316impl<'a, S, T, C, E: IntoFieldError<S>> IntoResolvable<'a, S, T, C> for Result<T, E>
317where
318    S: ScalarValue,
319    T: GraphQLValue<S>,
320    T::Context: FromContext<C>,
321{
322    type Type = T;
323
324    fn into_resolvable(self, ctx: &'a C) -> FieldResult<Option<(&'a T::Context, T)>, S> {
325        self.map(|v: T| Some((<T::Context as FromContext<C>>::from(ctx), v)))
326            .map_err(IntoFieldError::into_field_error)
327    }
328}
329
330impl<'a, S, T, C> IntoResolvable<'a, S, T, C> for (&'a T::Context, T)
331where
332    S: ScalarValue,
333    T: GraphQLValue<S>,
334{
335    type Type = T;
336
337    fn into_resolvable(self, _: &'a C) -> FieldResult<Option<(&'a T::Context, T)>, S> {
338        Ok(Some(self))
339    }
340}
341
342impl<'a, S, T, C> IntoResolvable<'a, S, Option<T>, C> for Option<(&'a T::Context, T)>
343where
344    S: ScalarValue,
345    T: GraphQLValue<S>,
346{
347    type Type = T;
348
349    fn into_resolvable(self, _: &'a C) -> FieldResult<Option<(&'a T::Context, Option<T>)>, S> {
350        Ok(self.map(|(ctx, v)| (ctx, Some(v))))
351    }
352}
353
354impl<'a, S1, S2, T, C> IntoResolvable<'a, S2, T, C> for FieldResult<(&'a T::Context, T), S1>
355where
356    S1: ScalarValue,
357    S2: ScalarValue,
358    T: GraphQLValue<S2>,
359{
360    type Type = T;
361
362    fn into_resolvable(self, _: &'a C) -> FieldResult<Option<(&'a T::Context, T)>, S2> {
363        self.map(Some).map_err(FieldError::map_scalar_value)
364    }
365}
366
367impl<'a, S1, S2, T, C> IntoResolvable<'a, S2, Option<T>, C>
368    for FieldResult<Option<(&'a T::Context, T)>, S1>
369where
370    S1: ScalarValue,
371    S2: ScalarValue,
372    T: GraphQLValue<S2>,
373{
374    type Type = T;
375
376    fn into_resolvable(self, _: &'a C) -> FieldResult<Option<(&'a T::Context, Option<T>)>, S2> {
377        self.map(|o| o.map(|(ctx, v)| (ctx, Some(v))))
378            .map_err(FieldError::map_scalar_value)
379    }
380}
381
382/// Conversion trait for context types
383///
384/// Used to support different context types for different parts of an
385/// application. By making each `GraphQL` type only aware of as much
386/// context as it needs to, isolation and robustness can be
387/// improved. Implement this trait if you have contexts that can
388/// generally be converted between each other.
389///
390/// The empty tuple `()` can be converted into from any context type,
391/// making it suitable for `GraphQL` that don't need _any_ context to
392/// work, e.g. scalars or enums.
393pub trait FromContext<T> {
394    /// Perform the conversion
395    fn from(value: &T) -> &Self;
396}
397
398/// Marker trait for types that can act as context objects for `GraphQL` types.
399pub trait Context {}
400
401impl<C: Context> Context for &C {}
402
403static NULL_CONTEXT: () = ();
404
405impl<T> FromContext<T> for () {
406    fn from(_: &T) -> &Self {
407        &NULL_CONTEXT
408    }
409}
410
411impl<T> FromContext<T> for T
412where
413    T: Context,
414{
415    fn from(value: &T) -> &Self {
416        value
417    }
418}
419
420impl<'r, 'a, CtxT, S> Executor<'r, 'a, CtxT, S>
421where
422    S: ScalarValue,
423{
424    /// Resolve a single arbitrary value into a stream of [`Value`]s.
425    /// If a field fails to resolve, pushes error to `Executor`
426    /// and returns `Value::Null`.
427    pub async fn resolve_into_stream<'i, 'v, 'res, T>(
428        &'r self,
429        info: &'i T::TypeInfo,
430        value: &'v T,
431    ) -> Value<ValuesStream<'res, S>>
432    where
433        'i: 'res,
434        'v: 'res,
435        'a: 'res,
436        T: GraphQLSubscriptionValue<S, Context = CtxT> + ?Sized,
437        T::TypeInfo: Sync,
438        CtxT: Sync,
439        S: Send + Sync,
440    {
441        self.subscribe(info, value).await.unwrap_or_else(|e| {
442            self.push_error(e);
443            Value::Null
444        })
445    }
446
447    /// Resolve a single arbitrary value into a stream of [`Value`]s.
448    /// Calls `resolve_into_stream` on `T`.
449    pub async fn subscribe<'s, 't, 'res, T>(
450        &'r self,
451        info: &'t T::TypeInfo,
452        value: &'t T,
453    ) -> Result<Value<ValuesStream<'res, S>>, FieldError<S>>
454    where
455        't: 'res,
456        'a: 'res,
457        T: GraphQLSubscriptionValue<S, Context = CtxT> + ?Sized,
458        T::TypeInfo: Sync,
459        CtxT: Sync,
460        S: Send + Sync,
461    {
462        value.resolve_into_stream(info, self).await
463    }
464
465    /// Resolve a single arbitrary value, mapping the context to a new type
466    pub fn resolve_with_ctx<NewCtxT, T>(&self, info: &T::TypeInfo, value: &T) -> ExecutionResult<S>
467    where
468        NewCtxT: FromContext<CtxT>,
469        T: GraphQLValue<S, Context = NewCtxT> + ?Sized,
470    {
471        self.replaced_context(<NewCtxT as FromContext<CtxT>>::from(self.context))
472            .resolve(info, value)
473    }
474
475    /// Resolve a single arbitrary value into an `ExecutionResult`
476    pub fn resolve<T>(&self, info: &T::TypeInfo, value: &T) -> ExecutionResult<S>
477    where
478        T: GraphQLValue<S, Context = CtxT> + ?Sized,
479    {
480        value.resolve(info, self.current_selection_set, self)
481    }
482
483    /// Resolve a single arbitrary value into an `ExecutionResult`
484    pub async fn resolve_async<T>(&self, info: &T::TypeInfo, value: &T) -> ExecutionResult<S>
485    where
486        T: GraphQLValueAsync<S, Context = CtxT> + ?Sized,
487        T::TypeInfo: Sync,
488        CtxT: Sync,
489        S: Send + Sync,
490    {
491        value
492            .resolve_async(info, self.current_selection_set, self)
493            .await
494    }
495
496    /// Resolve a single arbitrary value, mapping the context to a new type
497    pub async fn resolve_with_ctx_async<NewCtxT, T>(
498        &self,
499        info: &T::TypeInfo,
500        value: &T,
501    ) -> ExecutionResult<S>
502    where
503        T: GraphQLValueAsync<S, Context = NewCtxT> + ?Sized,
504        T::TypeInfo: Sync,
505        NewCtxT: FromContext<CtxT> + Sync,
506        S: Send + Sync,
507    {
508        let e = self.replaced_context(<NewCtxT as FromContext<CtxT>>::from(self.context));
509        e.resolve_async(info, value).await
510    }
511
512    /// Resolve a single arbitrary value into a return value
513    ///
514    /// If the field fails to resolve, `null` will be returned.
515    pub fn resolve_into_value<T>(&self, info: &T::TypeInfo, value: &T) -> Value<S>
516    where
517        T: GraphQLValue<S, Context = CtxT>,
518    {
519        self.resolve(info, value).unwrap_or_else(|e| {
520            self.push_error(e);
521            Value::null()
522        })
523    }
524
525    /// Resolve a single arbitrary value into a return value
526    ///
527    /// If the field fails to resolve, `null` will be returned.
528    pub async fn resolve_into_value_async<T>(&self, info: &T::TypeInfo, value: &T) -> Value<S>
529    where
530        T: GraphQLValueAsync<S, Context = CtxT> + ?Sized,
531        T::TypeInfo: Sync,
532        CtxT: Sync,
533        S: Send + Sync,
534    {
535        self.resolve_async(info, value).await.unwrap_or_else(|e| {
536            self.push_error(e);
537            Value::null()
538        })
539    }
540
541    /// Derive a new executor by replacing the context
542    ///
543    /// This can be used to connect different types, e.g. from different Rust
544    /// libraries, that require different context types.
545    pub fn replaced_context<'b, NewCtxT>(
546        &'b self,
547        ctx: &'b NewCtxT,
548    ) -> Executor<'b, 'b, NewCtxT, S> {
549        Executor {
550            fragments: self.fragments,
551            variables: self.variables,
552            current_selection_set: self.current_selection_set,
553            parent_selection_set: self.parent_selection_set,
554            current_type: self.current_type.clone(),
555            schema: self.schema,
556            context: ctx,
557            errors: self.errors,
558            field_path: self.field_path.clone(),
559        }
560    }
561
562    #[doc(hidden)]
563    pub fn field_sub_executor<'s>(
564        &'s self,
565        field_alias: &'a str,
566        field_name: &'s str,
567        location: SourcePosition,
568        selection_set: Option<&'s [Selection<'a, S>]>,
569    ) -> Executor<'s, 'a, CtxT, S> {
570        Executor {
571            fragments: self.fragments,
572            variables: self.variables,
573            current_selection_set: selection_set,
574            parent_selection_set: self.current_selection_set,
575            current_type: self.schema.make_type(
576                &self
577                    .current_type
578                    .innermost_concrete()
579                    .field_by_name(field_name)
580                    .expect("Field not found on inner type")
581                    .field_type,
582            ),
583            schema: self.schema,
584            context: self.context,
585            errors: self.errors,
586            field_path: Arc::new(FieldPath::Field(
587                field_alias,
588                location,
589                Arc::clone(&self.field_path),
590            )),
591        }
592    }
593
594    #[doc(hidden)]
595    pub fn type_sub_executor<'s>(
596        &'s self,
597        type_name: Option<&'s str>,
598        selection_set: Option<&'s [Selection<'a, S>]>,
599    ) -> Executor<'s, 'a, CtxT, S> {
600        Executor {
601            fragments: self.fragments,
602            variables: self.variables,
603            current_selection_set: selection_set,
604            parent_selection_set: self.current_selection_set,
605            current_type: match type_name {
606                Some(type_name) => self.schema.type_by_name(type_name).expect("Type not found"),
607                None => self.current_type.clone(),
608            },
609            schema: self.schema,
610            context: self.context,
611            errors: self.errors,
612            field_path: self.field_path.clone(),
613        }
614    }
615
616    /// `Executor`'s current selection set
617    pub(crate) fn current_selection_set(&self) -> Option<&[Selection<'a, S>]> {
618        self.current_selection_set
619    }
620
621    /// Access the current context
622    ///
623    /// You usually provide the context when calling the top-level `execute`
624    /// function, or using the context factory.
625    pub fn context(&self) -> &'r CtxT {
626        self.context
627    }
628
629    /// The currently executing schema
630    pub fn schema(&self) -> &'a SchemaType<S> {
631        self.schema
632    }
633
634    #[doc(hidden)]
635    pub fn current_type(&self) -> &TypeType<'a, S> {
636        &self.current_type
637    }
638
639    #[doc(hidden)]
640    pub fn variables(&self) -> &'r Variables<S> {
641        self.variables
642    }
643
644    #[doc(hidden)]
645    pub fn fragment_by_name<'s>(&'s self, name: &str) -> Option<&'s Fragment<'a, S>> {
646        self.fragments.get(name)
647    }
648
649    /// The current location of the executor
650    pub fn location(&self) -> &SourcePosition {
651        self.field_path.location()
652    }
653
654    /// Add an error to the execution engine at the current executor location
655    pub fn push_error(&self, error: FieldError<S>) {
656        self.push_error_at(error, *self.location());
657    }
658
659    /// Add an error to the execution engine at a specific location
660    pub fn push_error_at(&self, error: FieldError<S>, location: SourcePosition) {
661        let mut path = Vec::new();
662        self.field_path.construct_path(&mut path);
663
664        let mut errors = self.errors.write().unwrap();
665
666        errors.push(ExecutionError {
667            location,
668            path,
669            error,
670        });
671    }
672
673    /// Returns new [`ExecutionError`] at current location
674    pub fn new_error(&self, error: FieldError<S>) -> ExecutionError<S> {
675        let mut path = Vec::new();
676        self.field_path.construct_path(&mut path);
677
678        ExecutionError {
679            location: *self.location(),
680            path,
681            error,
682        }
683    }
684
685    /// Construct a lookahead selection for the current selection.
686    ///
687    /// This allows seeing the whole selection and perform operations
688    /// affecting the children.
689    pub fn look_ahead(&'a self) -> LookAheadSelection<'a, S> {
690        let field_name = match *self.field_path {
691            FieldPath::Field(x, ..) => x,
692            FieldPath::Root(_) => unreachable!(),
693        };
694        self.parent_selection_set
695            .and_then(|p| {
696                // Search the parent's fields to find this field within the selection set.
697                p.iter().find_map(|x| {
698                    match x {
699                        Selection::Field(field) => {
700                            let field = &field.item;
701                            // TODO: support excludes.
702                            let name = field.name.item;
703                            let alias = field.alias.as_ref().map(|a| a.item);
704
705                            (alias.unwrap_or(name) == field_name).then(|| {
706                                LookAheadSelection::new(
707                                    look_ahead::SelectionSource::Field(field),
708                                    self.variables,
709                                    self.fragments,
710                                )
711                            })
712                        }
713                        Selection::FragmentSpread(_) | Selection::InlineFragment(_) => None,
714                    }
715                })
716            })
717            .unwrap_or_else(|| {
718                // We didn't find this field in the parent's selection matching it, which means
719                // we're inside a `FragmentSpread`.
720                LookAheadSelection::new(
721                    look_ahead::SelectionSource::Spread {
722                        field_name,
723                        set: self.current_selection_set,
724                    },
725                    self.variables,
726                    self.fragments,
727                )
728            })
729    }
730
731    /// Create new `OwnedExecutor` and clone all current data
732    /// (except for errors) there
733    ///
734    /// New empty vector is created for `errors` because
735    /// existing errors won't be needed to be accessed by user
736    /// in OwnedExecutor as existing errors will be returned in
737    /// `execute_query`/`execute_mutation`/`resolve_into_stream`/etc.
738    pub fn as_owned_executor(&self) -> OwnedExecutor<'a, CtxT, S> {
739        OwnedExecutor {
740            fragments: self.fragments.clone(),
741            variables: self.variables.clone(),
742            current_selection_set: self.current_selection_set.map(|x| x.to_vec()),
743            parent_selection_set: self.parent_selection_set.map(|x| x.to_vec()),
744            current_type: self.current_type.clone(),
745            schema: self.schema,
746            context: self.context,
747            errors: RwLock::new(vec![]),
748            field_path: Arc::clone(&self.field_path),
749        }
750    }
751}
752
753impl FieldPath<'_> {
754    fn construct_path(&self, acc: &mut Vec<String>) {
755        match self {
756            FieldPath::Root(_) => (),
757            FieldPath::Field(name, _, parent) => {
758                parent.construct_path(acc);
759                acc.push((*name).into());
760            }
761        }
762    }
763
764    fn location(&self) -> &SourcePosition {
765        match *self {
766            FieldPath::Root(ref pos) | FieldPath::Field(_, ref pos, _) => pos,
767        }
768    }
769}
770
771impl<S> ExecutionError<S> {
772    #[doc(hidden)]
773    pub fn new(location: SourcePosition, path: &[&str], error: FieldError<S>) -> ExecutionError<S> {
774        ExecutionError {
775            location,
776            path: path.iter().map(|s| (*s).into()).collect(),
777            error,
778        }
779    }
780
781    /// The error message
782    pub fn error(&self) -> &FieldError<S> {
783        &self.error
784    }
785
786    /// The source location _in the query_ of the field that failed to resolve
787    pub fn location(&self) -> &SourcePosition {
788        &self.location
789    }
790
791    /// The path of fields leading to the field that generated this error
792    pub fn path(&self) -> &[String] {
793        &self.path
794    }
795}
796
797/// Create new `Executor` and start query/mutation execution.
798/// Returns `IsSubscription` error if subscription is passed.
799pub fn execute_validated_query<'b, QueryT, MutationT, SubscriptionT, S>(
800    document: &'b Document<S>,
801    operation: &'b Spanning<Operation<S>>,
802    root_node: &RootNode<QueryT, MutationT, SubscriptionT, S>,
803    variables: &Variables<S>,
804    context: &QueryT::Context,
805) -> Result<(Value<S>, Vec<ExecutionError<S>>), GraphQLError>
806where
807    S: ScalarValue,
808    QueryT: GraphQLType<S>,
809    MutationT: GraphQLType<S, Context = QueryT::Context>,
810    SubscriptionT: GraphQLType<S, Context = QueryT::Context>,
811{
812    if operation.item.operation_type == OperationType::Subscription {
813        return Err(GraphQLError::IsSubscription);
814    }
815
816    let mut fragments = vec![];
817    for def in document.iter() {
818        if let Definition::Fragment(f) = def {
819            fragments.push(f)
820        };
821    }
822
823    let default_variable_values = operation.item.variable_definitions.as_ref().map(|defs| {
824        defs.item
825            .items
826            .iter()
827            .filter_map(|(name, def)| {
828                def.default_value
829                    .as_ref()
830                    .map(|i| (name.item.into(), i.item.clone()))
831            })
832            .collect::<HashMap<String, InputValue<S>>>()
833    });
834
835    let errors = RwLock::new(Vec::new());
836    let value;
837
838    {
839        let mut all_vars;
840        let mut final_vars = variables;
841
842        if let Some(defaults) = default_variable_values {
843            all_vars = variables.clone();
844
845            for (name, value) in defaults {
846                all_vars.entry(name).or_insert(value);
847            }
848
849            final_vars = &all_vars;
850        }
851
852        let root_type = match operation.item.operation_type {
853            OperationType::Query => root_node.schema.query_type(),
854            OperationType::Mutation => root_node
855                .schema
856                .mutation_type()
857                .expect("No mutation type found"),
858            OperationType::Subscription => unreachable!(),
859        };
860
861        let executor = Executor {
862            fragments: &fragments
863                .iter()
864                .map(|f| (f.item.name.item, f.item.clone()))
865                .collect(),
866            variables: final_vars,
867            current_selection_set: Some(&operation.item.selection_set[..]),
868            parent_selection_set: None,
869            current_type: root_type,
870            schema: &root_node.schema,
871            context,
872            errors: &errors,
873            field_path: Arc::new(FieldPath::Root(operation.span.start)),
874        };
875
876        value = match operation.item.operation_type {
877            OperationType::Query => executor.resolve_into_value(&root_node.query_info, &root_node),
878            OperationType::Mutation => {
879                executor.resolve_into_value(&root_node.mutation_info, &root_node.mutation_type)
880            }
881            OperationType::Subscription => unreachable!(),
882        };
883    }
884
885    let mut errors = errors.into_inner().unwrap();
886    errors.sort();
887
888    Ok((value, errors))
889}
890
891/// Create new `Executor` and start asynchronous query execution.
892/// Returns `IsSubscription` error if subscription is passed.
893pub async fn execute_validated_query_async<'b, QueryT, MutationT, SubscriptionT, S>(
894    document: &'b Document<'_, S>,
895    operation: &'b Spanning<Operation<'_, S>>,
896    root_node: &RootNode<QueryT, MutationT, SubscriptionT, S>,
897    variables: &Variables<S>,
898    context: &QueryT::Context,
899) -> Result<(Value<S>, Vec<ExecutionError<S>>), GraphQLError>
900where
901    QueryT: GraphQLTypeAsync<S>,
902    QueryT::TypeInfo: Sync,
903    QueryT::Context: Sync,
904    MutationT: GraphQLTypeAsync<S, Context = QueryT::Context>,
905    MutationT::TypeInfo: Sync,
906    SubscriptionT: GraphQLType<S, Context = QueryT::Context> + Sync,
907    SubscriptionT::TypeInfo: Sync,
908    S: ScalarValue + Send + Sync,
909{
910    if operation.item.operation_type == OperationType::Subscription {
911        return Err(GraphQLError::IsSubscription);
912    }
913
914    let mut fragments = vec![];
915    for def in document.iter() {
916        if let Definition::Fragment(f) = def {
917            fragments.push(f)
918        };
919    }
920
921    let default_variable_values = operation.item.variable_definitions.as_ref().map(|defs| {
922        defs.item
923            .items
924            .iter()
925            .filter_map(|(name, def)| {
926                def.default_value
927                    .as_ref()
928                    .map(|i| (name.item.into(), i.item.clone()))
929            })
930            .collect::<HashMap<String, InputValue<S>>>()
931    });
932
933    let errors = RwLock::new(Vec::new());
934    let value;
935
936    {
937        let mut all_vars;
938        let mut final_vars = variables;
939
940        if let Some(defaults) = default_variable_values {
941            all_vars = variables.clone();
942
943            for (name, value) in defaults {
944                all_vars.entry(name).or_insert(value);
945            }
946
947            final_vars = &all_vars;
948        }
949
950        let root_type = match operation.item.operation_type {
951            OperationType::Query => root_node.schema.query_type(),
952            OperationType::Mutation => root_node
953                .schema
954                .mutation_type()
955                .expect("No mutation type found"),
956            OperationType::Subscription => unreachable!(),
957        };
958
959        let executor = Executor {
960            fragments: &fragments
961                .iter()
962                .map(|f| (f.item.name.item, f.item.clone()))
963                .collect(),
964            variables: final_vars,
965            current_selection_set: Some(&operation.item.selection_set[..]),
966            parent_selection_set: None,
967            current_type: root_type,
968            schema: &root_node.schema,
969            context,
970            errors: &errors,
971            field_path: Arc::new(FieldPath::Root(operation.span.start)),
972        };
973
974        value = match operation.item.operation_type {
975            OperationType::Query => {
976                executor
977                    .resolve_into_value_async(&root_node.query_info, &root_node)
978                    .await
979            }
980            OperationType::Mutation => {
981                executor
982                    .resolve_into_value_async(&root_node.mutation_info, &root_node.mutation_type)
983                    .await
984            }
985            OperationType::Subscription => unreachable!(),
986        };
987    }
988
989    let mut errors = errors.into_inner().unwrap();
990    errors.sort();
991
992    Ok((value, errors))
993}
994
995#[doc(hidden)]
996pub fn get_operation<'b, 'd, S>(
997    document: &'b Document<'d, S>,
998    operation_name: Option<&str>,
999) -> Result<&'b Spanning<Operation<'d, S>>, GraphQLError>
1000where
1001    S: ScalarValue,
1002{
1003    let mut operation = None;
1004    for def in document {
1005        if let Definition::Operation(op) = def {
1006            if operation_name.is_none() && operation.is_some() {
1007                return Err(GraphQLError::MultipleOperationsProvided);
1008            }
1009
1010            let move_op =
1011                operation_name.is_none() || op.item.name.as_ref().map(|s| s.item) == operation_name;
1012
1013            if move_op {
1014                operation = Some(op);
1015            }
1016        };
1017    }
1018    let op = match operation {
1019        Some(op) => op,
1020        None => return Err(GraphQLError::UnknownOperationName),
1021    };
1022    Ok(op)
1023}
1024
1025/// Initialize new `Executor` and start resolving subscription into stream
1026/// asynchronously.
1027/// Returns `NotSubscription` error if query or mutation is passed
1028pub async fn resolve_validated_subscription<
1029    'r,
1030    'exec_ref,
1031    'd,
1032    'op,
1033    QueryT,
1034    MutationT,
1035    SubscriptionT,
1036    S,
1037>(
1038    document: &Document<'d, S>,
1039    operation: &Spanning<Operation<'op, S>>,
1040    root_node: &'r RootNode<QueryT, MutationT, SubscriptionT, S>,
1041    variables: &Variables<S>,
1042    context: &'r QueryT::Context,
1043) -> Result<(Value<ValuesStream<'r, S>>, Vec<ExecutionError<S>>), GraphQLError>
1044where
1045    'r: 'exec_ref,
1046    'd: 'r,
1047    'op: 'd,
1048    QueryT: GraphQLTypeAsync<S>,
1049    QueryT::TypeInfo: Sync,
1050    QueryT::Context: Sync + 'r,
1051    MutationT: GraphQLTypeAsync<S, Context = QueryT::Context>,
1052    MutationT::TypeInfo: Sync,
1053    SubscriptionT: GraphQLSubscriptionType<S, Context = QueryT::Context>,
1054    SubscriptionT::TypeInfo: Sync,
1055    S: ScalarValue + Send + Sync,
1056{
1057    if operation.item.operation_type != OperationType::Subscription {
1058        return Err(GraphQLError::NotSubscription);
1059    }
1060
1061    let mut fragments = vec![];
1062    for def in document.iter() {
1063        if let Definition::Fragment(f) = def {
1064            fragments.push(f)
1065        }
1066    }
1067
1068    let default_variable_values = operation.item.variable_definitions.as_ref().map(|defs| {
1069        defs.item
1070            .items
1071            .iter()
1072            .filter_map(|(name, def)| {
1073                def.default_value
1074                    .as_ref()
1075                    .map(|i| (name.item.into(), i.item.clone()))
1076            })
1077            .collect::<HashMap<String, InputValue<S>>>()
1078    });
1079
1080    let errors = RwLock::new(Vec::new());
1081    let value;
1082
1083    {
1084        let mut all_vars;
1085        let mut final_vars = variables;
1086
1087        if let Some(defaults) = default_variable_values {
1088            all_vars = variables.clone();
1089
1090            for (name, value) in defaults {
1091                all_vars.entry(name).or_insert(value);
1092            }
1093
1094            final_vars = &all_vars;
1095        }
1096
1097        let root_type = match operation.item.operation_type {
1098            OperationType::Subscription => root_node
1099                .schema
1100                .subscription_type()
1101                .expect("No subscription type found"),
1102            _ => unreachable!(),
1103        };
1104
1105        let executor: Executor<'_, 'r, _, _> = Executor {
1106            fragments: &fragments
1107                .iter()
1108                .map(|f| (f.item.name.item, f.item.clone()))
1109                .collect(),
1110            variables: final_vars,
1111            current_selection_set: Some(&operation.item.selection_set[..]),
1112            parent_selection_set: None,
1113            current_type: root_type,
1114            schema: &root_node.schema,
1115            context,
1116            errors: &errors,
1117            field_path: Arc::new(FieldPath::Root(operation.span.start)),
1118        };
1119
1120        value = match operation.item.operation_type {
1121            OperationType::Subscription => {
1122                executor
1123                    .resolve_into_stream(&root_node.subscription_info, &root_node.subscription_type)
1124                    .await
1125            }
1126            _ => unreachable!(),
1127        };
1128    }
1129
1130    let mut errors = errors.into_inner().unwrap();
1131    errors.sort();
1132
1133    Ok((value, errors))
1134}
1135
1136/// A type registry used to build schemas
1137///
1138/// The registry gathers metadata for all types in a schema. It provides
1139/// convenience methods to convert types implementing the `GraphQLType` trait
1140/// into `Type` instances and automatically registers them.
1141pub struct Registry<S = DefaultScalarValue> {
1142    /// Currently registered types
1143    pub types: FnvHashMap<Name, MetaType<S>>,
1144}
1145
1146impl<S> Registry<S> {
1147    /// Constructs a new [`Registry`] out of the given `types`.
1148    pub fn new(types: FnvHashMap<Name, MetaType<S>>) -> Self {
1149        Self { types }
1150    }
1151
1152    /// Returns a [`Type`] instance for the given [`GraphQLType`], registered in this [`Registry`].
1153    ///
1154    /// If this [`Registry`] hasn't seen a [`Type`] with such [`GraphQLType::name`] before, it will
1155    /// construct the one and store it.
1156    pub fn get_type<T>(&mut self, info: &T::TypeInfo) -> Type
1157    where
1158        T: GraphQLType<S> + ?Sized,
1159        S: ScalarValue,
1160    {
1161        if let Some(name) = T::name(info) {
1162            let validated_name = Name::new(name.clone()).unwrap();
1163            if !self.types.contains_key(&name) {
1164                self.insert_placeholder(
1165                    validated_name.clone(),
1166                    Type::nullable(name.clone()).wrap_non_null(),
1167                );
1168                let meta = T::meta(info, self);
1169                self.types.insert(validated_name, meta);
1170            }
1171            self.types[&name].as_type()
1172        } else {
1173            T::meta(info, self).as_type()
1174        }
1175    }
1176
1177    /// Creates a [`Field`] with the provided `name`.
1178    pub fn field<T>(&mut self, name: impl Into<ArcStr>, info: &T::TypeInfo) -> Field<S>
1179    where
1180        T: GraphQLType<S> + ?Sized,
1181        S: ScalarValue,
1182    {
1183        Field {
1184            name: name.into(),
1185            description: None,
1186            arguments: None,
1187            field_type: self.get_type::<T>(info),
1188            deprecation_status: DeprecationStatus::Current,
1189        }
1190    }
1191
1192    #[doc(hidden)]
1193    pub fn field_convert<'a, T: IntoResolvable<'a, S, I, C>, I, C>(
1194        &mut self,
1195        name: impl Into<ArcStr>,
1196        info: &I::TypeInfo,
1197    ) -> Field<S>
1198    where
1199        I: GraphQLType<S>,
1200        S: ScalarValue,
1201    {
1202        Field {
1203            name: name.into(),
1204            description: None,
1205            arguments: None,
1206            field_type: self.get_type::<I>(info),
1207            deprecation_status: DeprecationStatus::Current,
1208        }
1209    }
1210
1211    /// Creates an [`Argument`] with the provided `name`.
1212    pub fn arg<T>(&mut self, name: impl Into<ArcStr>, info: &T::TypeInfo) -> Argument<S>
1213    where
1214        T: GraphQLType<S> + FromInputValue<S>,
1215        S: ScalarValue,
1216    {
1217        Argument::new(name, self.get_type::<T>(info))
1218    }
1219
1220    /// Creates an [`Argument`] with the provided default `value`.
1221    pub fn arg_with_default<T>(
1222        &mut self,
1223        name: impl Into<ArcStr>,
1224        value: &T,
1225        info: &T::TypeInfo,
1226    ) -> Argument<S>
1227    where
1228        T: GraphQLType<S> + ToInputValue<S> + FromInputValue<S>,
1229        S: ScalarValue,
1230    {
1231        Argument::new(name, self.get_type::<T>(info)).default_value(value.to_input_value())
1232    }
1233
1234    fn insert_placeholder(&mut self, name: Name, of_type: Type) {
1235        self.types
1236            .entry(name)
1237            .or_insert(MetaType::Placeholder(PlaceholderMeta { of_type }));
1238    }
1239
1240    /// Creates a [`ScalarMeta`] type.
1241    pub fn build_scalar_type<T>(&mut self, info: &T::TypeInfo) -> ScalarMeta<S>
1242    where
1243        T: GraphQLType<S> + FromInputValue<S> + ParseScalarValue<S>,
1244        T::Error: IntoFieldError<S>,
1245        S: ScalarValue,
1246    {
1247        let name = T::name(info).expect("Scalar types must be named. Implement `name()`");
1248
1249        ScalarMeta::new::<T>(name)
1250    }
1251
1252    /// Creates a [`ListMeta`] type.
1253    ///
1254    /// Specifying `expected_size` will be used to ensure that values of this
1255    /// type will always match it.
1256    pub fn build_list_type<T>(
1257        &mut self,
1258        info: &T::TypeInfo,
1259        expected_size: Option<usize>,
1260    ) -> ListMeta
1261    where
1262        T: GraphQLType<S> + ?Sized,
1263        S: ScalarValue,
1264    {
1265        let of_type = self.get_type::<T>(info);
1266        ListMeta::new(of_type, expected_size)
1267    }
1268
1269    /// Creates a [`NullableMeta`] type.
1270    pub fn build_nullable_type<T>(&mut self, info: &T::TypeInfo) -> NullableMeta
1271    where
1272        T: GraphQLType<S> + ?Sized,
1273        S: ScalarValue,
1274    {
1275        let of_type = self.get_type::<T>(info);
1276        NullableMeta::new(of_type)
1277    }
1278
1279    /// Creates an [`ObjectMeta`] type with the given `fields`.
1280    pub fn build_object_type<T>(&mut self, info: &T::TypeInfo, fields: &[Field<S>]) -> ObjectMeta<S>
1281    where
1282        T: GraphQLType<S> + ?Sized,
1283        S: ScalarValue,
1284    {
1285        let name = T::name(info).expect("Object types must be named. Implement name()");
1286
1287        let mut v = fields.to_vec();
1288        v.push(self.field::<String>(arcstr::literal!("__typename"), &()));
1289        ObjectMeta::new(name, &v)
1290    }
1291
1292    /// Creates an [`EnumMeta`] type out of the provided `values`.
1293    pub fn build_enum_type<T>(&mut self, info: &T::TypeInfo, values: &[EnumValue]) -> EnumMeta<S>
1294    where
1295        T: GraphQLType<S> + FromInputValue<S>,
1296        T::Error: IntoFieldError<S>,
1297        S: ScalarValue,
1298    {
1299        let name = T::name(info).expect("Enum types must be named. Implement `name()`");
1300
1301        EnumMeta::new::<T>(name, values)
1302    }
1303
1304    /// Creates an [`InterfaceMeta`] type with the given `fields`.
1305    pub fn build_interface_type<T>(
1306        &mut self,
1307        info: &T::TypeInfo,
1308        fields: &[Field<S>],
1309    ) -> InterfaceMeta<S>
1310    where
1311        T: GraphQLType<S> + ?Sized,
1312        S: ScalarValue,
1313    {
1314        let name = T::name(info).expect("Interface types must be named. Implement name()");
1315
1316        let mut v = fields.to_vec();
1317        v.push(self.field::<String>(arcstr::literal!("__typename"), &()));
1318        InterfaceMeta::new(name, &v)
1319    }
1320
1321    /// Creates an [`UnionMeta`] type of the given `types`.
1322    pub fn build_union_type<T>(&mut self, info: &T::TypeInfo, types: &[Type]) -> UnionMeta
1323    where
1324        T: GraphQLType<S> + ?Sized,
1325        S: ScalarValue,
1326    {
1327        let name = T::name(info).expect("Union types must be named. Implement name()");
1328
1329        UnionMeta::new(name, types)
1330    }
1331
1332    /// Creates an [`InputObjectMeta`] type with the given `args`.
1333    pub fn build_input_object_type<T>(
1334        &mut self,
1335        info: &T::TypeInfo,
1336        args: &[Argument<S>],
1337    ) -> InputObjectMeta<S>
1338    where
1339        T: GraphQLType<S> + FromInputValue<S>,
1340        T::Error: IntoFieldError<S>,
1341        S: ScalarValue,
1342    {
1343        let name = T::name(info).expect("Input object types must be named. Implement name()");
1344
1345        InputObjectMeta::new::<T>(name, args)
1346    }
1347}