1use crate::executor::expression::evaluator::traits::ExpressionContext;
9use crate::executor::expression::ExpressionError;
10use crate::executor::streaming::slot::{SlotId, SlotLayout};
11use crate::executor::streaming::subquery::{EvalEnv, SubqueryExecutor};
12use linkrs_core::Value;
13use std::collections::HashMap;
14use std::sync::Arc;
15
16use super::parameters::{ParameterFrame, ParameterSchema};
17
18pub struct ValueRowContext {
24 row: Vec<Value>,
26 variables: HashMap<String, Value>,
28 layout: Arc<SlotLayout>,
30 parameters: Option<Arc<HashMap<String, Value>>>,
32 session_variables: Option<Arc<HashMap<String, Value>>>,
34 subquery_executor: Option<Arc<SubqueryExecutor>>,
36 sequence_manager: Option<Arc<linkrs_core::metadata::SequenceManager>>,
38}
39
40impl ValueRowContext {
41 pub fn new(row: Vec<Value>, layout: Arc<SlotLayout>) -> Self {
43 Self {
44 row,
45 variables: HashMap::new(),
46 layout,
47 parameters: None,
48 session_variables: None,
49 subquery_executor: None,
50 sequence_manager: None,
51 }
52 }
53
54 pub fn with_parameters(
56 row: Vec<Value>,
57 layout: Arc<SlotLayout>,
58 parameters: Arc<HashMap<String, Value>>,
59 ) -> Self {
60 Self {
61 row,
62 variables: HashMap::new(),
63 layout,
64 parameters: Some(parameters),
65 session_variables: None,
66 subquery_executor: None,
67 sequence_manager: None,
68 }
69 }
70
71 pub fn with_env(row: Vec<Value>, layout: Arc<SlotLayout>, env: &EvalEnv) -> Self {
73 Self {
74 row,
75 variables: HashMap::new(),
76 layout,
77 parameters: env.params.clone(),
78 session_variables: env.session_variables.clone(),
79 subquery_executor: env.subquery_executor.clone(),
80 sequence_manager: env.sequence_manager.clone(),
81 }
82 }
83
84 pub fn build_parameter_map(
86 schema: &ParameterSchema,
87 frame: &ParameterFrame,
88 ) -> HashMap<String, Value> {
89 schema
90 .params
91 .iter()
92 .filter_map(|p| frame.get(p.slot).map(|v| (p.name.clone(), v.clone())))
93 .collect()
94 }
95
96 pub fn from_names(row: Vec<Value>, col_names: Vec<String>) -> Self {
103 let layout = Arc::new(SlotLayout::from_names(&col_names));
104 Self::new(row, layout)
105 }
106}
107
108impl ExpressionContext for ValueRowContext {
109 fn get_variable(&self, name: &str) -> Option<Value> {
110 if let Some(value) = self.variables.get(name) {
112 return Some(value.clone());
113 }
114 self.layout
116 .slot_id(name)
117 .and_then(|slot_id| self.row.get(slot_id).cloned())
118 }
119
120 fn get_variable_by_slot(&self, slot: SlotId) -> Option<Value> {
121 self.row.get(slot).cloned()
122 }
123
124 fn set_variable(&mut self, name: String, value: Value) {
125 self.variables.insert(name, value);
126 }
127
128 fn get_parameter(&self, name: &str) -> Option<Value> {
129 self.parameters.as_ref().and_then(|p| p.get(name).cloned())
130 }
131
132 fn get_session_variable(&self, name: &str) -> Result<Value, ExpressionError> {
133 self.session_variables
134 .as_ref()
135 .and_then(|vars| vars.get(name).cloned())
136 .ok_or_else(|| {
137 ExpressionError::type_error(format!("Session variable `{}` is not defined", name))
138 })
139 }
140
141 fn get_sequence_manager(&self) -> Option<Arc<linkrs_core::metadata::SequenceManager>> {
142 self.sequence_manager.clone()
143 }
144
145 fn execute_exists(
146 &mut self,
147 body: &linkrs_core::types::expr::SubqueryBody,
148 ) -> Result<bool, ExpressionError> {
149 self.subquery_executor
150 .as_ref()
151 .ok_or_else(|| {
152 ExpressionError::type_error("Subquery execution not supported in this context")
153 })?
154 .execute_exists(body, self.layout.clone(), self.row.clone())
155 }
156
157 fn execute_scalar_subquery(
158 &mut self,
159 body: &linkrs_core::types::expr::SubqueryBody,
160 ) -> Result<Value, ExpressionError> {
161 self.subquery_executor
162 .as_ref()
163 .ok_or_else(|| {
164 ExpressionError::type_error(
165 "Scalar subquery execution not supported in this context",
166 )
167 })?
168 .execute_scalar(body, self.layout.clone(), self.row.clone())
169 }
170
171 fn contains_subquery(
172 &mut self,
173 body: &linkrs_core::types::expr::SubqueryBody,
174 value: &Value,
175 ) -> Result<Value, ExpressionError> {
176 if value.is_null() {
177 return Ok(Value::Bool(false));
178 }
179 let found = self
180 .subquery_executor
181 .as_ref()
182 .ok_or_else(|| {
183 ExpressionError::type_error("Subquery execution not supported in this context")
184 })?
185 .execute_contains(body, self.layout.clone(), self.row.clone(), value)?;
186 Ok(Value::Bool(found))
187 }
188}
189
190pub struct BorrowedRowContext<'a> {
198 row: &'a [Value],
199 variables: HashMap<String, Value>,
200 layout: Arc<SlotLayout>,
201 parameters: Option<Arc<HashMap<String, Value>>>,
202 session_variables: Option<Arc<HashMap<String, Value>>>,
204 subquery_executor: Option<Arc<SubqueryExecutor>>,
206 sequence_manager: Option<Arc<linkrs_core::metadata::SequenceManager>>,
208}
209
210impl<'a> BorrowedRowContext<'a> {
211 pub fn new(row: &'a [Value], layout: Arc<SlotLayout>) -> Self {
212 Self {
213 row,
214 variables: HashMap::new(),
215 layout,
216 parameters: None,
217 session_variables: None,
218 subquery_executor: None,
219 sequence_manager: None,
220 }
221 }
222
223 pub fn with_parameters(
225 row: &'a [Value],
226 layout: Arc<SlotLayout>,
227 parameters: Arc<HashMap<String, Value>>,
228 ) -> Self {
229 Self {
230 row,
231 variables: HashMap::new(),
232 layout,
233 parameters: Some(parameters),
234 session_variables: None,
235 subquery_executor: None,
236 sequence_manager: None,
237 }
238 }
239
240 pub fn with_env(row: &'a [Value], layout: Arc<SlotLayout>, env: &EvalEnv) -> Self {
243 Self {
244 row,
245 variables: HashMap::new(),
246 layout,
247 parameters: env.params.clone(),
248 session_variables: env.session_variables.clone(),
249 subquery_executor: env.subquery_executor.clone(),
250 sequence_manager: env.sequence_manager.clone(),
251 }
252 }
253
254 pub fn set_row(&mut self, row: &'a [Value]) {
259 self.row = row;
260 self.variables.clear();
261 }
262}
263
264impl ExpressionContext for BorrowedRowContext<'_> {
265 fn get_variable(&self, name: &str) -> Option<Value> {
266 if let Some(value) = self.variables.get(name) {
267 return Some(value.clone());
268 }
269 self.layout
270 .slot_id(name)
271 .and_then(|slot_id| self.row.get(slot_id).cloned())
272 }
273
274 fn get_variable_by_slot(&self, slot: SlotId) -> Option<Value> {
275 self.row.get(slot).cloned()
276 }
277
278 fn set_variable(&mut self, name: String, value: Value) {
279 self.variables.insert(name, value);
280 }
281
282 fn get_parameter(&self, name: &str) -> Option<Value> {
283 self.parameters.as_ref().and_then(|p| p.get(name).cloned())
284 }
285
286 fn get_session_variable(&self, name: &str) -> Result<Value, ExpressionError> {
287 self.session_variables
288 .as_ref()
289 .and_then(|vars| vars.get(name).cloned())
290 .ok_or_else(|| {
291 ExpressionError::type_error(format!("Session variable `{}` is not defined", name))
292 })
293 }
294
295 fn get_sequence_manager(&self) -> Option<Arc<linkrs_core::metadata::SequenceManager>> {
296 self.sequence_manager.clone()
297 }
298
299 fn execute_exists(
300 &mut self,
301 body: &linkrs_core::types::expr::SubqueryBody,
302 ) -> Result<bool, ExpressionError> {
303 self.subquery_executor
304 .as_ref()
305 .ok_or_else(|| {
306 ExpressionError::type_error("Subquery execution not supported in this context")
307 })?
308 .execute_exists(body, self.layout.clone(), self.row.to_vec())
309 }
310
311 fn execute_scalar_subquery(
312 &mut self,
313 body: &linkrs_core::types::expr::SubqueryBody,
314 ) -> Result<Value, ExpressionError> {
315 self.subquery_executor
316 .as_ref()
317 .ok_or_else(|| {
318 ExpressionError::type_error(
319 "Scalar subquery execution not supported in this context",
320 )
321 })?
322 .execute_scalar(body, self.layout.clone(), self.row.to_vec())
323 }
324
325 fn contains_subquery(
326 &mut self,
327 body: &linkrs_core::types::expr::SubqueryBody,
328 value: &Value,
329 ) -> Result<Value, ExpressionError> {
330 if value.is_null() {
331 return Ok(Value::Bool(false));
332 }
333 let found = self
334 .subquery_executor
335 .as_ref()
336 .ok_or_else(|| {
337 ExpressionError::type_error("Subquery execution not supported in this context")
338 })?
339 .execute_contains(body, self.layout.clone(), self.row.to_vec(), value)?;
340 Ok(Value::Bool(found))
341 }
342}
343
344pub struct SplitRowContext<'a> {
351 left: &'a [Value],
352 right: &'a [Value],
353 split: usize,
354 variables: HashMap<String, Value>,
355 layout: Arc<SlotLayout>,
356 parameters: Option<Arc<HashMap<String, Value>>>,
357 session_variables: Option<Arc<HashMap<String, Value>>>,
359 subquery_executor: Option<Arc<SubqueryExecutor>>,
361 sequence_manager: Option<Arc<linkrs_core::metadata::SequenceManager>>,
363}
364
365impl<'a> SplitRowContext<'a> {
366 pub fn new(left: &'a [Value], right: &'a [Value], layout: Arc<SlotLayout>) -> Self {
367 let split = left.len();
368 Self {
369 left,
370 right,
371 split,
372 variables: HashMap::new(),
373 layout,
374 parameters: None,
375 session_variables: None,
376 subquery_executor: None,
377 sequence_manager: None,
378 }
379 }
380
381 pub fn with_env(
384 left: &'a [Value],
385 right: &'a [Value],
386 layout: Arc<SlotLayout>,
387 env: &EvalEnv,
388 ) -> Self {
389 let split = left.len();
390 Self {
391 left,
392 right,
393 split,
394 variables: HashMap::new(),
395 layout,
396 parameters: env.params.clone(),
397 session_variables: env.session_variables.clone(),
398 subquery_executor: env.subquery_executor.clone(),
399 sequence_manager: env.sequence_manager.clone(),
400 }
401 }
402}
403
404impl ExpressionContext for SplitRowContext<'_> {
405 fn get_variable(&self, name: &str) -> Option<Value> {
406 if let Some(value) = self.variables.get(name) {
407 return Some(value.clone());
408 }
409 self.layout
410 .slot_id(name)
411 .and_then(|slot_id| self.get_variable_by_slot(slot_id))
412 }
413
414 fn get_variable_by_slot(&self, slot: SlotId) -> Option<Value> {
415 if slot < self.split {
416 self.left.get(slot).cloned()
417 } else {
418 self.right.get(slot - self.split).cloned()
419 }
420 }
421
422 fn set_variable(&mut self, name: String, value: Value) {
423 self.variables.insert(name, value);
424 }
425
426 fn get_parameter(&self, name: &str) -> Option<Value> {
427 self.parameters.as_ref().and_then(|p| p.get(name).cloned())
428 }
429
430 fn get_session_variable(&self, name: &str) -> Result<Value, ExpressionError> {
431 self.session_variables
432 .as_ref()
433 .and_then(|vars| vars.get(name).cloned())
434 .ok_or_else(|| {
435 ExpressionError::type_error(format!("Session variable `{}` is not defined", name))
436 })
437 }
438
439 fn get_sequence_manager(&self) -> Option<Arc<linkrs_core::metadata::SequenceManager>> {
440 self.sequence_manager.clone()
441 }
442
443 fn execute_exists(
444 &mut self,
445 body: &linkrs_core::types::expr::SubqueryBody,
446 ) -> Result<bool, ExpressionError> {
447 let mut row = self.left.to_vec();
448 row.extend_from_slice(self.right);
449 self.subquery_executor
450 .as_ref()
451 .ok_or_else(|| {
452 ExpressionError::type_error("Subquery execution not supported in this context")
453 })?
454 .execute_exists(body, self.layout.clone(), row)
455 }
456
457 fn execute_scalar_subquery(
458 &mut self,
459 body: &linkrs_core::types::expr::SubqueryBody,
460 ) -> Result<Value, ExpressionError> {
461 let mut row = self.left.to_vec();
462 row.extend_from_slice(self.right);
463 self.subquery_executor
464 .as_ref()
465 .ok_or_else(|| {
466 ExpressionError::type_error(
467 "Scalar subquery execution not supported in this context",
468 )
469 })?
470 .execute_scalar(body, self.layout.clone(), row)
471 }
472
473 fn contains_subquery(
474 &mut self,
475 body: &linkrs_core::types::expr::SubqueryBody,
476 value: &Value,
477 ) -> Result<Value, ExpressionError> {
478 if value.is_null() {
479 return Ok(Value::Bool(false));
480 }
481 let mut row = self.left.to_vec();
482 row.extend_from_slice(self.right);
483 let found = self
484 .subquery_executor
485 .as_ref()
486 .ok_or_else(|| {
487 ExpressionError::type_error("Subquery execution not supported in this context")
488 })?
489 .execute_contains(body, self.layout.clone(), row, value)?;
490 Ok(Value::Bool(found))
491 }
492}
493
494#[cfg(test)]
495mod tests {
496 use super::*;
497
498 #[test]
499 fn test_context_creation() {
500 let row = vec![Value::Int(1), Value::string("test"), Value::Bool(true)];
501 let col_names = vec!["id".to_string(), "name".to_string(), "active".to_string()];
502 let layout = Arc::new(SlotLayout::from_names(&col_names));
503
504 let context = ValueRowContext::new(row, layout);
505
506 assert_eq!(context.get_variable("id"), Some(Value::Int(1)));
507 assert_eq!(context.get_variable("name"), Some(Value::string("test")));
508 assert_eq!(context.get_variable("active"), Some(Value::Bool(true)));
509 }
510
511 #[test]
512 fn test_variable_storage() {
513 let row = vec![Value::Int(1)];
514 let col_names = vec!["id".to_string()];
515 let layout = Arc::new(SlotLayout::from_names(&col_names));
516 let mut context = ValueRowContext::new(row, layout);
517
518 context.set_variable("var1".into(), Value::string("hello"));
519 context.set_variable("var2".into(), Value::Int(42));
520
521 assert_eq!(context.get_variable("var1"), Some(Value::string("hello")));
522 assert_eq!(context.get_variable("var2"), Some(Value::Int(42)));
523 }
524
525 #[test]
526 fn test_missing_column() {
527 let row = vec![Value::Int(1), Value::string("test")];
528 let col_names = vec!["id".to_string(), "name".to_string()];
529 let layout = Arc::new(SlotLayout::from_names(&col_names));
530
531 let context = ValueRowContext::new(row, layout);
532
533 assert_eq!(context.get_variable("nonexistent"), None);
534 assert_eq!(context.get_variable("var_not_set"), None);
535 }
536}