datasources 0.1.5

Async datasource interfaces, middleware, registry, and test doubles
Documentation
use crate::builders::Join;
use crate::i_select_statement::ISelectStatement;
use crate::i_where::IWhere;
use crate::statements::statement::Statement;
use crate::statements::{OrderBy, SelectStatementOptions};
use crate::{DefaultStatementTextRenderer, StatementTextRenderer};

pub struct SelectStatement {
    where_clause: Option<Box<dyn IWhere>>,
    pub distinct: bool,
    pub table: String,
    pub fields: Vec<String>,
    pub joins: Vec<Join>,
    pub group_by: Vec<String>,
    pub having: Option<Box<dyn IWhere>>,
    pub order_by: Vec<OrderBy>,
    pub limit: Option<i64>,
    pub offset: Option<i64>,
}

impl SelectStatement {
    pub fn new(options: SelectStatementOptions<'_>) -> Self {
        Self {
            where_clause: options.where_clause.map(box_where),
            distinct: options.distinct,
            table: options.table.to_string(),
            fields: options
                .fields
                .iter()
                .map(|field| (*field).to_string())
                .collect(),
            joins: options.joins.to_vec(),
            group_by: options
                .group_by
                .iter()
                .map(|column| (*column).to_string())
                .collect(),
            having: options.having.map(box_where),
            order_by: options.order_by.to_vec(),
            limit: options.limit,
            offset: options.offset,
        }
    }

    pub fn where_clause(&self) -> Option<&dyn IWhere> {
        self.where_clause.as_deref()
    }

    pub fn having(&self) -> Option<&dyn IWhere> {
        self.having.as_deref()
    }

    pub fn replace_where(mut self, where_clause: impl IWhere + 'static) -> Self {
        self.where_clause = Some(Box::new(where_clause));
        self
    }

    pub fn replace_having(mut self, having: impl IWhere + 'static) -> Self {
        self.having = Some(Box::new(having));
        self
    }
}

impl Statement for SelectStatement {
    fn accept(&self, text: &StatementTextRenderer) -> String {
        text.statements().visit_select(self, text)
    }

    fn as_any(&self) -> &dyn std::any::Any {
        self
    }
    fn kind(&self) -> crate::statements::StatementKind {
        crate::statements::StatementKind::Select
    }
    fn predicate(&self) -> Option<&dyn IWhere> {
        self.where_clause.as_deref()
    }
}

impl crate::ReadInput for SelectStatement {
    fn as_statement(&self) -> Option<&dyn crate::Statement> {
        Some(self)
    }
}

impl ISelectStatement for SelectStatement {
    fn where_clause(&self) -> Option<&dyn IWhere> {
        self.where_clause.as_deref()
    }
}

fn box_where(predicate: &dyn IWhere) -> Box<dyn IWhere> {
    predicate
        .as_any()
        .downcast_ref::<crate::statements::Where>()
        .cloned()
        .map(|clause| Box::new(clause) as Box<dyn IWhere>)
        .unwrap_or_else(|| {
            Box::new(crate::where_text::WhereText::new(
                DefaultStatementTextRenderer::instance().render_where(predicate),
            ))
        })
}