Don't clone selection sets during execution
This commit is contained in:
parent
6a4b883b97
commit
13903d7628
9 changed files with 41 additions and 46 deletions
|
@ -37,7 +37,7 @@ pub enum FieldPath<'a> {
|
||||||
pub struct Executor<'a, CtxT> where CtxT: 'a {
|
pub struct Executor<'a, CtxT> where CtxT: 'a {
|
||||||
fragments: &'a HashMap<&'a str, &'a Fragment>,
|
fragments: &'a HashMap<&'a str, &'a Fragment>,
|
||||||
variables: &'a HashMap<String, InputValue>,
|
variables: &'a HashMap<String, InputValue>,
|
||||||
current_selection_set: Option<Vec<Selection>>,
|
current_selection_set: Option<&'a [Selection]>,
|
||||||
schema: &'a SchemaType,
|
schema: &'a SchemaType,
|
||||||
context: &'a CtxT,
|
context: &'a CtxT,
|
||||||
errors: &'a RwLock<Vec<ExecutionError>>,
|
errors: &'a RwLock<Vec<ExecutionError>>,
|
||||||
|
@ -151,12 +151,7 @@ impl<'a, CtxT> Executor<'a, CtxT> {
|
||||||
|
|
||||||
/// Resolve a single arbitrary value into an `ExecutionResult`
|
/// Resolve a single arbitrary value into an `ExecutionResult`
|
||||||
pub fn resolve<T: GraphQLType<Context=CtxT>>(&self, value: &T) -> ExecutionResult {
|
pub fn resolve<T: GraphQLType<Context=CtxT>>(&self, value: &T) -> ExecutionResult {
|
||||||
Ok(value.resolve(
|
Ok(value.resolve(self.current_selection_set, self))
|
||||||
match self.current_selection_set {
|
|
||||||
Some(ref sel) => Some(sel.clone()),
|
|
||||||
None => None,
|
|
||||||
},
|
|
||||||
self))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve a single arbitrary value into a return value
|
/// Resolve a single arbitrary value into a return value
|
||||||
|
@ -194,7 +189,7 @@ impl<'a, CtxT> Executor<'a, CtxT> {
|
||||||
&self,
|
&self,
|
||||||
field_name: Option<String>,
|
field_name: Option<String>,
|
||||||
location: SourcePosition,
|
location: SourcePosition,
|
||||||
selection_set: Option<Vec<Selection>>,
|
selection_set: Option<&'a [Selection]>,
|
||||||
)
|
)
|
||||||
-> Executor<CtxT>
|
-> Executor<CtxT>
|
||||||
{
|
{
|
||||||
|
@ -339,7 +334,7 @@ pub fn execute_validated_query<'a, QueryT, MutationT, CtxT>(
|
||||||
let executor = Executor {
|
let executor = Executor {
|
||||||
fragments: &fragments.iter().map(|f| (f.item.name.item.as_str(), &f.item)).collect(),
|
fragments: &fragments.iter().map(|f| (f.item.name.item.as_str(), &f.item)).collect(),
|
||||||
variables: variables,
|
variables: variables,
|
||||||
current_selection_set: Some(op.item.selection_set),
|
current_selection_set: Some(&op.item.selection_set[..]),
|
||||||
schema: &root_node.schema,
|
schema: &root_node.schema,
|
||||||
context: context,
|
context: context,
|
||||||
errors: &errors,
|
errors: &errors,
|
||||||
|
|
|
@ -83,7 +83,7 @@ macro_rules! graphql_enum {
|
||||||
.into_meta()
|
.into_meta()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve(&self, _: Option<Vec<$crate::Selection>>, _: &$crate::Executor<Self::Context>) -> $crate::Value {
|
fn resolve(&self, _: Option<&[$crate::Selection]>, _: &$crate::Executor<Self::Context>) -> $crate::Value {
|
||||||
match self {
|
match self {
|
||||||
$(
|
$(
|
||||||
&graphql_enum!(@as_pattern, $eval) =>
|
&graphql_enum!(@as_pattern, $eval) =>
|
||||||
|
|
|
@ -268,7 +268,7 @@ macro_rules! graphql_interface {
|
||||||
fn resolve_into_type(
|
fn resolve_into_type(
|
||||||
&$mainself,
|
&$mainself,
|
||||||
type_name: &str,
|
type_name: &str,
|
||||||
_: Option<Vec<$crate::Selection>>,
|
_: Option<&[$crate::Selection]>,
|
||||||
executor: &$crate::Executor<Self::Context>,
|
executor: &$crate::Executor<Self::Context>,
|
||||||
)
|
)
|
||||||
-> $crate::ExecutionResult
|
-> $crate::ExecutionResult
|
||||||
|
|
|
@ -77,7 +77,7 @@ macro_rules! graphql_scalar {
|
||||||
|
|
||||||
fn resolve(
|
fn resolve(
|
||||||
&$resolve_selfvar,
|
&$resolve_selfvar,
|
||||||
_: Option<Vec<$crate::Selection>>,
|
_: Option<&[$crate::Selection]>,
|
||||||
_: &$crate::Executor<Self::Context>) -> $crate::Value {
|
_: &$crate::Executor<Self::Context>) -> $crate::Value {
|
||||||
$resolve_body
|
$resolve_body
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@ macro_rules! graphql_union {
|
||||||
fn resolve_into_type(
|
fn resolve_into_type(
|
||||||
&$mainself,
|
&$mainself,
|
||||||
type_name: &str,
|
type_name: &str,
|
||||||
_: Option<Vec<$crate::Selection>>,
|
_: Option<&[$crate::Selection]>,
|
||||||
executor: &$crate::Executor<Self::Context>,
|
executor: &$crate::Executor<Self::Context>,
|
||||||
)
|
)
|
||||||
-> $crate::ExecutionResult
|
-> $crate::ExecutionResult
|
||||||
|
|
|
@ -248,7 +248,7 @@ pub trait GraphQLType: Sized {
|
||||||
///
|
///
|
||||||
/// The default implementation panics.
|
/// The default implementation panics.
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn resolve_into_type(&self, type_name: &str, selection_set: Option<Vec<Selection>>, executor: &Executor<Self::Context>) -> ExecutionResult {
|
fn resolve_into_type(&self, type_name: &str, selection_set: Option<&[Selection]>, executor: &Executor<Self::Context>) -> ExecutionResult {
|
||||||
if Self::name().unwrap() == type_name {
|
if Self::name().unwrap() == type_name {
|
||||||
Ok(self.resolve(selection_set, executor))
|
Ok(self.resolve(selection_set, executor))
|
||||||
} else {
|
} else {
|
||||||
|
@ -274,7 +274,7 @@ pub trait GraphQLType: Sized {
|
||||||
/// The default implementation uses `resolve_field` to resolve all fields,
|
/// The default implementation uses `resolve_field` to resolve all fields,
|
||||||
/// including those through fragment expansion, for object types. For
|
/// including those through fragment expansion, for object types. For
|
||||||
/// non-object types, this method panics.
|
/// non-object types, this method panics.
|
||||||
fn resolve(&self, selection_set: Option<Vec<Selection>>, executor: &Executor<Self::Context>) -> Value {
|
fn resolve(&self, selection_set: Option<&[Selection]>, executor: &Executor<Self::Context>) -> Value {
|
||||||
if let Some(selection_set) = selection_set {
|
if let Some(selection_set) = selection_set {
|
||||||
let mut result = HashMap::new();
|
let mut result = HashMap::new();
|
||||||
resolve_selection_set_into(self, selection_set, executor, &mut result);
|
resolve_selection_set_into(self, selection_set, executor, &mut result);
|
||||||
|
@ -288,7 +288,7 @@ pub trait GraphQLType: Sized {
|
||||||
|
|
||||||
fn resolve_selection_set_into<T, CtxT>(
|
fn resolve_selection_set_into<T, CtxT>(
|
||||||
instance: &T,
|
instance: &T,
|
||||||
selection_set: Vec<Selection>,
|
selection_set: &[Selection],
|
||||||
executor: &Executor<CtxT>,
|
executor: &Executor<CtxT>,
|
||||||
result: &mut HashMap<String, Value>)
|
result: &mut HashMap<String, Value>)
|
||||||
where T: GraphQLType<Context=CtxT>
|
where T: GraphQLType<Context=CtxT>
|
||||||
|
@ -299,11 +299,11 @@ fn resolve_selection_set_into<T, CtxT>(
|
||||||
|
|
||||||
for selection in selection_set {
|
for selection in selection_set {
|
||||||
match selection {
|
match selection {
|
||||||
Selection::Field(Spanning { item: f, start: start_pos, .. }) => {
|
&Selection::Field(Spanning { item: ref f, start: ref start_pos, .. }) => {
|
||||||
if is_excluded(
|
if is_excluded(
|
||||||
&match f.directives {
|
&match &f.directives {
|
||||||
Some(sel) => Some(sel.iter().cloned().map(|s| s.item).collect()),
|
&Some(ref sel) => Some(sel.iter().cloned().map(|s| s.item).collect()),
|
||||||
None => None,
|
&None => None,
|
||||||
},
|
},
|
||||||
executor.variables()) {
|
executor.variables()) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -327,13 +327,13 @@ fn resolve_selection_set_into<T, CtxT>(
|
||||||
let mut sub_exec = executor.sub_executor(
|
let mut sub_exec = executor.sub_executor(
|
||||||
Some(response_name.clone()),
|
Some(response_name.clone()),
|
||||||
start_pos.clone(),
|
start_pos.clone(),
|
||||||
f.selection_set);
|
f.selection_set.as_ref().map(|v| &v[..]));
|
||||||
|
|
||||||
let field_result = instance.resolve_field(
|
let field_result = instance.resolve_field(
|
||||||
&f.name.item,
|
&f.name.item,
|
||||||
&Arguments::new(
|
&Arguments::new(
|
||||||
f.arguments.map(|m|
|
f.arguments.as_ref().map(|m|
|
||||||
m.item.into_iter().map(|(k, v)|
|
m.item.iter().cloned().map(|(k, v)|
|
||||||
(k.item, v.item.into_const(exec_vars))).collect()),
|
(k.item, v.item.into_const(exec_vars))).collect()),
|
||||||
&meta_field.arguments),
|
&meta_field.arguments),
|
||||||
&mut sub_exec);
|
&mut sub_exec);
|
||||||
|
@ -341,16 +341,16 @@ fn resolve_selection_set_into<T, CtxT>(
|
||||||
match field_result {
|
match field_result {
|
||||||
Ok(v) => merge_key_into(result, response_name.clone(), v),
|
Ok(v) => merge_key_into(result, response_name.clone(), v),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
sub_exec.push_error(e, start_pos);
|
sub_exec.push_error(e, start_pos.clone());
|
||||||
result.insert(response_name.clone(), Value::null());
|
result.insert(response_name.clone(), Value::null());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Selection::FragmentSpread(Spanning { item: spread, .. }) => {
|
&Selection::FragmentSpread(Spanning { item: ref spread, .. }) => {
|
||||||
if is_excluded(
|
if is_excluded(
|
||||||
&match spread.directives {
|
&match &spread.directives {
|
||||||
Some(sel) => Some(sel.iter().cloned().map(|s| s.item).collect()),
|
&Some(ref sel) => Some(sel.iter().cloned().map(|s| s.item).collect()),
|
||||||
None => None,
|
&None => None,
|
||||||
},
|
},
|
||||||
executor.variables()) {
|
executor.variables()) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -360,13 +360,13 @@ fn resolve_selection_set_into<T, CtxT>(
|
||||||
.expect("Fragment could not be found");
|
.expect("Fragment could not be found");
|
||||||
|
|
||||||
resolve_selection_set_into(
|
resolve_selection_set_into(
|
||||||
instance, fragment.selection_set.clone(), executor, result);
|
instance, &fragment.selection_set[..], executor, result);
|
||||||
},
|
},
|
||||||
Selection::InlineFragment(Spanning { item: fragment, start: start_pos, .. }) => {
|
&Selection::InlineFragment(Spanning { item: ref fragment, start: ref start_pos, .. }) => {
|
||||||
if is_excluded(
|
if is_excluded(
|
||||||
&match fragment.directives {
|
&match &fragment.directives {
|
||||||
Some(sel) => Some(sel.iter().cloned().map(|s| s.item).collect()),
|
&Some(ref sel) => Some(sel.iter().cloned().map(|s| s.item).collect()),
|
||||||
None => None
|
&None => None
|
||||||
},
|
},
|
||||||
executor.variables()) {
|
executor.variables()) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -375,12 +375,12 @@ fn resolve_selection_set_into<T, CtxT>(
|
||||||
let mut sub_exec = executor.sub_executor(
|
let mut sub_exec = executor.sub_executor(
|
||||||
None,
|
None,
|
||||||
start_pos.clone(),
|
start_pos.clone(),
|
||||||
Some(fragment.selection_set.clone()));
|
Some(&fragment.selection_set[..]));
|
||||||
|
|
||||||
if let Some(type_condition) = fragment.type_condition {
|
if let &Some(ref type_condition) = &fragment.type_condition {
|
||||||
let sub_result = instance.resolve_into_type(
|
let sub_result = instance.resolve_into_type(
|
||||||
&type_condition.item,
|
&type_condition.item,
|
||||||
Some(fragment.selection_set.clone()),
|
Some(&fragment.selection_set[..]),
|
||||||
&mut sub_exec);
|
&mut sub_exec);
|
||||||
|
|
||||||
if let Ok(Value::Object(mut hash_map)) = sub_result {
|
if let Ok(Value::Object(mut hash_map)) = sub_result {
|
||||||
|
@ -389,13 +389,13 @@ fn resolve_selection_set_into<T, CtxT>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if let Err(e) = sub_result {
|
else if let Err(e) = sub_result {
|
||||||
sub_exec.push_error(e, start_pos);
|
sub_exec.push_error(e, start_pos.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
resolve_selection_set_into(
|
resolve_selection_set_into(
|
||||||
instance,
|
instance,
|
||||||
fragment.selection_set.clone(),
|
&fragment.selection_set[..],
|
||||||
&mut sub_exec,
|
&mut sub_exec,
|
||||||
result);
|
result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ impl<T, CtxT> GraphQLType for Option<T> where T: GraphQLType<Context=CtxT> {
|
||||||
registry.build_nullable_type::<T>().into_meta()
|
registry.build_nullable_type::<T>().into_meta()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve(&self, _: Option<Vec<Selection>>, executor: &Executor<CtxT>) -> Value {
|
fn resolve(&self, _: Option<&[Selection]>, executor: &Executor<CtxT>) -> Value {
|
||||||
match *self {
|
match *self {
|
||||||
Some(ref obj) => executor.resolve_into_value(obj),
|
Some(ref obj) => executor.resolve_into_value(obj),
|
||||||
None => Value::null(),
|
None => Value::null(),
|
||||||
|
@ -56,7 +56,7 @@ impl<T, CtxT> GraphQLType for Vec<T> where T: GraphQLType<Context=CtxT> {
|
||||||
registry.build_list_type::<T>().into_meta()
|
registry.build_list_type::<T>().into_meta()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve(&self, _: Option<Vec<Selection>>, executor: &Executor<CtxT>) -> Value {
|
fn resolve(&self, _: Option<&[Selection]>, executor: &Executor<CtxT>) -> Value {
|
||||||
Value::list(
|
Value::list(
|
||||||
self.iter().map(|e| executor.resolve_into_value(e)).collect()
|
self.iter().map(|e| executor.resolve_into_value(e)).collect()
|
||||||
)
|
)
|
||||||
|
@ -103,7 +103,7 @@ impl<'a, T, CtxT> GraphQLType for &'a [T] where T: GraphQLType<Context=CtxT> {
|
||||||
registry.build_list_type::<T>().into_meta()
|
registry.build_list_type::<T>().into_meta()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve(&self, _: Option<Vec<Selection>>, executor: &Executor<CtxT>) -> Value {
|
fn resolve(&self, _: Option<&[Selection]>, executor: &Executor<CtxT>) -> Value {
|
||||||
Value::list(
|
Value::list(
|
||||||
self.iter().map(|e| executor.resolve_into_value(e)).collect()
|
self.iter().map(|e| executor.resolve_into_value(e)).collect()
|
||||||
)
|
)
|
||||||
|
|
|
@ -16,7 +16,7 @@ impl<T, CtxT> GraphQLType for Box<T> where T: GraphQLType<Context=CtxT> {
|
||||||
T::meta(registry)
|
T::meta(registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_into_type(&self, name: &str, selection_set: Option<Vec<Selection>>, executor: &Executor<CtxT>) -> ExecutionResult {
|
fn resolve_into_type(&self, name: &str, selection_set: Option<&[Selection]>, executor: &Executor<CtxT>) -> ExecutionResult {
|
||||||
(**self).resolve_into_type(name, selection_set, executor)
|
(**self).resolve_into_type(name, selection_set, executor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ impl<T, CtxT> GraphQLType for Box<T> where T: GraphQLType<Context=CtxT> {
|
||||||
(**self).resolve_field(field, args, executor)
|
(**self).resolve_field(field, args, executor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve(&self, selection_set: Option<Vec<Selection>>, executor: &Executor<CtxT>) -> Value {
|
fn resolve(&self, selection_set: Option<&[Selection]>, executor: &Executor<CtxT>) -> Value {
|
||||||
(**self).resolve(selection_set, executor)
|
(**self).resolve(selection_set, executor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ impl<'a, T, CtxT> GraphQLType for &'a T where T: GraphQLType<Context=CtxT> {
|
||||||
T::meta(registry)
|
T::meta(registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_into_type(&self, name: &str, selection_set: Option<Vec<Selection>>, executor: &Executor<CtxT>) -> ExecutionResult {
|
fn resolve_into_type(&self, name: &str, selection_set: Option<&[Selection]>, executor: &Executor<CtxT>) -> ExecutionResult {
|
||||||
(**self).resolve_into_type(name, selection_set, executor)
|
(**self).resolve_into_type(name, selection_set, executor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ impl<'a, T, CtxT> GraphQLType for &'a T where T: GraphQLType<Context=CtxT> {
|
||||||
(**self).resolve_field(field, args, executor)
|
(**self).resolve_field(field, args, executor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve(&self, selection_set: Option<Vec<Selection>>, executor: &Executor<CtxT>) -> Value {
|
fn resolve(&self, selection_set: Option<&[Selection]>, executor: &Executor<CtxT>) -> Value {
|
||||||
(**self).resolve(selection_set, executor)
|
(**self).resolve(selection_set, executor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ impl<'a> GraphQLType for &'a str {
|
||||||
registry.build_scalar_type::<String>().into_meta()
|
registry.build_scalar_type::<String>().into_meta()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve(&self, _: Option<Vec<Selection>>, _: &Executor<Self::Context>) -> Value {
|
fn resolve(&self, _: Option<&[Selection]>, _: &Executor<Self::Context>) -> Value {
|
||||||
Value::string(self)
|
Value::string(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue