use std::sync::Arc;
use apollo_compiler::ExecutableDocument;
use apollo_compiler::Name;
use apollo_compiler::executable;
use serde::Deserialize;
use serde::Serialize;
use crate::query_plan::query_planner::QueryPlanningStatistics;
pub(crate) mod conditions;
pub(crate) mod display;
pub(crate) mod fetch_dependency_graph;
pub(crate) mod fetch_dependency_graph_processor;
pub mod generate;
pub mod query_planner;
pub(crate) mod query_planning_traversal;
pub mod requires_selection;
pub mod serializable_document;
pub type QueryPlanCost = f64;
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct QueryPlan {
pub node: Option<TopLevelPlanNode>,
pub statistics: QueryPlanningStatistics,
}
#[derive(Debug, Clone, PartialEq, derive_more::From, Serialize, Deserialize)]
pub enum TopLevelPlanNode {
Subscription(SubscriptionNode),
#[from(FetchNode, Box<FetchNode>)]
Fetch(Box<FetchNode>),
Sequence(SequenceNode),
Parallel(ParallelNode),
Flatten(FlattenNode),
Defer(DeferNode),
#[from(ConditionNode, Box<ConditionNode>)]
Condition(Box<ConditionNode>),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SubscriptionNode {
pub primary: Box<FetchNode>,
pub rest: Option<Box<PlanNode>>,
}
#[derive(Debug, Clone, PartialEq, derive_more::From, Serialize, Deserialize)]
pub enum PlanNode {
#[from(FetchNode, Box<FetchNode>)]
Fetch(Box<FetchNode>),
Sequence(SequenceNode),
Parallel(ParallelNode),
Flatten(FlattenNode),
Defer(DeferNode),
#[from(ConditionNode, Box<ConditionNode>)]
Condition(Box<ConditionNode>),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FetchNode {
pub subgraph_name: Arc<str>,
pub id: Option<u64>,
pub variable_usages: Vec<Name>,
#[serde(skip_serializing_if = "Vec::is_empty")]
#[serde(default)]
pub requires: Vec<requires_selection::Selection>,
pub operation_document: serializable_document::SerializableDocument,
pub operation_name: Option<Name>,
#[serde(with = "crate::utils::serde_bridge::operation_type")]
pub operation_kind: executable::OperationType,
pub input_rewrites: Arc<Vec<Arc<FetchDataRewrite>>>,
pub output_rewrites: Vec<Arc<FetchDataRewrite>>,
pub context_rewrites: Vec<Arc<FetchDataRewrite>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SequenceNode {
pub nodes: Vec<PlanNode>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ParallelNode {
pub nodes: Vec<PlanNode>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FlattenNode {
pub path: Vec<FetchDataPathElement>,
pub node: Box<PlanNode>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DeferNode {
pub primary: PrimaryDeferBlock,
pub deferred: Vec<DeferredDeferBlock>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PrimaryDeferBlock {
pub sub_selection: Option<String>,
pub node: Option<Box<PlanNode>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DeferredDeferBlock {
pub depends: Vec<DeferredDependency>,
pub label: Option<String>,
pub query_path: Vec<QueryPathElement>,
pub sub_selection: Option<String>,
pub node: Option<Box<PlanNode>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DeferredDependency {
pub id: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ConditionNode {
pub condition_variable: Name,
pub if_clause: Option<Box<PlanNode>>,
pub else_clause: Option<Box<PlanNode>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, derive_more::From)]
pub enum FetchDataRewrite {
ValueSetter(FetchDataValueSetter),
KeyRenamer(FetchDataKeyRenamer),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FetchDataValueSetter {
pub path: Vec<FetchDataPathElement>,
pub set_value_to: serde_json_bytes::Value,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FetchDataKeyRenamer {
pub path: Vec<FetchDataPathElement>,
pub rename_key_to: Name,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum FetchDataPathElement {
Key(Name, Option<Conditions>),
AnyIndex(Option<Conditions>),
TypenameEquals(Name),
Parent,
}
pub type Conditions = Vec<Name>;
#[derive(Debug, Clone, PartialEq, serde::Serialize, Deserialize)]
pub enum QueryPathElement {
Field { response_key: Name },
InlineFragment { type_condition: Name },
}
impl PlanNode {
fn node_kind(&self) -> &'static str {
match self {
Self::Fetch(_) => "Fetch",
Self::Sequence(_) => "Sequence",
Self::Parallel(_) => "Parallel",
Self::Flatten(_) => "Flatten",
Self::Defer(_) => "Defer",
Self::Condition(_) => "Condition",
}
}
}