use lora_compiler::{CompiledQuery, PhysicalNodeId, PhysicalOp, PhysicalPlan};
pub(crate) fn should_collect_read_via_pull(compiled: &CompiledQuery) -> bool {
compiled.unions.is_empty() && plan_has_early_limit(&compiled.physical)
}
fn plan_has_early_limit(plan: &PhysicalPlan) -> bool {
plan.nodes.iter().any(|op| {
let PhysicalOp::Limit(limit) = op else {
return false;
};
limit.limit.is_some() && !subtree_contains_blocking_limit_input(plan, limit.input)
})
}
fn subtree_contains_blocking_limit_input(plan: &PhysicalPlan, node_id: PhysicalNodeId) -> bool {
match &plan.nodes[node_id] {
PhysicalOp::Sort(_) | PhysicalOp::HashAggregation(_) | PhysicalOp::OptionalMatch(_) => true,
PhysicalOp::Argument(_)
| PhysicalOp::NodeScan(_)
| PhysicalOp::NodeByLabelScan(_)
| PhysicalOp::NodeByPropertyScan(_) => false,
PhysicalOp::Expand(op) => subtree_contains_blocking_limit_input(plan, op.input),
PhysicalOp::Filter(op) => subtree_contains_blocking_limit_input(plan, op.input),
PhysicalOp::Projection(op) => subtree_contains_blocking_limit_input(plan, op.input),
PhysicalOp::Unwind(op) => subtree_contains_blocking_limit_input(plan, op.input),
PhysicalOp::Limit(op) => subtree_contains_blocking_limit_input(plan, op.input),
PhysicalOp::PathBuild(op) => subtree_contains_blocking_limit_input(plan, op.input),
PhysicalOp::Create(_)
| PhysicalOp::Merge(_)
| PhysicalOp::Delete(_)
| PhysicalOp::Set(_)
| PhysicalOp::Remove(_) => true,
}
}