Skip to content

Commit f4185c1

Browse files
committed
graph, graphql: Resolve variables before executing query
1 parent 4b5ca34 commit f4185c1

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
@@ -184,7 +184,7 @@ pub mod prelude {
184184
static_graphql!(q, query, {
185185
Document, Value, OperationDefinition, InlineFragment, TypeCondition,
186186
FragmentSpread, Field, Selection, SelectionSet, FragmentDefinition,
187-
Directive, VariableDefinition, Type,
187+
Directive, VariableDefinition, Type, Query,
188188
});
189189
static_graphql!(s, schema, {
190190
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
@@ -18,6 +18,7 @@ use graph::data::schema::ApiSchema;
1818
use graph::prelude::{info, o, q, r, s, BlockNumber, CheapClone, Logger, TryFromValue};
1919

2020
use crate::introspection::introspection_schema;
21+
use crate::query::ext::ValueExt;
2122
use crate::query::{ast as qast, ext::BlockConstraint};
2223
use crate::schema::ast as sast;
2324
use crate::{
@@ -214,7 +215,7 @@ impl Query {
214215
let start = Instant::now();
215216
// Use an intermediate struct so we can modify the query before
216217
// enclosing it in an Arc
217-
let raw_query = RawQuery {
218+
let mut raw_query = RawQuery {
218219
schema,
219220
variables,
220221
selection_set,
@@ -226,6 +227,7 @@ impl Query {
226227
// overflow from invalid queries.
227228
let complexity = raw_query.check_complexity(max_complexity, max_depth)?;
228229
raw_query.validate_fields()?;
230+
raw_query.expand_variables()?;
229231

230232
let query = Self {
231233
schema: raw_query.schema,
@@ -726,4 +728,97 @@ impl RawQuery {
726728
errors
727729
})
728730
}
731+
732+
fn expand_variables(&mut self) -> Result<(), QueryExecutionError> {
733+
fn expand_field(
734+
field: &mut q::Field,
735+
vars: &HashMap<String, r::Value>,
736+
) -> Result<(), QueryExecutionError> {
737+
expand_arguments(&mut field.arguments, &field.position, vars)?;
738+
expand_directives(&mut field.directives, vars)?;
739+
expand_selection_set(&mut field.selection_set, vars)
740+
}
741+
742+
fn expand_selection_set(
743+
set: &mut q::SelectionSet,
744+
vars: &HashMap<String, r::Value>,
745+
) -> Result<(), QueryExecutionError> {
746+
for sel in &mut set.items {
747+
match sel {
748+
q::Selection::Field(field) => expand_field(field, vars)?,
749+
q::Selection::FragmentSpread(spread) => {
750+
expand_directives(&mut spread.directives, vars)?;
751+
}
752+
q::Selection::InlineFragment(frag) => {
753+
expand_directives(&mut frag.directives, vars)?;
754+
expand_selection_set(&mut frag.selection_set, vars)?;
755+
}
756+
}
757+
}
758+
Ok(())
759+
}
760+
761+
fn expand_directives(
762+
dirs: &mut Vec<q::Directive>,
763+
vars: &HashMap<String, r::Value>,
764+
) -> Result<(), QueryExecutionError> {
765+
for dir in dirs {
766+
expand_arguments(&mut dir.arguments, &dir.position, vars)?;
767+
}
768+
Ok(())
769+
}
770+
771+
fn expand_arguments(
772+
args: &mut Vec<(String, q::Value)>,
773+
pos: &Pos,
774+
vars: &HashMap<String, r::Value>,
775+
) -> Result<(), QueryExecutionError> {
776+
for arg in args {
777+
expand_value(&mut arg.1, pos, vars)?;
778+
}
779+
Ok(())
780+
}
781+
782+
fn expand_value(
783+
val: &mut q::Value,
784+
pos: &Pos,
785+
vars: &HashMap<String, r::Value>,
786+
) -> Result<(), QueryExecutionError> {
787+
match val {
788+
q::Value::Variable(ref var) => {
789+
let newval = match vars.get(var) {
790+
Some(val) => q::Value::from(val.clone()),
791+
None => {
792+
return Err(QueryExecutionError::MissingVariableError(
793+
pos.clone(),
794+
var.to_string(),
795+
))
796+
}
797+
};
798+
*val = newval;
799+
Ok(())
800+
}
801+
q::Value::Int(_)
802+
| q::Value::Float(_)
803+
| q::Value::String(_)
804+
| q::Value::Boolean(_)
805+
| q::Value::Null
806+
| q::Value::Enum(_) => Ok(()),
807+
q::Value::List(ref mut vals) => {
808+
for mut val in vals.iter_mut() {
809+
expand_value(&mut val, pos, vars)?;
810+
}
811+
Ok(())
812+
}
813+
q::Value::Object(obj) => {
814+
for mut val in obj.values_mut() {
815+
expand_value(&mut val, pos, vars)?;
816+
}
817+
Ok(())
818+
}
819+
}
820+
}
821+
822+
expand_selection_set(&mut self.selection_set, &self.variables)
823+
}
729824
}

0 commit comments

Comments
 (0)