Skip to content

Commit 215adc5

Browse files
committed
Revert "graph, graphql: Optimize away unneeded child queries"
This reverts commit 2d6c531.
1 parent 452bec5 commit 215adc5

File tree

3 files changed

+9
-133
lines changed

3 files changed

+9
-133
lines changed

graph/src/components/store/mod.rs

Lines changed: 1 addition & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::blockchain::Block;
3030
use crate::components::store::write::EntityModification;
3131
use crate::data::store::scalar::Bytes;
3232
use crate::data::store::*;
33-
use crate::data::value::{Object, Word};
33+
use crate::data::value::Word;
3434
use crate::data_source::CausalityRegion;
3535
use crate::schema::InputSchema;
3636
use crate::util::intern;
@@ -483,84 +483,6 @@ pub enum EntityLink {
483483
Parent(EntityType, ParentLink),
484484
}
485485

486-
impl EntityLink {
487-
/// Return a list of objects that have only the `id`, parent id, and
488-
/// typename set using the child ids from `self` when `self` is
489-
/// `Parent`. If `self` is `Direct`, return `None`
490-
///
491-
/// The list that is returned is sorted and truncated to `first` many
492-
/// entries.
493-
///
494-
/// This makes it possible to avoid running a query when all that is
495-
/// needed is the `id` of the children
496-
pub fn to_basic_objects(self, parents: &Vec<String>, first: usize) -> Option<Vec<Object>> {
497-
use crate::data::value::Value as V;
498-
499-
fn basic_object(entity_type: &EntityType, parent: &str, child: String) -> Object {
500-
let mut obj = Vec::new();
501-
obj.push((ID.clone(), V::String(child)));
502-
obj.push((Word::from("__typename"), V::String(entity_type.to_string())));
503-
obj.push((PARENT_ID.clone(), V::String(parent.to_string())));
504-
Object::from_iter(obj)
505-
}
506-
507-
fn basic_objects(
508-
entity_type: &EntityType,
509-
parent: &str,
510-
children: Vec<String>,
511-
) -> Vec<Object> {
512-
children
513-
.into_iter()
514-
.map(|child| basic_object(entity_type, parent, child))
515-
.collect()
516-
}
517-
518-
fn obj_key<'a>(obj: &'a Object) -> Option<(&'a str, &'a str)> {
519-
match (obj.get(&*PARENT_ID), obj.get(ID.as_str())) {
520-
(Some(V::String(p)), Some(V::String(id))) => Some((p, id)),
521-
_ => None,
522-
}
523-
}
524-
525-
fn obj_cmp(a: &Object, b: &Object) -> std::cmp::Ordering {
526-
obj_key(a).cmp(&obj_key(b))
527-
}
528-
529-
match self {
530-
EntityLink::Direct(_, _) => return None,
531-
EntityLink::Parent(entity_type, link) => {
532-
let mut objects = Vec::new();
533-
match link {
534-
ParentLink::List(ids) => {
535-
for (parent, children) in parents.iter().zip(ids) {
536-
objects.extend(basic_objects(&entity_type, parent, children));
537-
}
538-
}
539-
ParentLink::Scalar(ids) => {
540-
for (parent, child) in parents.iter().zip(ids) {
541-
if let Some(child) = child {
542-
objects.push(basic_object(&entity_type, parent, child));
543-
}
544-
}
545-
}
546-
}
547-
// Sort the objects by parent id and child id just as
548-
// running a query would
549-
objects.sort_by(obj_cmp);
550-
objects.truncate(first);
551-
Some(objects)
552-
}
553-
}
554-
}
555-
556-
pub fn has_child_ids(&self) -> bool {
557-
match self {
558-
EntityLink::Direct(_, _) => false,
559-
EntityLink::Parent(_, _) => true,
560-
}
561-
}
562-
}
563-
564486
/// Window results of an `EntityQuery` query along the parent's id:
565487
/// the `order_by`, `order_direction`, and `range` of the query apply to
566488
/// entities that belong to the same parent. Only entities that belong to

graph/src/data/query/error.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ pub enum QueryExecutionError {
7575
InvalidSubgraphManifest,
7676
ResultTooBig(usize, usize),
7777
DeploymentNotFound(String),
78-
IdMissing,
79-
IdNotString,
8078
}
8179

8280
impl QueryExecutionError {
@@ -134,9 +132,7 @@ impl QueryExecutionError {
134132
| InvalidSubgraphManifest
135133
| ValidationError(_, _)
136134
| ResultTooBig(_, _)
137-
| DeploymentNotFound(_)
138-
| IdMissing
139-
| IdNotString => false,
135+
| DeploymentNotFound(_) => false,
140136
}
141137
}
142138
}
@@ -283,9 +279,7 @@ impl fmt::Display for QueryExecutionError {
283279
SubgraphManifestResolveError(e) => write!(f, "failed to resolve subgraph manifest: {}", e),
284280
InvalidSubgraphManifest => write!(f, "invalid subgraph manifest file"),
285281
ResultTooBig(actual, limit) => write!(f, "the result size of {} is larger than the allowed limit of {}", actual, limit),
286-
DeploymentNotFound(id_or_name) => write!(f, "deployment `{}` does not exist", id_or_name),
287-
IdMissing => write!(f, "Entity is missing an `id` attribute"),
288-
IdNotString => write!(f, "Entity is missing an `id` attribute")
282+
DeploymentNotFound(id_or_name) => write!(f, "deployment `{}` does not exist", id_or_name)
289283
}
290284
}
291285
}

graphql/src/store/prefetch.rs

Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
//! Run a GraphQL query and fetch all the entitied needed to build the
22
//! final result
33
4+
use anyhow::{anyhow, Error};
45
use graph::constraint_violation;
56
use graph::data::query::Trace;
6-
use graph::data::store::{ID, PARENT_ID};
7+
use graph::data::store::PARENT_ID;
78
use graph::data::value::{Object, Word};
8-
use graph::prelude::{r, CacheWeight, CheapClone, EntityQuery, EntityRange};
9+
use graph::prelude::{r, CacheWeight, CheapClone};
910
use graph::slog::warn;
1011
use graph::util::cache_weight;
1112
use std::collections::BTreeMap;
@@ -170,11 +171,11 @@ impl ValueExt for r::Value {
170171
}
171172

172173
impl Node {
173-
fn id(&self) -> Result<String, QueryExecutionError> {
174+
fn id(&self) -> Result<String, Error> {
174175
match self.get("id") {
175-
None => Err(QueryExecutionError::IdMissing),
176+
None => Err(anyhow!("Entity is missing an `id` attribute")),
176177
Some(r::Value::String(s)) => Ok(s.clone()),
177-
_ => Err(QueryExecutionError::IdNotString),
178+
_ => Err(anyhow!("Entity has non-string `id` attribute")),
178179
}
179180
}
180181

@@ -657,30 +658,6 @@ fn execute_field(
657658
.map_err(|e| vec![e])
658659
}
659660

660-
/// Check whether `field` only selects the `id` of its children and whether
661-
/// it is safe to skip running `query` if we have all child ids in memory
662-
/// already.
663-
fn selects_id_only(field: &a::Field, query: &EntityQuery) -> bool {
664-
if query.filter.is_some() || query.range.skip != 0 {
665-
return false;
666-
}
667-
match &query.order {
668-
EntityOrder::Ascending(attr, _) => {
669-
if attr != ID.as_str() {
670-
return false;
671-
}
672-
}
673-
_ => {
674-
return false;
675-
}
676-
}
677-
field
678-
.selection_set
679-
.single_field()
680-
.map(|field| field.name.as_str() == ID.as_str())
681-
.unwrap_or(false)
682-
}
683-
684661
/// Query child entities for `parents` from the store. The `join` indicates
685662
/// in which child field to look for the parent's id/join field. When
686663
/// `is_single` is `true`, there is at most one child per parent.
@@ -727,23 +704,6 @@ fn fetch(
727704
if windows.is_empty() {
728705
return Ok((vec![], Trace::None));
729706
}
730-
// See if we can short-circuit query execution and just reuse what
731-
// we already have in memory. We could do this probably even with
732-
// multiple windows, but this covers the most common case.
733-
if windows.len() == 1 && windows[0].link.has_child_ids() && selects_id_only(field, &query) {
734-
let mut windows = windows;
735-
// unwrap: we checked that len is 1
736-
let window = windows.pop().unwrap();
737-
let parent_ids = parents
738-
.iter()
739-
.map(|parent| parent.id())
740-
.collect::<Result<_, _>>()
741-
.map_err(QueryExecutionError::from)?;
742-
// unwrap: we checked in the if condition that the window has child ids
743-
let first = query.range.first.unwrap_or(EntityRange::FIRST) as usize;
744-
let objs = window.link.to_basic_objects(&parent_ids, first).unwrap();
745-
return Ok((objs.into_iter().map(Node::from).collect(), Trace::None));
746-
}
747707
query.collection = EntityCollection::Window(windows);
748708
}
749709
resolver

0 commit comments

Comments
 (0)