Skip to main content

uqa_execution/batch/
physical_row_view.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7use super::{PhysicalRow, ResultRow, RowLookup, RowSchema, Value, NULL_VALUE};
8
9/// Stack-only schema/row pair implementing the scalar evaluator's read seam.
10#[derive(Debug, Clone, Copy)]
11pub struct PhysicalRowView<'a> {
12    pub(super) schema: &'a RowSchema,
13    pub(super) row: &'a PhysicalRow,
14}
15
16impl<'a> PhysicalRowView<'a> {
17    pub fn get(&self, name: &str) -> Option<&'a Value> {
18        self.schema
19            .exact_slot(name)
20            .and_then(|slot| self.row.value(slot))
21    }
22
23    pub fn value_at(&self, logical: usize) -> Option<&'a Value> {
24        self.schema
25            .slot(logical)
26            .and_then(|slot| self.row.value(slot))
27    }
28
29    pub fn iter(&'a self) -> impl Iterator<Item = (&'a str, &'a Value)> + 'a {
30        self.schema
31            .columns()
32            .iter()
33            .enumerate()
34            .map(|(logical, column)| {
35                (
36                    column.as_str(),
37                    self.value_at(logical).unwrap_or(&NULL_VALUE),
38                )
39            })
40    }
41
42    pub fn to_result_row(&self) -> ResultRow {
43        self.iter()
44            .map(|(column, value)| (column.to_string(), value.clone()))
45            .collect()
46    }
47}
48
49impl RowLookup for PhysicalRowView<'_> {
50    fn column(&self, name: &str) -> Option<&Value> {
51        self.schema
52            .column_slot(name)
53            .and_then(|slot| self.row.value(slot))
54    }
55
56    fn column_is_ambiguous(&self, name: &str) -> bool {
57        self.schema.column_is_ambiguous(name)
58    }
59
60    fn qualified_column(&self, qualifier: &str, column: &str) -> Option<&Value> {
61        self.schema
62            .qualified_slot(qualifier, column)
63            .and_then(|slot| self.row.value(slot))
64    }
65
66    fn qualified_column_is_ambiguous(&self, qualifier: &str, column: &str) -> bool {
67        self.schema.qualified_column_is_ambiguous(qualifier, column)
68    }
69
70    fn positional_column(&self, index: usize) -> Option<&Value> {
71        self.value_at(index)
72    }
73
74    fn visit_columns(&self, visitor: &mut dyn FnMut(&str, &Value)) {
75        for (column, value) in self.iter() {
76            visitor(column, value);
77        }
78    }
79}