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