1use std::{cell::RefCell, rc::Rc};
7
8use lru::LruCache;
9
10use crate::errors::ExecutorError;
11
12pub struct ExpressionEvaluator<'a> {
14 pub(super) schema: &'a vibesql_catalog::TableSchema,
15 pub(super) outer_row: Option<&'a vibesql_storage::Row>,
16 pub(super) outer_schema: Option<&'a vibesql_catalog::TableSchema>,
17 pub(super) database: Option<&'a vibesql_storage::Database>,
18 pub(super) trigger_context: Option<&'a crate::trigger_execution::TriggerContext<'a>>,
20 pub(super) procedural_context: Option<&'a crate::procedural::ExecutionContext>,
22 pub(super) cte_context: Option<&'a std::collections::HashMap<String, crate::select::cte::CteResult>>,
24 pub(super) depth: usize,
26 pub(super) cse_cache: Rc<RefCell<LruCache<u64, vibesql_types::SqlValue>>>,
29 pub(super) enable_cse: bool,
31 pub(super) subquery_cache: Rc<RefCell<LruCache<u64, Vec<vibesql_storage::Row>>>>,
34 pub(super) row_index: Option<u64>,
37 pub(super) table_alias: Option<String>,
40}
41
42impl<'a> ExpressionEvaluator<'a> {
43 pub fn new(schema: &'a vibesql_catalog::TableSchema) -> Self {
45 ExpressionEvaluator {
46 schema,
47 outer_row: None,
48 outer_schema: None,
49 database: None,
50 trigger_context: None,
51 procedural_context: None,
52 cte_context: None,
53 depth: 0,
54 cse_cache: Rc::new(RefCell::new(super::caching::create_cse_cache())),
55 enable_cse: super::caching::is_cse_enabled(),
56 subquery_cache: Rc::new(RefCell::new(super::caching::create_subquery_cache())),
57 row_index: None,
58 table_alias: None,
59 }
60 }
61
62 pub fn with_outer_context(
64 schema: &'a vibesql_catalog::TableSchema,
65 outer_row: &'a vibesql_storage::Row,
66 outer_schema: &'a vibesql_catalog::TableSchema,
67 ) -> Self {
68 ExpressionEvaluator {
69 schema,
70 outer_row: Some(outer_row),
71 outer_schema: Some(outer_schema),
72 database: None,
73 trigger_context: None,
74 procedural_context: None,
75 cte_context: None,
76 depth: 0,
77 cse_cache: Rc::new(RefCell::new(super::caching::create_cse_cache())),
78 enable_cse: super::caching::is_cse_enabled(),
79 subquery_cache: Rc::new(RefCell::new(super::caching::create_subquery_cache())),
80 row_index: None,
81 table_alias: None,
82 }
83 }
84
85 pub fn with_database(
87 schema: &'a vibesql_catalog::TableSchema,
88 database: &'a vibesql_storage::Database,
89 ) -> Self {
90 ExpressionEvaluator {
91 schema,
92 outer_row: None,
93 outer_schema: None,
94 database: Some(database),
95 trigger_context: None,
96 procedural_context: None,
97 cte_context: None,
98 depth: 0,
99 cse_cache: Rc::new(RefCell::new(super::caching::create_cse_cache())),
100 enable_cse: super::caching::is_cse_enabled(),
101 subquery_cache: Rc::new(RefCell::new(super::caching::create_subquery_cache())),
102 row_index: None,
103 table_alias: None,
104 }
105 }
106
107 pub fn with_trigger_context(
109 schema: &'a vibesql_catalog::TableSchema,
110 database: &'a vibesql_storage::Database,
111 trigger_context: &'a crate::trigger_execution::TriggerContext<'a>,
112 ) -> Self {
113 ExpressionEvaluator {
114 schema,
115 outer_row: None,
116 outer_schema: None,
117 database: Some(database),
118 trigger_context: Some(trigger_context),
119 procedural_context: None,
120 cte_context: None,
121 depth: 0,
122 cse_cache: Rc::new(RefCell::new(super::caching::create_cse_cache())),
123 enable_cse: super::caching::is_cse_enabled(),
124 subquery_cache: Rc::new(RefCell::new(super::caching::create_subquery_cache())),
125 row_index: None,
126 table_alias: None,
127 }
128 }
129
130 pub fn with_database_and_outer_context(
133 schema: &'a vibesql_catalog::TableSchema,
134 database: &'a vibesql_storage::Database,
135 outer_row: &'a vibesql_storage::Row,
136 outer_schema: &'a vibesql_catalog::TableSchema,
137 ) -> Self {
138 ExpressionEvaluator {
139 schema,
140 outer_row: Some(outer_row),
141 outer_schema: Some(outer_schema),
142 database: Some(database),
143 trigger_context: None,
144 procedural_context: None,
145 cte_context: None,
146 depth: 0,
147 cse_cache: Rc::new(RefCell::new(super::caching::create_cse_cache())),
148 enable_cse: super::caching::is_cse_enabled(),
149 subquery_cache: Rc::new(RefCell::new(super::caching::create_subquery_cache())),
150 row_index: None,
151 table_alias: None,
152 }
153 }
154
155 pub fn with_procedural_context(
158 schema: &'a vibesql_catalog::TableSchema,
159 database: &'a vibesql_storage::Database,
160 procedural_context: &'a crate::procedural::ExecutionContext,
161 ) -> Self {
162 ExpressionEvaluator {
163 schema,
164 outer_row: None,
165 outer_schema: None,
166 database: Some(database),
167 trigger_context: None,
168 procedural_context: Some(procedural_context),
169 cte_context: None,
170 depth: 0,
171 cse_cache: Rc::new(RefCell::new(super::caching::create_cse_cache())),
172 enable_cse: super::caching::is_cse_enabled(),
173 subquery_cache: Rc::new(RefCell::new(super::caching::create_subquery_cache())),
174 row_index: None,
175 table_alias: None,
176 }
177 }
178
179 pub fn with_database_and_cte(
182 schema: &'a vibesql_catalog::TableSchema,
183 database: &'a vibesql_storage::Database,
184 cte_context: &'a std::collections::HashMap<String, crate::select::cte::CteResult>,
185 ) -> Self {
186 ExpressionEvaluator {
187 schema,
188 outer_row: None,
189 outer_schema: None,
190 database: Some(database),
191 trigger_context: None,
192 procedural_context: None,
193 cte_context: Some(cte_context),
194 depth: 0,
195 cse_cache: Rc::new(RefCell::new(super::caching::create_cse_cache())),
196 enable_cse: super::caching::is_cse_enabled(),
197 subquery_cache: Rc::new(RefCell::new(super::caching::create_subquery_cache())),
198 row_index: None,
199 table_alias: None,
200 }
201 }
202
203 pub fn set_row_index(&mut self, index: u64) {
208 self.row_index = Some(index);
209 }
210
211 pub fn clear_row_index(&mut self) {
213 self.row_index = None;
214 }
215
216 pub fn set_table_alias(&mut self, alias: String) {
221 self.table_alias = Some(alias);
222 }
223
224 pub(crate) fn eval_binary_op(
226 &self,
227 left: &vibesql_types::SqlValue,
228 op: &vibesql_ast::BinaryOperator,
229 right: &vibesql_types::SqlValue,
230 ) -> Result<vibesql_types::SqlValue, ExecutorError> {
231 let sql_mode = self.database.map(|db| db.sql_mode()).unwrap_or_default();
233
234 super::core::eval_binary_op_static(left, op, right, sql_mode)
235 }
236
237 pub fn clear_cse_cache(&self) {
240 self.cse_cache.borrow_mut().clear();
241 }
242
243 pub(crate) fn eval_binary_op_static(
247 left: &vibesql_types::SqlValue,
248 op: &vibesql_ast::BinaryOperator,
249 right: &vibesql_types::SqlValue,
250 sql_mode: vibesql_types::SqlMode,
251 ) -> Result<vibesql_types::SqlValue, ExecutorError> {
252 super::core::eval_binary_op_static(left, op, right, sql_mode)
253 }
254
255 pub(crate) fn eval_between_static(
259 expr_val: &vibesql_types::SqlValue,
260 low_val: &vibesql_types::SqlValue,
261 high_val: &vibesql_types::SqlValue,
262 negated: bool,
263 symmetric: bool,
264 sql_mode: vibesql_types::SqlMode,
265 ) -> Result<vibesql_types::SqlValue, ExecutorError> {
266 super::core::eval_between_static(expr_val, low_val, high_val, negated, symmetric, sql_mode)
267 }
268
269 pub(crate) fn values_are_equal(
273 left: &vibesql_types::SqlValue,
274 right: &vibesql_types::SqlValue,
275 ) -> bool {
276 super::core::values_are_equal(left, right)
277 }
278
279 pub(crate) fn values_are_distinct(
283 left: &vibesql_types::SqlValue,
284 right: &vibesql_types::SqlValue,
285 ) -> bool {
286 super::core::values_are_distinct(left, right)
287 }
288
289 pub(super) fn with_incremented_depth<F, T>(&self, f: F) -> Result<T, ExecutorError>
291 where
292 F: FnOnce(&Self) -> Result<T, ExecutorError>,
293 {
294 let evaluator = ExpressionEvaluator {
297 schema: self.schema,
298 outer_row: self.outer_row,
299 outer_schema: self.outer_schema,
300 database: self.database,
301 trigger_context: self.trigger_context,
302 procedural_context: self.procedural_context,
303 cte_context: self.cte_context,
304 depth: self.depth + 1,
305 cse_cache: self.cse_cache.clone(),
306 enable_cse: self.enable_cse,
307 subquery_cache: self.subquery_cache.clone(),
308 row_index: self.row_index,
309 table_alias: self.table_alias.clone(),
310 };
311 f(&evaluator)
312 }
313}