blob: c4944a11ad66ceb55981f6b745ad1d57d7f45955 [file] [log] [blame]
//! Within this module, types commonly use the following abbreviations:
//!
//! F: From Clause
//! S: Select Clause
//! D: Distinct Clause
//! W: Where Clause
//! O: Order By Clause
//! L: Limit Clause
//! Of: Offset Clause
//! G: Group By Clause
//! LC: For Update Clause
#![allow(missing_docs)] // The missing_docs lint triggers even though this is hidden
mod boxed;
mod dsl_impls;
pub use self::boxed::BoxedSelectStatement;
use super::distinct_clause::NoDistinctClause;
use super::group_by_clause::NoGroupByClause;
use super::limit_clause::NoLimitClause;
use super::locking_clause::NoLockingClause;
use super::offset_clause::NoOffsetClause;
use super::order_clause::NoOrderClause;
use super::select_clause::*;
use super::where_clause::*;
use super::{AstPass, Query, QueryFragment};
use crate::backend::Backend;
use crate::expression::subselect::ValidSubselect;
use crate::expression::*;
use crate::query_builder::SelectQuery;
use crate::query_source::joins::{AppendSelection, Inner, Join};
use crate::query_source::*;
use crate::result::QueryResult;
#[derive(Debug, Clone, Copy, QueryId)]
#[doc(hidden)]
#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
pub struct SelectStatement<
From,
Select = DefaultSelectClause,
Distinct = NoDistinctClause,
Where = NoWhereClause,
Order = NoOrderClause,
Limit = NoLimitClause,
Offset = NoOffsetClause,
GroupBy = NoGroupByClause,
Locking = NoLockingClause,
> {
pub(crate) select: Select,
pub(crate) from: From,
pub(crate) distinct: Distinct,
pub(crate) where_clause: Where,
pub(crate) order: Order,
pub(crate) limit: Limit,
pub(crate) offset: Offset,
pub(crate) group_by: GroupBy,
pub(crate) locking: Locking,
}
impl<F, S, D, W, O, L, Of, G, LC> SelectStatement<F, S, D, W, O, L, Of, G, LC> {
#[allow(clippy::too_many_arguments)]
pub fn new(
select: S,
from: F,
distinct: D,
where_clause: W,
order: O,
limit: L,
offset: Of,
group_by: G,
locking: LC,
) -> Self {
SelectStatement {
select: select,
from: from,
distinct: distinct,
where_clause: where_clause,
order: order,
limit: limit,
offset: offset,
group_by: group_by,
locking: locking,
}
}
}
impl<F> SelectStatement<F> {
pub fn simple(from: F) -> Self {
SelectStatement::new(
DefaultSelectClause,
from,
NoDistinctClause,
NoWhereClause,
NoOrderClause,
NoLimitClause,
NoOffsetClause,
NoGroupByClause,
NoLockingClause,
)
}
}
impl<F, S, D, W, O, L, Of, G, LC> Query for SelectStatement<F, S, D, W, O, L, Of, G, LC>
where
S: SelectClauseExpression<F>,
W: ValidWhereClause<F>,
{
type SqlType = S::SelectClauseSqlType;
}
impl<F, S, D, W, O, L, Of, G, LC> SelectQuery for SelectStatement<F, S, D, W, O, L, Of, G, LC>
where
S: SelectClauseExpression<F>,
{
type SqlType = S::SelectClauseSqlType;
}
impl<F, S, D, W, O, L, Of, G, LC, DB> QueryFragment<DB>
for SelectStatement<F, S, D, W, O, L, Of, G, LC>
where
DB: Backend,
S: SelectClauseQueryFragment<F, DB>,
F: QuerySource,
F::FromClause: QueryFragment<DB>,
D: QueryFragment<DB>,
W: QueryFragment<DB>,
O: QueryFragment<DB>,
L: QueryFragment<DB>,
Of: QueryFragment<DB>,
G: QueryFragment<DB>,
LC: QueryFragment<DB>,
{
fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
out.push_sql("SELECT ");
self.distinct.walk_ast(out.reborrow())?;
self.select.walk_ast(&self.from, out.reborrow())?;
out.push_sql(" FROM ");
self.from.from_clause().walk_ast(out.reborrow())?;
self.where_clause.walk_ast(out.reborrow())?;
self.group_by.walk_ast(out.reborrow())?;
self.order.walk_ast(out.reborrow())?;
self.limit.walk_ast(out.reborrow())?;
self.offset.walk_ast(out.reborrow())?;
self.locking.walk_ast(out.reborrow())?;
Ok(())
}
}
impl<S, D, W, O, L, Of, G, LC, DB> QueryFragment<DB>
for SelectStatement<(), S, D, W, O, L, Of, G, LC>
where
DB: Backend,
S: SelectClauseQueryFragment<(), DB>,
D: QueryFragment<DB>,
W: QueryFragment<DB>,
O: QueryFragment<DB>,
L: QueryFragment<DB>,
Of: QueryFragment<DB>,
G: QueryFragment<DB>,
LC: QueryFragment<DB>,
{
fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
out.push_sql("SELECT ");
self.distinct.walk_ast(out.reborrow())?;
self.select.walk_ast(&(), out.reborrow())?;
self.where_clause.walk_ast(out.reborrow())?;
self.group_by.walk_ast(out.reborrow())?;
self.order.walk_ast(out.reborrow())?;
self.limit.walk_ast(out.reborrow())?;
self.offset.walk_ast(out.reborrow())?;
self.locking.walk_ast(out.reborrow())?;
Ok(())
}
}
impl<S, F, D, W, O, L, Of, G, LC, QS> ValidSubselect<QS>
for SelectStatement<F, S, D, W, O, L, Of, LC, G>
where
Self: SelectQuery,
W: ValidWhereClause<Join<F, QS, Inner>>,
{
}
/// Allow `SelectStatement<From>` to act as if it were `From` as long as
/// no other query methods have been called on it
impl<From, T> AppearsInFromClause<T> for SelectStatement<From>
where
From: AppearsInFromClause<T>,
{
type Count = From::Count;
}
impl<From> QuerySource for SelectStatement<From>
where
From: QuerySource,
From::DefaultSelection: SelectableExpression<Self>,
{
type FromClause = From::FromClause;
type DefaultSelection = From::DefaultSelection;
fn from_clause(&self) -> Self::FromClause {
self.from.from_clause()
}
fn default_selection(&self) -> Self::DefaultSelection {
self.from.default_selection()
}
}
impl<From, Selection> AppendSelection<Selection> for SelectStatement<From>
where
From: AppendSelection<Selection>,
{
type Output = From::Output;
fn append_selection(&self, selection: Selection) -> Self::Output {
self.from.append_selection(selection)
}
}