uqa_sql/expr/
array_access.rs1use std::ops::Deref;
10use uqa_core::{
11 memory::{Produced, ProductionControl},
12 Value,
13};
14
15use crate::{
16 ast::{ArrayAccess, MAX_ARRAY_SUBSCRIPT_DIMENSIONS},
17 SQLError,
18};
19
20pub fn eval_array_access_with_control(
22 access: ArrayAccess,
23 control: &ProductionControl<'_>,
24 mut evaluate: impl FnMut(usize) -> Result<Produced<Value>, SQLError>,
25) -> Result<Produced<Value>, SQLError> {
26 control.check()?;
27 access.validate_dimensions()?;
28 let array = evaluate(0)?;
29 eval_array_access_from_input(access, &array, control, evaluate)
30}
31
32pub(in crate::expr) fn eval_array_access_from_input<B: Deref<Target = Value>>(
34 access: ArrayAccess,
35 array: &Value,
36 control: &ProductionControl<'_>,
37 mut evaluate: impl FnMut(usize) -> Result<B, SQLError>,
38) -> Result<Produced<Value>, SQLError> {
39 control.check()?;
40 access.validate_dimensions()?;
41 if matches!(array, Value::Null) {
42 return Ok(control.finish(Value::Null, control.empty_reservation())?);
43 }
44 let mut bounds: [Value; MAX_ARRAY_SUBSCRIPT_DIMENSIONS * 2] =
45 std::array::from_fn(|_| Value::Null);
46 for index in access.evaluation_order() {
47 control.check()?;
48 let value = evaluate(index)?;
49 let value = super::cast_value_from_with_control(&value, "integer", None, control)?;
50 bounds[index - 1] = match *value {
51 Value::Null => Value::Null,
52 Value::Int(value) => Value::Int(value),
53 _ => {
54 return Err(SQLError::Internal(
55 "array bound coercion did not produce an integer".into(),
56 ))
57 }
58 };
59 }
60 super::scalar_postgres::subscripts::eval_selected_array_access(
61 array,
62 &bounds[..access.bound_count()],
63 access.slice_bounds(),
64 control,
65 )
66}
67
68#[cfg(test)]
69mod tests;