use super::RowSchema;
use crate::ast::{ColumnDef, ColumnType, InternalColumnRef};
pub trait ScalarTypeSchema {
fn has_unqualified_column(&self, name: &str) -> bool;
fn column_is_ambiguous(&self, name: &str) -> bool;
fn type_of(&self, name: &str) -> Option<&ColumnType>;
fn column_type(&self, position: usize) -> Option<&ColumnType>;
fn internal_type(&self, column: InternalColumnRef) -> Option<&ColumnType>;
fn has_qualifier(&self, qualifier: &str) -> bool;
fn has_qualified_column(&self, qualifier: &str, name: &str) -> bool;
fn qualified_column_is_ambiguous(&self, qualifier: &str, name: &str) -> bool;
fn qualified_type(&self, qualifier: &str, name: &str) -> Option<&ColumnType>;
fn columns_are_open(&self, qualifier: Option<&str>) -> bool;
fn physical_schema(&self) -> Option<&RowSchema>;
}
impl ScalarTypeSchema for RowSchema {
fn has_unqualified_column(&self, name: &str) -> bool {
Self::has_unqualified_column(self, name)
}
fn column_is_ambiguous(&self, name: &str) -> bool {
Self::column_is_ambiguous(self, name)
}
fn type_of(&self, name: &str) -> Option<&ColumnType> {
Self::type_of(self, name)
}
fn column_type(&self, position: usize) -> Option<&ColumnType> {
Self::column_type(self, position)
}
fn internal_type(&self, column: InternalColumnRef) -> Option<&ColumnType> {
Self::internal_type(self, column)
}
fn has_qualifier(&self, qualifier: &str) -> bool {
Self::has_qualifier(self, qualifier)
}
fn has_qualified_column(&self, qualifier: &str, name: &str) -> bool {
Self::has_qualified_column(self, qualifier, name)
}
fn qualified_column_is_ambiguous(&self, qualifier: &str, name: &str) -> bool {
Self::qualified_column_is_ambiguous(self, qualifier, name)
}
fn qualified_type(&self, qualifier: &str, name: &str) -> Option<&ColumnType> {
Self::qualified_type(self, qualifier, name)
}
fn columns_are_open(&self, qualifier: Option<&str>) -> bool {
Self::columns_are_open(self, qualifier)
}
fn physical_schema(&self) -> Option<&RowSchema> {
Some(self)
}
}
#[derive(Clone, Copy)]
pub struct ColumnTypeSchema<'a> {
columns: &'a [ColumnDef],
}
impl<'a> ColumnTypeSchema<'a> {
pub fn new(columns: &'a [ColumnDef]) -> Self {
Self { columns }
}
}
impl ScalarTypeSchema for ColumnTypeSchema<'_> {
fn has_unqualified_column(&self, name: &str) -> bool {
self.columns.iter().any(|column| column.name == name)
}
fn column_is_ambiguous(&self, name: &str) -> bool {
self.columns
.iter()
.filter(|column| column.name == name)
.nth(1)
.is_some()
}
fn type_of(&self, name: &str) -> Option<&ColumnType> {
let mut matching = self.columns.iter().filter(|column| column.name == name);
let first = matching.next()?;
matching.next().is_none().then_some(&first.ty)
}
fn column_type(&self, position: usize) -> Option<&ColumnType> {
self.columns.get(position).map(|column| &column.ty)
}
fn internal_type(&self, _: InternalColumnRef) -> Option<&ColumnType> {
None
}
fn has_qualifier(&self, _: &str) -> bool {
false
}
fn has_qualified_column(&self, _: &str, _: &str) -> bool {
false
}
fn qualified_column_is_ambiguous(&self, _: &str, _: &str) -> bool {
false
}
fn qualified_type(&self, _: &str, _: &str) -> Option<&ColumnType> {
None
}
fn columns_are_open(&self, _: Option<&str>) -> bool {
false
}
fn physical_schema(&self) -> Option<&RowSchema> {
None
}
}
#[cfg(test)]
mod tests;