//! Translation implementations for array and map access functions
use crate::{utils::hamelin_array_index_to_sql_with_negatives, TranslationRegistry};
use hamelin_lib::{
func::defs::{GetArray, GetMap},
sql::expression::apply::FunctionCallApply,
};
/// Register all access function translations.
pub fn register(registry: &mut TranslationRegistry) {
// get(array, index) -> element_at(array, safe_index)
// Use element_at instead of array[index] subscript syntax because subscript throws
// an error on out-of-bounds access while element_at returns NULL (which matches Hamelin semantics).
// Hamelin uses 0-based indexing with negative index support, SQL uses 1-based.
// The index conversion in hamelin_array_index_to_sql_with_negatives guards against
// out-of-bounds negative indices by returning NULL for converted values < 1.
registry.register::<GetArray>(|_, mut bindings| {
let array = bindings.take_by_name("array")?;
let index = bindings.take_by_name("index")?;
let sql_index = hamelin_array_index_to_sql_with_negatives(index.sql, array.sql.clone());
Ok(FunctionCallApply::with_two("element_at", array.sql, sql_index).into())
});
// get(map, key) -> element_at(map, key)
// Use element_at instead of map[key] subscript syntax because subscript throws
// an error for missing keys while element_at returns NULL (which matches Hamelin semantics)
registry.register::<GetMap>(|_, mut bindings| {
let map = bindings.take_by_name("map")?;
let key = bindings.take_by_name("key")?;
Ok(FunctionCallApply::with_two("element_at", map.sql, key.sql).into())
});
}