use uqa_core::Value;
use uqa_sql::expr::RowLookup;
use uqa_sql::ResultRow;
use crate::physical::{ExecError, ExecResult};
use super::{PhysicalRow, PhysicalRowView, RowSchema};
#[derive(Debug, Clone, PartialEq)]
pub struct OwnedPhysicalRow {
pub schema: RowSchema,
pub row: PhysicalRow,
}
impl OwnedPhysicalRow {
pub fn new(schema: RowSchema, row: PhysicalRow) -> Self {
Self { schema, row }
}
pub fn view(&self) -> PhysicalRowView<'_> {
self.schema.view(&self.row)
}
pub fn get(&self, name: &str) -> Option<&Value> {
self.schema
.exact_slot(name)
.and_then(|slot| self.row.value(slot))
}
pub fn relabel(self, schema: RowSchema) -> ExecResult<Self> {
if self.schema.len() != schema.len() {
return Err(ExecError::Other(format!(
"cannot relabel {} columns as {} columns",
self.schema.len(),
schema.len()
)));
}
let slots = self.schema.index.slots.to_vec();
Ok(Self::new(schema, self.row.project_slots(&slots)))
}
pub fn into_result_row(self) -> ResultRow {
self.schema.materialize_result_row(self.row)
}
}
impl RowLookup for OwnedPhysicalRow {
fn column(&self, name: &str) -> Option<&Value> {
self.schema
.column_slot(name)
.and_then(|slot| self.row.value(slot))
}
fn column_is_ambiguous(&self, name: &str) -> bool {
self.schema.column_is_ambiguous(name)
}
fn qualified_column(&self, qualifier: &str, column: &str) -> Option<&Value> {
self.schema
.qualified_slot(qualifier, column)
.and_then(|slot| self.row.value(slot))
}
fn qualified_column_is_ambiguous(&self, qualifier: &str, column: &str) -> bool {
self.schema.qualified_column_is_ambiguous(qualifier, column)
}
fn positional_column(&self, index: usize) -> Option<&Value> {
self.schema
.slot(index)
.and_then(|slot| self.row.value(slot))
}
fn visit_columns(&self, visitor: &mut dyn FnMut(&str, &Value)) {
self.view().visit_columns(visitor);
}
}