use rudb_catalog::Table;
use rudb_common::{Error, Result};
use rudb_plan::{ExprRef, Plan, Slice};
use rudb_vector::{Chunk, VECTOR_SIZE, Vector};
use crate::expr::evaluate_all;
use crate::operator::Operator;
use crate::schema::Schema;
#[derive(Debug)]
pub(crate) struct Scan<'a> {
table: &'a Table,
columns: Vec<usize>,
schema: Schema,
at: usize,
}
impl<'a> Scan<'a> {
pub(crate) fn new(
plan: &Plan,
table: &'a Table,
index: u32,
projection: Slice,
) -> Result<Self> {
let fields = plan.field_list(projection).to_vec();
let mut columns = Vec::with_capacity(fields.len());
for field in &fields {
let position = table.column_index(&field.name).ok_or_else(|| {
Error::catalog(format!(
"Table \"{}\" does not have a column named \"{}\"",
table.name().table,
field.name
))
})?;
columns.push(position);
}
let schema = Schema::numbered(fields, index);
Ok(Self { table, columns, schema, at: 0 })
}
}
impl Operator for Scan<'_> {
fn schema(&self) -> &Schema {
&self.schema
}
fn next(&mut self) -> Result<Option<Chunk>> {
if self.at >= self.table.rows().chunk_count() {
return Ok(None);
}
let chunk = self.table.rows().read(self.at, &self.columns)?;
self.at += 1;
Ok(Some(chunk))
}
}
#[derive(Debug)]
pub(crate) struct Dummy {
schema: Schema,
done: bool,
}
impl Dummy {
pub(crate) fn new() -> Self {
Self { schema: Schema::empty(), done: false }
}
}
impl Operator for Dummy {
fn schema(&self) -> &Schema {
&self.schema
}
fn next(&mut self) -> Result<Option<Chunk>> {
if self.done {
return Ok(None);
}
self.done = true;
Ok(Some(Chunk::with_rows(Vec::new(), 1)?))
}
}
#[derive(Debug)]
pub(crate) struct Values {
schema: Schema,
chunks: Vec<Chunk>,
at: usize,
}
impl Values {
pub(crate) fn new(plan: &Plan, index: u32, columns: Slice, rows: Slice) -> Result<Self> {
let fields = plan.field_list(columns).to_vec();
let schema = Schema::numbered(fields, index);
let types = schema.types();
let source = Schema::empty();
let one = Chunk::with_rows(Vec::new(), 1)?;
let mut down: Vec<Vec<rudb_common::Value>> = vec![Vec::new(); types.len()];
for row in plan.row_list(rows) {
let exprs: Vec<ExprRef> = plan.expr_list(*row).to_vec();
if exprs.len() != types.len() {
return Err(Error::internal(format!(
"a VALUES row of {} expressions in a {} column list",
exprs.len(),
types.len()
)));
}
let evaluated = evaluate_all(plan, &exprs, &source, &one)?;
for (position, vector) in evaluated.iter().enumerate() {
down[position].push(vector.value_at(0));
}
}
let total = down.first().map_or(0, Vec::len);
let mut chunks = Vec::new();
let mut start = 0;
while start < total {
let end = (start + VECTOR_SIZE).min(total);
let mut built = Vec::with_capacity(types.len());
for (position, ty) in types.iter().enumerate() {
built.push(Vector::from_values(ty.clone(), &down[position][start..end])?);
}
chunks.push(Chunk::with_rows(built, end - start)?);
start = end;
}
Ok(Self { schema, chunks, at: 0 })
}
}
impl Operator for Values {
fn schema(&self) -> &Schema {
&self.schema
}
fn next(&mut self) -> Result<Option<Chunk>> {
if self.at >= self.chunks.len() {
return Ok(None);
}
let chunk = self.chunks[self.at].clone();
self.at += 1;
Ok(Some(chunk))
}
}