Files
turso/testing
Jussi Saurio af039ffa6e Merge 'Initial support for aggregate functions in extensions' from Preston Thorpe
#708
This PR adds basic support for the following API for defining
Aggregates, and changes the existing API for scalars.
```rust
register_extension! {
    scalars: { Double },
    aggregates: { MedianState },
}

#[derive(ScalarDerive)]
struct Double;

impl Scalar for Double {
    fn name(&self) -> &'static str {
        "double"
    }
    fn call(&self, args: &[Value]) -> Value {
        if let Some(arg) = args.first() {
            match arg.value_type() {
                ValueType::Float => {
                    let val = arg.to_float().unwrap();
                    Value::from_float(val * 2.0)
                }
                ValueType::Integer => {
                    let val = arg.to_integer().unwrap();
                    Value::from_integer(val * 2)
                }
                _ => {
                    println!("arg: {:?}", arg);
                    Value::null()
                }
            }
        } else {
            Value::null()
        }
    }
}

#[derive(AggregateDerive)]
struct MedianState;

impl AggFunc for MedianState {
    type State = Vec<f64>;

    fn name(&self) -> &'static str {
        "median"
    }
    fn args(&self) -> i32 { 1 }

    fn step(state: &mut Self::State, args: &[Value]) {
        if let Some(val) = args.first().and_then(Value::to_float) {
            state.push(val);
        }
    }

    fn finalize(state: Self::State) -> Value {
        if state.is_empty() {
            return Value::null();
        }
        let mut sorted = state;
        sorted.sort_by(|a, b| a.partial_cmp(b).unwrap());
        let len = sorted.len();
        if len % 2 == 1 {
            Value::from_float(sorted[len / 2])
        } else {
            let mid1 = sorted[len / 2 - 1];
            let mid2 = sorted[len / 2];
            Value::from_float((mid1 + mid2) / 2.0)
        }
    }
}

```
I know it's a bit more verbose than the previous version, but I think in
the long run this will be more robust, and it matches the aggregate API
of implementing a trait on a struct that you derive the relevant trait
on.
Also this allows for better registration of functions, I think passing
in the struct identifiers just feels much better than the `"func_name"
=> function_ptr`

Closes #721
2025-01-18 11:07:06 +02:00
..
2024-08-03 12:16:34 +03:00
2024-12-31 14:18:29 +02:00
2024-07-16 07:20:35 +03:00
2024-12-30 17:02:31 +05:30
2025-01-16 00:09:45 +05:30
2024-12-28 13:55:12 +05:30
2025-01-15 21:21:51 +05:30
2024-12-31 14:18:29 +02:00
2024-12-27 11:39:02 -03:00
2024-10-05 18:25:04 +03:00