uqa_execution/batch/
owned_row.rs1use uqa_core::Value;
10use uqa_sql::expr::RowLookup;
11use uqa_sql::ResultRow;
12
13use crate::physical::{ExecError, ExecResult};
14
15use super::{PhysicalRow, PhysicalRowView, RowSchema};
16
17#[derive(Debug, Clone, PartialEq)]
19pub struct OwnedPhysicalRow {
20 pub schema: RowSchema,
21 pub row: PhysicalRow,
22}
23
24impl OwnedPhysicalRow {
25 pub fn new(schema: RowSchema, row: PhysicalRow) -> Self {
26 Self { schema, row }
27 }
28
29 pub fn view(&self) -> PhysicalRowView<'_> {
30 self.schema.view(&self.row)
31 }
32
33 pub fn get(&self, name: &str) -> Option<&Value> {
34 self.schema
35 .exact_slot(name)
36 .and_then(|slot| self.row.value(slot))
37 }
38
39 pub fn relabel(self, schema: RowSchema) -> ExecResult<Self> {
41 if self.schema.len() != schema.len() {
42 return Err(ExecError::Other(format!(
43 "cannot relabel {} columns as {} columns",
44 self.schema.len(),
45 schema.len()
46 )));
47 }
48 let slots = self.schema.index.slots.to_vec();
49 Ok(Self::new(schema, self.row.project_slots(&slots)))
50 }
51
52 pub fn into_result_row(self) -> ResultRow {
53 self.schema.materialize_result_row(self.row)
54 }
55}
56
57impl RowLookup for OwnedPhysicalRow {
58 fn column(&self, name: &str) -> Option<&Value> {
59 self.schema
60 .column_slot(name)
61 .and_then(|slot| self.row.value(slot))
62 }
63
64 fn column_is_ambiguous(&self, name: &str) -> bool {
65 self.schema.column_is_ambiguous(name)
66 }
67
68 fn qualified_column(&self, qualifier: &str, column: &str) -> Option<&Value> {
69 self.schema
70 .qualified_slot(qualifier, column)
71 .and_then(|slot| self.row.value(slot))
72 }
73
74 fn qualified_column_is_ambiguous(&self, qualifier: &str, column: &str) -> bool {
75 self.schema.qualified_column_is_ambiguous(qualifier, column)
76 }
77
78 fn positional_column(&self, index: usize) -> Option<&Value> {
79 self.schema
80 .slot(index)
81 .and_then(|slot| self.row.value(slot))
82 }
83
84 fn visit_columns(&self, visitor: &mut dyn FnMut(&str, &Value)) {
85 self.view().visit_columns(visitor);
86 }
87}