use super::super::super::ast::OrderItem;
use super::super::super::result::ResultRow;
use super::super::ordering::{SortSpec, TopKCollector};
use super::super::CypherExecutor;
use super::RowStream;
use crate::datatypes::values::Value;
pub fn apply<'q>(
executor: &'q CypherExecutor<'q>,
upstream: RowStream<'q>,
order_items: &[OrderItem],
limit: usize,
) -> Result<RowStream<'q>, String> {
let columns = upstream.columns_owned();
if limit == 0 {
for row in upstream {
row?;
}
return Ok(RowStream::from_vec(Vec::new(), columns));
}
let folded_exprs: Vec<_> = order_items
.iter()
.map(|item| executor.fold_constants_expr(&item.expression))
.collect();
let specs: Vec<SortSpec> = order_items.iter().map(SortSpec::from_order_item).collect();
let mut collector: TopKCollector<ResultRow> = TopKCollector::new(specs, limit);
let mut key_buf: Vec<Value> = Vec::with_capacity(folded_exprs.len());
for (seq, row) in upstream.enumerate() {
let row = row?;
key_buf.clear();
for expr in &folded_exprs {
key_buf.push(
executor
.evaluate_expression(expr, &row)
.unwrap_or(Value::Null),
);
}
if collector.accepts(&key_buf, seq) {
collector.push(&key_buf, seq, row);
}
}
let rows: Vec<ResultRow> = collector
.into_sorted()
.into_iter()
.map(|(_, row)| row)
.collect();
Ok(RowStream::from_vec(rows, columns))
}