use rudb_catalog::Catalog;
use rudb_common::{Error, Field, Result, Value};
use crate::result::QueryResult;
#[derive(Debug)]
pub struct Database {
catalog: Catalog,
}
impl Default for Database {
fn default() -> Self {
Self::new()
}
}
impl Database {
#[must_use]
pub fn new() -> Self {
Self { catalog: Catalog::new() }
}
#[must_use]
pub fn catalog(&self) -> &Catalog {
&self.catalog
}
pub fn catalog_mut(&mut self) -> &mut Catalog {
&mut self.catalog
}
pub fn create_table(&mut self, name: &str, columns: Vec<Field>) -> Result<()> {
let parts: Vec<&str> = name.split('.').collect();
let resolved = self.catalog.resolve_for_create(&parts)?;
self.catalog.create_table(resolved, columns)
}
pub fn drop_table(&mut self, name: &str) -> Result<()> {
let parts: Vec<&str> = name.split('.').collect();
let resolved = self.catalog.resolve(&parts)?;
self.catalog.drop_table(&resolved)
}
pub fn append(&mut self, name: &str, rows: &[Vec<Value>]) -> Result<()> {
let parts: Vec<&str> = name.split('.').collect();
let resolved = self.catalog.resolve(&parts)?;
self.catalog.table_mut(&resolved)?.rows_mut().append_rows(rows)
}
pub fn table_len(&self, name: &str) -> Result<usize> {
let parts: Vec<&str> = name.split('.').collect();
let resolved = self.catalog.resolve(&parts)?;
Ok(self.catalog.table(&resolved)?.rows().len())
}
pub fn query(&self, sql: &str) -> Result<QueryResult> {
let plan = rudb_bind::bind_sql(sql, &self.catalog)?;
let mut root = rudb_exec::build(&plan, &self.catalog)?;
let names = root.schema().names();
let types = root.schema().types();
let mut chunks = Vec::new();
while let Some(chunk) = root.next()? {
if chunk.is_empty() {
continue;
}
chunks.push(chunk.flatten()?);
}
Ok(QueryResult::new(names, types, chunks))
}
pub fn plan(&self, sql: &str) -> Result<String> {
let plan = rudb_bind::bind_sql(sql, &self.catalog)?;
Ok(plan.to_string())
}
pub fn value(&self, sql: &str) -> Result<Value> {
let result = self.query(sql)?;
if result.len() != 1 || result.width() != 1 {
return Err(Error::invalid_input(format!(
"expected one row of one column, got {} rows of {} columns",
result.len(),
result.width()
)));
}
Ok(result.value_at(0, 0))
}
}