Skip to content

Commit 6dc097a

Browse files
committed
graph, graphql: Resolve variables before executing query
1 parent 9086736 commit 6dc097a

File tree

4 files changed

+105
-3
lines changed

4 files changed

+105
-3
lines changed

graph/src/data/graphql/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@ pub use object_or_interface::ObjectOrInterface;
3131
pub mod object_macro;
3232
pub use crate::object;
3333
pub use object_macro::{object_value, IntoValue};
34+
pub mod visitor;

graph/src/data/value.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::collections::BTreeMap;
55
use std::convert::TryFrom;
66
use std::iter::FromIterator;
77

8-
#[derive(Debug, Clone, PartialEq)]
8+
#[derive(Clone, PartialEq)]
99
pub struct Object(BTreeMap<String, Value>);
1010

1111
impl Object {
@@ -76,6 +76,12 @@ impl Default for Object {
7676
}
7777
}
7878

79+
impl std::fmt::Debug for Object {
80+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81+
self.0.fmt(f)
82+
}
83+
}
84+
7985
#[derive(Debug, Clone, PartialEq)]
8086
pub enum Value {
8187
Int(i64),

graph/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ pub mod prelude {
190190
static_graphql!(q, query, {
191191
Document, Value, OperationDefinition, InlineFragment, TypeCondition,
192192
FragmentSpread, Field, Selection, SelectionSet, FragmentDefinition,
193-
Directive, VariableDefinition, Type,
193+
Directive, VariableDefinition, Type, Query,
194194
});
195195
static_graphql!(s, schema, {
196196
Field, Directive, InterfaceType, ObjectType, Value, TypeDefinition,

graphql/src/execution/query.rs

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use graph::prelude::{
1616
};
1717

1818
use crate::introspection::introspection_schema;
19+
use crate::query::ext::ValueExt;
1920
use crate::query::{ast as qast, ext::BlockConstraint};
2021
use crate::schema::ast as sast;
2122
use crate::{
@@ -162,7 +163,7 @@ impl Query {
162163
let start = Instant::now();
163164
// Use an intermediate struct so we can modify the query before
164165
// enclosing it in an Arc
165-
let raw_query = RawQuery {
166+
let mut raw_query = RawQuery {
166167
schema,
167168
variables,
168169
selection_set,
@@ -174,6 +175,7 @@ impl Query {
174175
// overflow from invalid queries.
175176
let complexity = raw_query.check_complexity(max_complexity, max_depth)?;
176177
raw_query.validate_fields()?;
178+
raw_query.expand_variables()?;
177179

178180
let query = Self {
179181
schema: raw_query.schema,
@@ -674,4 +676,97 @@ impl RawQuery {
674676
errors
675677
})
676678
}
679+
680+
fn expand_variables(&mut self) -> Result<(), QueryExecutionError> {
681+
fn expand_field(
682+
field: &mut q::Field,
683+
vars: &HashMap<String, r::Value>,
684+
) -> Result<(), QueryExecutionError> {
685+
expand_arguments(&mut field.arguments, &field.position, vars)?;
686+
expand_directives(&mut field.directives, vars)?;
687+
expand_selection_set(&mut field.selection_set, vars)
688+
}
689+
690+
fn expand_selection_set(
691+
set: &mut q::SelectionSet,
692+
vars: &HashMap<String, r::Value>,
693+
) -> Result<(), QueryExecutionError> {
694+
for sel in &mut set.items {
695+
match sel {
696+
q::Selection::Field(field) => expand_field(field, vars)?,
697+
q::Selection::FragmentSpread(spread) => {
698+
expand_directives(&mut spread.directives, vars)?;
699+
}
700+
q::Selection::InlineFragment(frag) => {
701+
expand_directives(&mut frag.directives, vars)?;
702+
expand_selection_set(&mut frag.selection_set, vars)?;
703+
}
704+
}
705+
}
706+
Ok(())
707+
}
708+
709+
fn expand_directives(
710+
dirs: &mut Vec<q::Directive>,
711+
vars: &HashMap<String, r::Value>,
712+
) -> Result<(), QueryExecutionError> {
713+
for dir in dirs {
714+
expand_arguments(&mut dir.arguments, &dir.position, vars)?;
715+
}
716+
Ok(())
717+
}
718+
719+
fn expand_arguments(
720+
args: &mut Vec<(String, q::Value)>,
721+
pos: &Pos,
722+
vars: &HashMap<String, r::Value>,
723+
) -> Result<(), QueryExecutionError> {
724+
for arg in args {
725+
expand_value(&mut arg.1, pos, vars)?;
726+
}
727+
Ok(())
728+
}
729+
730+
fn expand_value(
731+
val: &mut q::Value,
732+
pos: &Pos,
733+
vars: &HashMap<String, r::Value>,
734+
) -> Result<(), QueryExecutionError> {
735+
match val {
736+
q::Value::Variable(ref var) => {
737+
let newval = match vars.get(var) {
738+
Some(val) => q::Value::from(val.clone()),
739+
None => {
740+
return Err(QueryExecutionError::MissingVariableError(
741+
pos.clone(),
742+
var.to_string(),
743+
))
744+
}
745+
};
746+
*val = newval;
747+
Ok(())
748+
}
749+
q::Value::Int(_)
750+
| q::Value::Float(_)
751+
| q::Value::String(_)
752+
| q::Value::Boolean(_)
753+
| q::Value::Null
754+
| q::Value::Enum(_) => Ok(()),
755+
q::Value::List(ref mut vals) => {
756+
for mut val in vals.iter_mut() {
757+
expand_value(&mut val, pos, vars)?;
758+
}
759+
Ok(())
760+
}
761+
q::Value::Object(obj) => {
762+
for mut val in obj.values_mut() {
763+
expand_value(&mut val, pos, vars)?;
764+
}
765+
Ok(())
766+
}
767+
}
768+
}
769+
770+
expand_selection_set(&mut self.selection_set, &self.variables)
771+
}
677772
}

0 commit comments

Comments
 (0)