fn selection_set_to_paths<A: AsAid + From<String>>(
    selection_set: &SelectionSet,
    mut plan: Hector<A>,
    arguments: &[(Name, Value)],
    parent_path: &[A],
) -> Vec<Plan<A>> {
    // We must first construct the correct plan for this level,
    // starting from that for the parent level. We do this even if no
    // attributes are actually pulled at this level. In that case we
    // will not synthesize this plan, but it still is required in
    // order to pass all necessary bindings to nested levels.

    // For any level after the first, we must introduce a binding
    // linking the parent level to the current one.
    if !parent_path.is_empty() {
        let parent = *plan.variables.last().unwrap();
        let this = plan.variables.len() as Var;
        let aid = parent_path.last().unwrap();

        plan.variables.push(this);
        plan.bindings
            .push(Binding::attribute(parent, A::from(aid.to_string()), this));
    }

    let this = *plan.variables.last().unwrap();

    // Then we must introduce additional bindings for any arguments.
    for (aid, v) in arguments.iter() {
        // This variable is only relevant for tying the two clauses
        // together, we do not want to include it into the output
        // projection.
        let vsym = gensym();

        plan.bindings
            .push(Binding::attribute(this, A::from(aid.to_string()), vsym));
        plan.bindings
            .push(Binding::constant(vsym, v.clone().into()));
    }

    // We will first gather the attributes that need to be retrieved
    // at this level. These are the fields that do not refer to a
    // nested entity. This is the easy part.
    let pull_attributes = pull_attributes(selection_set);

    // Now we process nested levels.
    let nested_levels = selection_set
        .items
        .iter()
        .flat_map(|item| match item {
            Selection::Field(field) => {
                if !field.selection_set.items.is_empty() {
                    let mut parent_path = parent_path.to_vec();
                    parent_path.push(A::from(field.name.to_string()));

                    selection_set_to_paths(
                        &field.selection_set,
                        plan.clone(),
                        &field.arguments,
                        &parent_path,
                    )
                } else {
                    vec![]
                }
            }
            _ => unimplemented!(),
        })
        .collect::<Vec<Plan<A>>>();

    let mut levels = nested_levels;

    // Here we don't actually want to include the current plan, if
    // we're not interested in any attributes at this level.
    if !pull_attributes.is_empty() {
        if plan.bindings.is_empty() {
            levels.push(Plan::PullAll(PullAll {
                variables: vec![],
                pull_attributes,
            }));
        } else {
            levels.push(Plan::PullLevel(PullLevel {
                pull_attributes,
                path_attributes: parent_path.to_vec(),
                pull_variable: this,
                variables: vec![],
                plan: Box::new(Plan::Hector(plan)),
                cardinality_many: false,
            }));
        }
    }

    levels
}
/// Takes a GraphQL `SelectionSet` and recursively transforms it into
/// `PullLevel`s.
///
/// A `SelectionSet` consists of multiple items. We're interested in
/// items of type `Field`, which might contain a nested `SelectionSet`
/// themselves. We iterate through each field and construct (1) a
/// parent path, which describes how to traverse to the current
/// nesting level ("vertical"), and (2) pull attributes, which
/// describe the attributes pulled at the current nesting level
/// ("horizontal"); only attributes at the lowest nesting level can be
/// part of a `PullLevel`'s `pull_attributes`.
Takes a GraphQL `SelectionSet` and recursively transforms it into
`PullLevel`s.

A `SelectionSet` consists of multiple items. We're interested in
items of type `Field`, which might contain a nested `SelectionSet`
themselves. We iterate through each field and construct (1) a
parent path, which describes how to traverse to the current
nesting level ("vertical"), and (2) pull attributes, which
describe the attributes pulled at the current nesting level
("horizontal"); only attributes at the lowest nesting level can be
part of a `PullLevel`'s `pull_attributes`.
Takes a GraphQL ` SelectionSet ` and recursively transforms it into ` PullLevel ` s . A ` SelectionSet ` consists of multiple items . We ' re interested in items of type ` Field ` which might contain a nested ` SelectionSet ` themselves . We iterate through each field and construct ( 1 ) a parent path which describes how to traverse to the current nesting level ( " vertical " ) and ( 2 ) pull attributes which describe the attributes pulled at the current nesting level ( " horizontal " ) ; only attributes at the lowest nesting level can be part of a ` PullLevel ` ' s ` pull_attributes ` .
fn selection_set_to_paths<A: AsAid + From<String>>(
    selection_set: &SelectionSet,
    mut plan: Hector<A>,
    arguments: &[(Name, Value)],
    parent_path: &[A],
) -> Vec<Plan<A>> {
    // We must first construct the correct plan for this level,
    // starting from that for the parent level. We do this even if no
    // attributes are actually pulled at this level. In that case we
    // will not synthesize this plan, but it still is required in
    // order to pass all necessary bindings to nested levels.
    // For any level after the first, we must introduce a binding
    // linking the parent level to the current one.
    if !parent_path.is_empty() {
        let parent = *plan.variables.last().unwrap();
        let this = plan.variables.len() as Var;
        let aid = parent_path.last().unwrap();
        plan.variables.push(this);
        plan.bindings
            .push(Binding::attribute(parent, A::from(aid.to_string()), this));
    }
    let this = *plan.variables.last().unwrap();
    // Then we must introduce additional bindings for any arguments.
    for (aid, v) in arguments.iter() {
        // This variable is only relevant for tying the two clauses
        // together, we do not want to include it into the output
        // projection.
        let vsym = gensym();
        plan.bindings
            .push(Binding::attribute(this, A::from(aid.to_string()), vsym));
        plan.bindings
            .push(Binding::constant(vsym, v.clone().into()));
    }
    // We will first gather the attributes that need to be retrieved
    // at this level. These are the fields that do not refer to a
    // nested entity. This is the easy part.
    let pull_attributes = pull_attributes(selection_set);
    // Now we process nested levels.
    let nested_levels = selection_set
        .items
        .iter()
        .flat_map(|item| match item {
            Selection::Field(field) => {
                if !field.selection_set.items.is_empty() {
                    let mut parent_path = parent_path.to_vec();
                    parent_path.push(A::from(field.name.to_string()));
                    selection_set_to_paths(
                        &field.selection_set,
                        plan.clone(),
                        &field.arguments,
                        &parent_path,
                    )
                } else {
                    vec![]
                }
            }
            _ => unimplemented!(),
        })
        .collect::<Vec<Plan<A>>>();
    let mut levels = nested_levels;
    // Here we don't actually want to include the current plan, if
    // we're not interested in any attributes at this level.
    if !pull_attributes.is_empty() {
        if plan.bindings.is_empty() {
            levels.push(Plan::PullAll(PullAll {
                variables: vec![],
                pull_attributes,
            }));
        } else {
            levels.push(Plan::PullLevel(PullLevel {
                pull_attributes,
                path_attributes: parent_path.to_vec(),
                pull_variable: this,
                variables: vec![],
                plan: Box::new(Plan::Hector(plan)),
                cardinality_many: false,
            }));
        }
    }
    levels
}
fn selection_set_to_paths < A : AsAid + From < String > > ( selection_set : & SelectionSet , mut plan : Hector < A > , arguments : & [ ( Name , Value ) ] , parent_path : & [ A ] , ) -> Vec < Plan < A > > { // We must first construct the correct plan for this level, // starting from that for the parent level. We do this even if no // attributes are actually pulled at this level. In that case we // will not synthesize this plan, but it still is required in // order to pass all necessary bindings to nested levels. // For any level after the first, we must introduce a binding // linking the parent level to the current one. if ! parent_path . is_empty ( ) { let parent = * plan . variables . last ( ) . unwrap ( ) ; let this = plan . variables . len ( ) as Var ; let aid = parent_path . last ( ) . unwrap ( ) ; plan . variables . push ( this ) ; plan . bindings . push ( Binding :: attribute ( parent , A :: from ( aid . to_string ( ) ) , this ) ) ; } let this = * plan . variables . last ( ) . unwrap ( ) ; // Then we must introduce additional bindings for any arguments. for ( aid , v ) in arguments . iter ( ) { // This variable is only relevant for tying the two clauses // together, we do not want to include it into the output // projection. let vsym = gensym ( ) ; plan . bindings . push ( Binding :: attribute ( this , A :: from ( aid . to_string ( ) ) , vsym ) ) ; plan . bindings . push ( Binding :: constant ( vsym , v . clone ( ) . into ( ) ) ) ; } // We will first gather the attributes that need to be retrieved // at this level. These are the fields that do not refer to a // nested entity. This is the easy part. let pull_attributes = pull_attributes ( selection_set ) ; // Now we process nested levels. let nested_levels = selection_set . items . iter ( ) . flat_map ( | item | match item { Selection :: Field ( field ) => { if ! field . selection_set . items . is_empty ( ) { let mut parent_path = parent_path . to_vec ( ) ; parent_path . push ( A :: from ( field . name . to_string ( ) ) ) ; selection_set_to_paths ( & field . selection_set , plan . clone ( ) , & field . arguments , & parent_path , ) } else { vec ! [ ] } } _ => unimplemented ! ( ) , } ) . collect :: < Vec < Plan < A > > > ( ) ; let mut levels = nested_levels ; // Here we don't actually want to include the current plan, if // we're not interested in any attributes at this level. if ! pull_attributes . is_empty ( ) { if plan . bindings . is_empty ( ) { levels . push ( Plan :: PullAll ( PullAll { variables : vec ! [ ] , pull_attributes , } ) ) ; } else { levels . push ( Plan :: PullLevel ( PullLevel { pull_attributes , path_attributes : parent_path . to_vec ( ) , pull_variable : this , variables : vec ! [ ] , plan : Box :: new ( Plan :: Hector ( plan ) ) , cardinality_many : false , } ) ) ; } } levels }
Takes a GraphQL `SelectionSet` and recursively transforms it into
`PullLevel`s.
Takes a GraphQL ` SelectionSet ` and recursively transforms it into ` PullLevel ` s .
selection_set
&SelectionSet
plan
Hector<A>
arguments
&[(Name, Value)]
parent_path
&[A]
selection_set
&SelectionSet
plan
Hector<A>
arguments
&[(Name, Value)]
parent_path
&[A]