diesel_dynamic_schema/
dynamic_select.rs
1use diesel::backend::Backend;
2use diesel::expression::{is_aggregate, NonAggregate, ValidGrouping};
3use diesel::query_builder::{AstPass, QueryFragment, QueryId};
4use diesel::sql_types::Untyped;
5use diesel::{AppearsOnTable, Expression, QueryResult, SelectableExpression};
6use std::marker::PhantomData;
7
8#[allow(missing_debug_implementations)]
10pub struct DynamicSelectClause<'a, DB, QS> {
11 selects: Vec<Box<dyn QueryFragment<DB> + Send + 'a>>,
12 p: PhantomData<QS>,
13}
14
15impl<DB, QS> QueryId for DynamicSelectClause<'_, DB, QS> {
16 const HAS_STATIC_QUERY_ID: bool = false;
17 type QueryId = ();
18}
19
20impl<DB, QS> Default for DynamicSelectClause<'_, DB, QS> {
21 fn default() -> Self {
22 Self::new()
23 }
24}
25
26impl<'a, DB, QS> DynamicSelectClause<'a, DB, QS> {
27 pub fn new() -> Self {
29 Self {
30 selects: Vec::new(),
31 p: PhantomData,
32 }
33 }
34
35 pub fn add_field<F>(&mut self, field: F)
37 where
38 F: QueryFragment<DB> + SelectableExpression<QS> + NonAggregate + Send + 'a,
39 DB: Backend,
40 {
41 self.selects.push(Box::new(field))
42 }
43}
44
45impl<DB, QS> AppearsOnTable<QS> for DynamicSelectClause<'_, DB, QS> where Self: Expression {}
46
47impl<DB, QS> SelectableExpression<QS> for DynamicSelectClause<'_, DB, QS> where
48 Self: AppearsOnTable<QS>
49{
50}
51
52impl<QS, DB> Expression for DynamicSelectClause<'_, DB, QS> {
53 type SqlType = Untyped;
54}
55
56impl<DB, QS> QueryFragment<DB> for DynamicSelectClause<'_, DB, QS>
57where
58 DB: Backend,
59{
60 fn walk_ast<'b>(&'b self, mut pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
61 let mut first = true;
62 for s in &self.selects {
63 if first {
64 first = false;
65 } else {
66 pass.push_sql(", ");
67 }
68 s.walk_ast(pass.reborrow())?;
69 }
70 Ok(())
71 }
72}
73
74impl<DB, QS> ValidGrouping<()> for DynamicSelectClause<'_, DB, QS> {
75 type IsAggregate = is_aggregate::No;
76}