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(_)
| PhysicalOp::CallSubquery(_)
| PhysicalOp::NodeByPropertyRangeScan(_)
| PhysicalOp::NodeByTextScan(_)
| PhysicalOp::NodeByPointScan(_)
| PhysicalOp::RelByPropertyRangeScan(_)
| PhysicalOp::RelByTextScan(_)
| PhysicalOp::RelByPointScan(_) => 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,
}
}