selene-db-gql 1.3.0

ISO/IEC 39075:2024 GQL parser, planner, optimizer, and executor for selene-db.
Documentation
use crate::{
    BindingTableColumn, BindingTableSchema, ProjectExpr,
    runtime::{Binding, BindingTable, EvalCtx, ExecutorError, evaluator},
};

pub(super) fn execute(
    items: &[ProjectExpr],
    table: BindingTable,
    ctx: &EvalCtx<'_, '_, '_, '_>,
) -> Result<BindingTable, ExecutorError> {
    let (input_schema, input_rows) = table.into_parts();
    let output_schema = schema_for_items(items);
    let mut rows = Vec::with_capacity(input_rows.len());
    let mut rows_since_check = 0;
    for row in input_rows {
        ctx.tx.check_cancellation_stride(&mut rows_since_check, 1)?;
        let values = items
            .iter()
            .map(|item| project_value(item, &row, &input_schema, ctx))
            .collect::<Result<Vec<_>, _>>()?;
        rows.push(Binding::new(values));
    }
    Ok(BindingTable::new(output_schema, rows))
}

fn project_value(
    item: &ProjectExpr,
    row: &Binding,
    schema: &BindingTableSchema,
    ctx: &EvalCtx<'_, '_, '_, '_>,
) -> Result<selene_core::Value, ExecutorError> {
    evaluator::evaluate(&item.expr, row, schema, ctx)
}

pub(super) fn schema_for_items(items: &[ProjectExpr]) -> BindingTableSchema {
    BindingTableSchema {
        columns: items
            .iter()
            .map(|item| BindingTableColumn {
                name: item.alias.clone(),
                hidden: None,
                ty: item.ty.clone(),
            })
            .collect(),
    }
}