use crate::pipeline::*;
pub(crate) fn is_bare(query: &Query) -> bool {
query.correlations.is_empty()
&& !query.branches.is_empty()
&& query.branches.iter().all(|b| {
matches!(b.anchor, Anchor::Root) && b.steps.is_empty() && b.projection.is_none()
})
}
pub(crate) fn eval_bare<H: Host>(
query: &Query,
host: &H,
outer: Option<&Scope<'_, H::Ext>>,
) -> (Vec<Thread<H::Ext>>, bool) {
let trace = H::Trace::default();
let mut caps: Vec<Thread<H::Ext>> = Vec::new();
for _ in &query.branches {
let t = Thread {
register: outer.map(|s| s.register.to_vec()).unwrap_or_default(),
topic: None,
prov: Prov::default(),
members: Vec::new(),
captures: outer.map(|s| s.captures.to_vec()).unwrap_or_default(),
named: outer.map(|s| s.named.to_vec()).unwrap_or_default(),
ext: host.root_ext(),
};
if !caps
.iter()
.any(|c| reg_key(&c.register) == reg_key(&t.register))
{
caps.push(t);
}
}
if outer.is_none()
&& let Some(seed) = run_option(|o| o.topic.clone())
{
for c in caps.iter_mut().filter(|c| c.topic.is_none()) {
c.topic = Some(seed.clone());
}
}
let at = query.join_at.min(query.pipeline.len());
let top = outer.is_none();
caps = apply_commands(&query.pipeline[..at], 0, top, caps, host, &trace, outer);
caps = apply_commands(&query.pipeline[at..], at, top, caps, host, &trace, outer);
(caps, pipeline_projected(query))
}
pub(crate) fn pipeline_projected(query: &Query) -> bool {
let mut projected = query.branches.iter().any(|b| b.projection.is_some());
let mut before_group: Vec<bool> = Vec::new();
for command in &query.pipeline {
match command {
Command::Agg(call) if matches!(call.name.as_str(), "group" | "window") => {
before_group.push(projected);
projected = true;
}
Command::Agg(call) if call.name == "ungroup" => {
projected = before_group.pop().unwrap_or(false);
}
Command::Nav(b) => projected = b.projection.is_some(),
s => projected = projected || command_projects(s),
}
}
projected
}
pub(crate) fn command_projects(command: &Command) -> bool {
match command {
Command::Select(_) | Command::Filter(_) => false,
Command::Push(_)
| Command::Subcontext { .. }
| Command::ExprPush { .. }
| Command::RecordPush { .. }
| Command::FieldsPush
| Command::AggPush { .. } => false,
Command::Repeat { command, .. } => command_projects(command),
Command::Splice(_) => false,
Command::SessionPush(_) => false,
Command::Nav(b) => b.projection.is_some(),
Command::Agg(call) => {
!(stdlib::known_keyed(&call.name)
|| matches!(
call.name.as_str(),
"sort" | "unique" | "reverse" | "first" | "last"
))
|| call.name == "group"
}
_ => true,
}
}