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