datasources 0.1.47

Async datasource interfaces, middleware, registry, and test doubles
Documentation
use super::expression::Expression;
use super::identifier::Identifier;
use super::nested_where_argument::NestedWhereArgument;
use super::operator::Operator;
use super::statement::Statement;
use super::statement_text_renderer::StatementTextRenderer;
use super::Where;
use super::i_where::IWhere;
use super::nested_select_statement::NestedSelectStatement;
use crate::statements::SelectStatementOptions;
use crate::SelectStatement;

pub struct CreateNestedReadStoredProcedureStatement {
    name: String,
    nested: NestedSelectStatement,
    arguments: Vec<NestedWhereArgument>,
}

impl CreateNestedReadStoredProcedureStatement {
    pub fn new(
        name: impl Into<String>,
        nested: NestedSelectStatement,
        arguments: Vec<NestedWhereArgument>,
    ) -> Self {
        Self {
            name: name.into(),
            nested,
            arguments,
        }
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn nested(&self) -> &NestedSelectStatement {
        &self.nested
    }

    pub fn arguments(&self) -> &[NestedWhereArgument] {
        &self.arguments
    }

    pub fn select(&self) -> SelectStatement {
        with_arguments(&self.nested.select, &self.arguments)
    }
}

fn with_arguments(select: &SelectStatement, arguments: &[NestedWhereArgument]) -> SelectStatement {
    let mut clause = select
        .where_clause()
        .and_then(|item| item.as_any().downcast_ref::<Where>().cloned());
    for argument in arguments {
        let equals = Operator::Equals {
            left: Box::new(Expression::Identifier(Identifier::new(&argument.path))),
            right: Box::new(Expression::Identifier(Identifier::new(
                &argument.parameter.name,
            ))),
        };
        clause = Some(match clause {
            Some(existing) => Where::new(Operator::and(existing.condition, equals)),
            None => Where::new(equals),
        });
    }
    let field_refs: Vec<&str> = select.fields.iter().map(String::as_str).collect();
    let group: Vec<&str> = select.group_by.iter().map(String::as_str).collect();
    let aliases: Vec<Option<&str>> = select.aliases.iter().map(|alias| alias.as_deref()).collect();
    SelectStatement::new(SelectStatementOptions {
        distinct: select.distinct,
        joins: &select.joins,
        group_by: &group,
        order_by: &select.order_by,
        limit: select.limit,
        offset: select.offset,
        where_clause: clause.as_ref().map(|item| item as &dyn IWhere),
        having: select.having(),
        aliases: &aliases,
        ..SelectStatementOptions::new(&select.table, &field_refs)
    })
}

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

    fn as_any(&self) -> &dyn std::any::Any {
        self
    }
}

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