1use rudb_common::{Error, Result, Value};
17use rudb_kernels::{Comparison, Connective, cast, combine, compare, is_true};
18use rudb_plan::{CompareOp, ConjunctionOp, Expr, ExprRef, Plan};
19use rudb_vector::{Chunk, Selection, Vector};
20
21use crate::schema::Schema;
22
23pub fn evaluate(plan: &Plan, expr: ExprRef, schema: &Schema, chunk: &Chunk) -> Result<Vector> {
32 let ty = plan.expr_type(expr).clone();
33 match *plan.expr(expr) {
34 Expr::Column(binding) => {
35 let position = schema.position_of(binding).ok_or_else(|| {
36 Error::internal(format!(
37 "column #{}.{} is not in the schema this operator was given",
38 binding.table, binding.column
39 ))
40 })?;
41 Ok(chunk.column(position)?.clone())
42 }
43 Expr::Constant(reference) => {
44 Ok(Vector::constant(ty, plan.value(reference).clone(), chunk.len()))
45 }
46 Expr::Cast { input, try_cast } => {
47 let inner = evaluate(plan, input, schema, chunk)?;
48 cast(&inner, &ty, try_cast)
49 }
50 Expr::Compare { op, left, right } => {
51 let left = evaluate(plan, left, schema, chunk)?;
52 let right = evaluate(plan, right, schema, chunk)?;
53 compare(comparison(op), &left, &right)
54 }
55 Expr::Conjunction { op, children } => {
56 let children = evaluate_all(plan, plan.expr_list(children), schema, chunk)?;
57 combine(connective(op), &children)
58 }
59 Expr::Function { name, args } => {
60 let args = evaluate_all(plan, plan.expr_list(args), schema, chunk)?;
61 rudb_kernels::call(plan.string(name), &args, &ty)
62 }
63 Expr::Aggregate { name, .. } => Err(Error::internal(format!(
64 "the {} aggregate was evaluated as an ordinary expression",
65 plan.string(name)
66 ))),
67 Expr::Case { arms, otherwise } => {
68 let arms = plan.arm_list(arms).to_vec();
69 let mut answers = vec![Value::Null; chunk.len()];
70 let mut pending: Vec<usize> = (0..chunk.len()).collect();
71 for arm in arms {
72 if pending.is_empty() {
73 break;
74 }
75 let narrowed = narrow(chunk, &pending)?;
76 let flags = evaluate(plan, arm.when, schema, &narrowed)?;
77 let mut taken = Vec::new();
78 let mut still = Vec::new();
79 for (at, &row) in pending.iter().enumerate() {
80 if is_true(&flags.value_at(at)) {
81 taken.push((at, row));
82 } else {
83 still.push(row);
84 }
85 }
86 if !taken.is_empty() {
87 let positions: Vec<usize> = taken.iter().map(|&(at, _)| at).collect();
88 let matched = narrow(&narrowed, &positions)?;
89 let results = evaluate(plan, arm.then, schema, &matched)?;
90 for (slot, &(_, row)) in taken.iter().enumerate() {
91 answers[row] = results.value_at(slot);
92 }
93 }
94 pending = still;
95 }
96 if let Some(otherwise) = otherwise {
97 if !pending.is_empty() {
98 let narrowed = narrow(chunk, &pending)?;
99 let results = evaluate(plan, otherwise, schema, &narrowed)?;
100 for (slot, &row) in pending.iter().enumerate() {
101 answers[row] = results.value_at(slot);
102 }
103 }
104 }
105 Vector::from_values(ty, &answers)
106 }
107 }
108}
109
110pub fn evaluate_all(
116 plan: &Plan,
117 exprs: &[ExprRef],
118 schema: &Schema,
119 chunk: &Chunk,
120) -> Result<Vec<Vector>> {
121 exprs.iter().map(|&expr| evaluate(plan, expr, schema, chunk)).collect()
122}
123
124fn narrow(chunk: &Chunk, rows: &[usize]) -> Result<Chunk> {
131 let mut selection = Selection::with_capacity(rows.len());
132 for &row in rows {
133 selection.push(row);
134 }
135 chunk.clone().select(&selection)
136}
137
138fn comparison(op: CompareOp) -> Comparison {
143 match op {
144 CompareOp::Equal => Comparison::Equal,
145 CompareOp::NotEqual => Comparison::NotEqual,
146 CompareOp::Less => Comparison::Less,
147 CompareOp::LessOrEqual => Comparison::LessOrEqual,
148 CompareOp::Greater => Comparison::Greater,
149 CompareOp::GreaterOrEqual => Comparison::GreaterOrEqual,
150 CompareOp::DistinctFrom => Comparison::DistinctFrom,
151 CompareOp::NotDistinctFrom => Comparison::NotDistinctFrom,
152 }
153}
154
155fn connective(op: ConjunctionOp) -> Connective {
157 match op {
158 ConjunctionOp::And => Connective::And,
159 ConjunctionOp::Or => Connective::Or,
160 }
161}