|
|
|
@ -756,6 +756,47 @@ impl NormalAggrObj for AggrLatestBy {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
define_aggr!(AGGR_SMALLEST_BY, false);
|
|
|
|
|
|
|
|
|
|
pub(crate) struct AggrSmallestBy {
|
|
|
|
|
found: DataValue,
|
|
|
|
|
cost: DataValue,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for AggrSmallestBy {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
found: DataValue::Null,
|
|
|
|
|
cost: DataValue::Null,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl NormalAggrObj for AggrSmallestBy {
|
|
|
|
|
fn set(&mut self, value: &DataValue) -> Result<()> {
|
|
|
|
|
match value {
|
|
|
|
|
DataValue::List(l) => {
|
|
|
|
|
ensure!(
|
|
|
|
|
l.len() == 2,
|
|
|
|
|
"'smallest_by' requires a list of exactly two items as argument"
|
|
|
|
|
);
|
|
|
|
|
let c = &l[1];
|
|
|
|
|
if *c < self.cost {
|
|
|
|
|
self.cost = c.clone();
|
|
|
|
|
self.found = l[0].clone();
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
v => bail!("cannot compute 'smallest_by' on {:?}", v),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get(&self) -> Result<DataValue> {
|
|
|
|
|
Ok(self.found.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
define_aggr!(AGGR_MIN_COST, true);
|
|
|
|
|
|
|
|
|
|
pub(crate) struct AggrMinCost {
|
|
|
|
@ -1188,6 +1229,7 @@ impl Aggregation {
|
|
|
|
|
name if name == AGGR_SHORTEST.name => Box::new(AggrShortest::default()),
|
|
|
|
|
name if name == AGGR_MIN_COST.name => Box::new(AggrMinCost::default()),
|
|
|
|
|
name if name == AGGR_LATEST_BY.name => Box::new(AggrLatestBy::default()),
|
|
|
|
|
name if name == AGGR_SMALLEST_BY.name => Box::new(AggrSmallestBy::default()),
|
|
|
|
|
name if name == AGGR_CHOICE_RAND.name => Box::new(AggrChoiceRand::default()),
|
|
|
|
|
name if name == AGGR_COLLECT.name => Box::new({
|
|
|
|
|
if args.is_empty() {
|
|
|
|
|