linkrs-query 0.1.0

Query engine, parser, and executor for Linkrs
Documentation
use crate::executor::expression::ExpressionError;
use linkrs_core::value::NullType;
use linkrs_core::Value;

pub(crate) fn execute_generate_series(args: &[Value]) -> Result<Value, ExpressionError> {
    if args.len() < 2 || args.len() > 3 {
        return Err(ExpressionError::type_error(
            "generate_series requires 2 or 3 arguments",
        ));
    }
    let start = match &args[0] {
        Value::BigInt(v) => *v,
        Value::Int(v) => *v as i64,
        Value::Null(_) => return Ok(Value::Null(NullType::Null)),
        _ => {
            return Err(ExpressionError::type_error(
                "generate_series start must be an integer",
            ))
        }
    };
    let end = match &args[1] {
        Value::BigInt(v) => *v,
        Value::Int(v) => *v as i64,
        Value::Null(_) => return Ok(Value::Null(NullType::Null)),
        _ => {
            return Err(ExpressionError::type_error(
                "generate_series end must be an integer",
            ))
        }
    };
    let step = if args.len() > 2 {
        match &args[2] {
            Value::BigInt(v) => *v,
            Value::Int(v) => *v as i64,
            Value::Null(_) => return Ok(Value::Null(NullType::Null)),
            _ => {
                return Err(ExpressionError::type_error(
                    "generate_series step must be an integer",
                ))
            }
        }
    } else {
        1
    };

    if step == 0 {
        return Err(ExpressionError::type_error(
            "generate_series step cannot be 0",
        ));
    }

    let mut result = Vec::new();
    if step > 0 {
        let mut i = start;
        while i <= end {
            result.push(Value::BigInt(i));
            i += step;
        }
    } else {
        let mut i = start;
        while i >= end {
            result.push(Value::BigInt(i));
            i += step;
        }
    }

    use linkrs_core::value::list::List;
    Ok(Value::list(List { values: result }))
}