use crate::db::query::plan::expr::ast::{Alias, Expr, FieldId};
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum ProjectionSelection {
All,
Fields(Vec<FieldId>),
Expression(Expr),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum ProjectionField {
Scalar { expr: Expr, alias: Option<Alias> },
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub(crate) struct ProjectionSpec {
fields: Vec<ProjectionField>,
}
impl ProjectionSpec {
#[must_use]
pub(in crate::db::query::plan) const fn new(fields: Vec<ProjectionField>) -> Self {
Self { fields }
}
#[must_use]
#[cfg(test)]
pub(in crate::db) const fn from_fields_for_test(fields: Vec<ProjectionField>) -> Self {
Self::new(fields)
}
#[must_use]
pub(crate) const fn is_empty(&self) -> bool {
self.fields.is_empty()
}
#[must_use]
pub(crate) const fn len(&self) -> usize {
self.fields.len()
}
pub(crate) fn fields(&self) -> std::slice::Iter<'_, ProjectionField> {
self.fields.iter()
}
}
#[must_use]
pub(crate) fn expr_references_only_fields(expr: &Expr, allowed: &[&str]) -> bool {
match expr {
Expr::Field(field) => allowed.iter().any(|allowed| *allowed == field.as_str()),
Expr::Literal(_) | Expr::Aggregate(_) => true,
Expr::Alias { expr, .. } | Expr::Unary { expr, .. } => {
expr_references_only_fields(expr.as_ref(), allowed)
}
Expr::Binary { left, right, .. } => {
expr_references_only_fields(left.as_ref(), allowed)
&& expr_references_only_fields(right.as_ref(), allowed)
}
}
}