use std::sync::{Arc, RwLock};
use rudb_common::Field;
use crate::catalog::DETACHED;
use crate::name::QualifiedName;
#[derive(Debug, Clone)]
pub struct View {
name: QualifiedName,
sql: String,
statement: String,
aliases: Vec<String>,
oid: i64,
columns: Arc<RwLock<Vec<Field>>>,
}
impl View {
#[must_use]
pub fn new(
name: QualifiedName,
sql: String,
statement: String,
aliases: Vec<String>,
columns: Vec<Field>,
) -> Self {
Self {
name,
sql,
statement,
aliases,
oid: DETACHED,
columns: Arc::new(RwLock::new(columns)),
}
}
#[must_use]
pub fn oid(&self) -> i64 {
self.oid
}
pub(crate) fn stamp(&mut self, oid: i64) {
self.oid = oid;
}
#[must_use]
pub fn name(&self) -> &QualifiedName {
&self.name
}
#[must_use]
pub fn sql(&self) -> &str {
&self.sql
}
#[must_use]
pub fn statement(&self) -> &str {
&self.statement
}
#[must_use]
pub fn aliases(&self) -> &[String] {
&self.aliases
}
#[must_use]
pub fn columns(&self) -> Vec<Field> {
self.columns.read().unwrap_or_else(|held| held.into_inner()).clone()
}
pub fn remember(&self, columns: Vec<Field>) {
*self.columns.write().unwrap_or_else(|held| held.into_inner()) = columns;
}
}
#[cfg(test)]
mod tests {
use rudb_common::{Field, LogicalType};
use super::View;
use crate::name::QualifiedName;
fn view(columns: Vec<Field>) -> View {
View::new(
QualifiedName::new("memory", "main", "v"),
"SELECT x FROM t".to_string(),
"CREATE VIEW v AS SELECT x FROM t;".to_string(),
Vec::new(),
columns,
)
}
#[test]
fn a_view_reports_the_columns_it_was_made_with() {
let made = view(vec![Field::new("x", LogicalType::Integer)]);
assert_eq!(made.columns(), vec![Field::new("x", LogicalType::Integer)]);
}
#[test]
fn a_bind_writes_over_what_the_last_one_left() {
let made = view(vec![Field::new("x", LogicalType::Integer)]);
made.remember(vec![
Field::new("x", LogicalType::Integer),
Field::new("z", LogicalType::Varchar),
]);
assert_eq!(made.columns().len(), 2);
assert_eq!(made.columns()[1].name, "z");
}
#[test]
fn a_copy_of_a_view_sees_what_the_original_was_told() {
let made = view(Vec::new());
let copy = made.clone();
made.remember(vec![Field::new("x", LogicalType::Integer)]);
assert_eq!(copy.columns().len(), 1);
}
}