use crate::{
db::{
data::{FieldDecodeError, ValueStorageView},
query::plan::expr::ProjectionEvalError,
},
error::InternalError,
value::Value,
};
pub(in crate::db::executor) fn resolve_value_field_path<'value>(
root: &'value Value,
segments: &[String],
) -> Result<Option<&'value Value>, ProjectionEvalError> {
let mut current = root;
for segment in segments {
if matches!(current, Value::Null) {
return Ok(None);
}
let entries = current.as_map().ok_or_else(|| {
let err = InternalError::persisted_row_decode_corruption();
ProjectionEvalError::FieldPathEvaluationFailed {
class: err.class(),
origin: err.origin(),
}
})?;
let Some((_, value)) = entries
.iter()
.find(|(key, _)| matches!(key, Value::Text(text) if text == segment))
else {
return Ok(None);
};
current = value;
}
Ok(Some(current))
}
pub(in crate::db::executor) fn resolve_path_segments<'a>(
raw_bytes: &'a [u8],
segment_bytes: &[Box<[u8]>],
) -> Result<Option<&'a [u8]>, FieldDecodeError> {
let mut current = ValueStorageView::from_raw_validated(raw_bytes)?;
for segment in segment_bytes {
if current.is_null() {
return Ok(None);
}
current = match current.map_text_key_bytes(segment)? {
Some(next) => next,
None => return Ok(None),
};
}
Ok(Some(current.as_bytes()))
}