1use crate::dsl;
2use crate::expression::array_comparison::{AsInExpression, InExpression};
3use crate::expression::subselect::Subselect;
4use crate::expression::{
5 AppearsOnTable, AsExpression, Expression, SelectableExpression, TypedExpressionType,
6 ValidGrouping,
7};
8use crate::pg::Pg;
9use crate::query_builder::combination_clause::CombinationClause;
10use crate::query_builder::{
11 AstPass, BoxedSelectStatement, QueryFragment, QueryId, SelectQuery, SelectStatement,
12};
13use crate::sql_types::{self, SqlType};
14use std::marker::PhantomData;
15
16pub fn array<ST, T>(elements: T) -> dsl::array<ST, T>
54where
55 T: IntoArrayExpression<ST>,
56 ST: SqlType + TypedExpressionType,
57{
58 elements.into_array_expression()
59}
60
61#[allow(non_camel_case_types)]
63#[cfg(feature = "postgres_backend")]
64pub type array<ST, T> = <T as IntoArrayExpression<ST>>::ArrayExpression;
65
66#[diagnostic::on_unimplemented(
70 message = "Cannot convert `{Self}` into an expression of type `Array<{ST}>`",
71 note = "`the trait bound `{Self}: IntoArrayExpression<{ST}>` is not satisfied. \
72 (`AsExpressionList` is a deprecated trait alias for `IntoArrayExpression`)"
73)]
74pub trait IntoArrayExpression<ST: SqlType + TypedExpressionType> {
75 type ArrayExpression: Expression<SqlType = sql_types::Array<ST>>;
77
78 fn into_array_expression(self) -> Self::ArrayExpression;
81}
82
83impl<ST, T> IntoArrayExpression<ST> for T
85where
86 T: AsExpression<sql_types::Array<ST>>,
87 ST: SqlType + TypedExpressionType + 'static,
88{
89 type ArrayExpression = <T as AsExpression<sql_types::Array<ST>>>::Expression;
90
91 fn into_array_expression(self) -> Self::ArrayExpression {
92 <T as AsExpression<sql_types::Array<ST>>>::as_expression(self)
93 }
94}
95
96macro_rules! tuple_impls {
102 ($(
103 $Tuple:tt {
104 $(($idx:tt) -> $T:ident, $ST:ident, $TT:ident,)+
105 }
106 )+) => {
107 $(
108 impl<$($T,)+ ST> IntoArrayExpression<ST> for ($($T,)+) where
109 $($T: AsExpression<ST>,)+
110 ST: SqlType + TypedExpressionType,
111 {
112 type ArrayExpression = ArrayLiteral<($($T::Expression,)+), ST>;
113
114 fn into_array_expression(self) -> Self::ArrayExpression {
115 ArrayLiteral {
116 elements: ($(self.$idx.as_expression(),)+),
117 _marker: PhantomData,
118 }
119 }
120 }
121 )+
122 }
123}
124
125diesel_derives::__diesel_for_each_tuple!(tuple_impls);
126
127#[derive(Debug, Clone, Copy, QueryId)]
129pub struct ArrayLiteral<T, ST> {
130 elements: T,
131 _marker: PhantomData<ST>,
132}
133
134impl<T, ST> Expression for ArrayLiteral<T, ST>
135where
136 ST: 'static,
137 T: Expression,
138{
139 type SqlType = sql_types::Array<ST>;
140}
141
142impl<T, ST> QueryFragment<Pg> for ArrayLiteral<T, ST>
143where
144 T: QueryFragment<Pg>,
145{
146 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> crate::result::QueryResult<()> {
147 out.push_sql("ARRAY[");
148 QueryFragment::walk_ast(&self.elements, out.reborrow())?;
149 out.push_sql("]");
150 Ok(())
151 }
152}
153
154impl<T, ST, QS> SelectableExpression<QS> for ArrayLiteral<T, ST>
155where
156 T: SelectableExpression<QS>,
157 ArrayLiteral<T, ST>: AppearsOnTable<QS>,
158{
159}
160
161impl<T, ST, QS> AppearsOnTable<QS> for ArrayLiteral<T, ST>
162where
163 T: AppearsOnTable<QS>,
164 ArrayLiteral<T, ST>: Expression,
165{
166}
167
168impl<T, ST, GB> ValidGrouping<GB> for ArrayLiteral<T, ST>
169where
170 T: ValidGrouping<GB>,
171{
172 type IsAggregate = T::IsAggregate;
173}
174
175impl<T, ST> InExpression for ArrayLiteral<T, ST>
176where
177 Self: Expression<SqlType = sql_types::Array<ST>>,
178 ST: SqlType,
179{
180 type SqlType = ST;
181
182 fn is_empty(&self) -> bool {
183 false
184 }
185
186 fn is_array(&self) -> bool {
187 false
189 }
190}
191
192impl<T, ST> AsInExpression<ST> for ArrayLiteral<T, ST>
193where
194 Self: Expression<SqlType = sql_types::Array<ST>>,
195 ST: SqlType,
196{
197 type InExpression = Self;
198
199 fn as_in_expression(self) -> Self::InExpression {
200 self
201 }
202}
203
204impl<ST, F, S, D, W, O, LOf, G, H, LC> IntoArrayExpression<ST>
205 for SelectStatement<F, S, D, W, O, LOf, G, H, LC>
206where
207 ST: SqlType + TypedExpressionType,
208 ArraySubselect<Self, ST>: Expression<SqlType = sql_types::Array<ST>>,
209 Self: SelectQuery<SqlType = ST>,
210{
211 type ArrayExpression = ArraySubselect<Self, ST>;
212
213 fn into_array_expression(self) -> Self::ArrayExpression {
214 ArraySubselect::new(self)
215 }
216}
217
218impl<'a, ST, QS, DB, GB> IntoArrayExpression<ST> for BoxedSelectStatement<'a, ST, QS, DB, GB>
219where
220 ST: SqlType + TypedExpressionType,
221 ArraySubselect<BoxedSelectStatement<'a, ST, QS, DB, GB>, ST>:
222 Expression<SqlType = sql_types::Array<ST>>,
223{
224 type ArrayExpression = ArraySubselect<Self, ST>;
225
226 fn into_array_expression(self) -> Self::ArrayExpression {
227 ArraySubselect::new(self)
228 }
229}
230
231impl<ST, Combinator, Rule, Source, Rhs> IntoArrayExpression<ST>
232 for CombinationClause<Combinator, Rule, Source, Rhs>
233where
234 ST: SqlType + TypedExpressionType,
235 Self: SelectQuery<SqlType = ST>,
236 ArraySubselect<Self, ST>: Expression<SqlType = sql_types::Array<ST>>,
237{
238 type ArrayExpression = ArraySubselect<Self, ST>;
239
240 fn into_array_expression(self) -> Self::ArrayExpression {
241 ArraySubselect::new(self)
242 }
243}
244
245#[derive(Debug, Clone, Copy, QueryId)]
247pub struct ArraySubselect<T, ST> {
248 subquery: Subselect<T, ST>,
249}
250
251impl<T, ST> ArraySubselect<T, ST> {
252 pub(crate) fn new(elements: T) -> Self {
253 Self {
254 subquery: Subselect::new(elements),
255 }
256 }
257}
258
259impl<T, ST> Expression for ArraySubselect<T, ST>
260where
261 ST: 'static,
262 Subselect<T, ST>: Expression<SqlType = ST>,
263{
264 type SqlType = sql_types::Array<ST>;
265}
266
267impl<T, ST> QueryFragment<Pg> for ArraySubselect<T, ST>
268where
269 Subselect<T, ST>: QueryFragment<Pg>,
270{
271 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> crate::result::QueryResult<()> {
272 out.push_sql("ARRAY(");
273 QueryFragment::walk_ast(&self.subquery, out.reborrow())?;
274 out.push_sql(")");
275 Ok(())
276 }
277}
278
279impl<T, ST, QS> SelectableExpression<QS> for ArraySubselect<T, ST>
280where
281 Subselect<T, ST>: SelectableExpression<QS>,
282 ArraySubselect<T, ST>: AppearsOnTable<QS>,
283{
284}
285
286impl<T, ST, QS> AppearsOnTable<QS> for ArraySubselect<T, ST>
287where
288 Subselect<T, ST>: AppearsOnTable<QS>,
289 ArraySubselect<T, ST>: Expression,
290{
291}
292
293impl<T, ST, GB> ValidGrouping<GB> for ArraySubselect<T, ST>
294where
295 Subselect<T, ST>: ValidGrouping<GB>,
296{
297 type IsAggregate = <Subselect<T, ST> as ValidGrouping<GB>>::IsAggregate;
298}
299
300impl<T, ST> InExpression for ArraySubselect<T, ST>
301where
302 Self: Expression<SqlType = sql_types::Array<ST>>,
303 ST: SqlType,
304{
305 type SqlType = ST;
306
307 fn is_empty(&self) -> bool {
308 false
309 }
310
311 fn is_array(&self) -> bool {
312 false
314 }
315}
316
317impl<T, ST> AsInExpression<ST> for ArraySubselect<T, ST>
318where
319 Self: Expression<SqlType = sql_types::Array<ST>>,
320 ST: SqlType,
321{
322 type InExpression = Self;
323
324 fn as_in_expression(self) -> Self::InExpression {
325 self
326 }
327}