Skip to main content

uqa_execution/relational/
evaluator.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Expression-evaluation and row-predicate seams.
8
9use super::{
10    eval_scalar, Arc, ExecResult, RowSchema, SQLParam, ScalarEvalContext, ScalarExpr, Value,
11};
12use uqa_sql::ast::ColumnType;
13use uqa_sql::expr::RowLookup;
14use uqa_sql::SQLError;
15
16use crate::PhysicalRow;
17
18pub trait ExpressionEvaluator: Send + Sync {
19    fn evaluate(&self, expression: &ScalarExpr, row: &dyn RowLookup) -> ExecResult<Value>;
20
21    fn evaluate_physical(
22        &self,
23        expression: &ScalarExpr,
24        schema: &RowSchema,
25        row: &PhysicalRow,
26    ) -> ExecResult<Value> {
27        self.evaluate(expression, &schema.view(row))
28    }
29
30    /// Bound SQL parameters used by static type resolution. Implementations
31    /// that do not evaluate parameters may keep the empty default.
32    fn parameters(&self) -> &[SQLParam] {
33        &[]
34    }
35
36    fn expression_type(
37        &self,
38        expression: &ScalarExpr,
39        schema: &RowSchema,
40    ) -> Result<Option<ColumnType>, SQLError> {
41        crate::scalar_type(expression, schema, self.parameters())
42    }
43
44    fn star_column_visible(&self, _column: &str) -> bool {
45        true
46    }
47
48    fn project_star(&self, row: &dyn RowLookup) -> ExecResult<Vec<(String, Value)>> {
49        let mut output = Vec::new();
50        row.visit_columns(&mut |column, value| {
51            if self.star_column_visible(column) {
52                output.push((column.to_string(), value.clone()));
53            }
54        });
55        Ok(output)
56    }
57}
58
59pub type SharedExpressionEvaluator<'a> = Arc<dyn ExpressionEvaluator + 'a>;
60
61pub trait RowPredicate: Send + Sync {
62    fn keep_physical(&self, schema: &RowSchema, row: &PhysicalRow) -> ExecResult<bool>;
63}
64
65pub type SharedRowPredicate<'a> = Arc<dyn RowPredicate + 'a>;
66
67pub(super) struct DefaultExpressionEvaluator {
68    params: Vec<SQLParam>,
69}
70
71impl DefaultExpressionEvaluator {
72    pub(super) fn shared(params: Vec<SQLParam>) -> SharedExpressionEvaluator<'static> {
73        Arc::new(Self { params })
74    }
75}
76
77impl ExpressionEvaluator for DefaultExpressionEvaluator {
78    fn evaluate(&self, expression: &ScalarExpr, row: &dyn RowLookup) -> ExecResult<Value> {
79        let context = ScalarEvalContext::from_row_lookup(row, &self.params);
80        Ok(eval_scalar(expression, &context)?)
81    }
82
83    fn parameters(&self) -> &[SQLParam] {
84        &self.params
85    }
86}