Skip to main content

drizzle_core/expr/
agg.rs

1//! Type-safe aggregate functions.
2//!
3//! These functions return expressions marked as aggregates, which can be used
4//! to enforce GROUP BY rules at compile time.
5//!
6//! # Type Safety
7//!
8//! - `sum`, `avg`: Require `Numeric` types (Int, `BigInt`, Float, Double)
9//! - `count`: Works with any type
10//! - `min`, `max`: Work with any type (ordered types in SQL)
11
12use crate::dialect::DialectTypes;
13use crate::sql::SQL;
14use crate::traits::SQLParam;
15use crate::types::{Array, Numeric};
16use crate::{PostgresDialect, SQLiteDialect};
17use drizzle_types::postgres::types::{
18    Boolean as PgBoolean, Float4, Float8, Int2, Int4, Int8, Numeric as PgNumeric,
19};
20use drizzle_types::sqlite::types::{
21    Integer as SqliteInteger, Numeric as SqliteNumeric, Real as SqliteReal,
22};
23
24use super::{Agg, Expr, NonNull, Null, SQLExpr, Scalar};
25
26// =============================================================================
27// Dialect Aggregate Policy
28// =============================================================================
29
30/// Dialect-specific aggregate output mapping.
31///
32/// Keeps aggregate output typing in one place so all aggregate functions
33/// follow the same per-dialect policy.
34#[diagnostic::on_unimplemented(
35    message = "no aggregate policy for `{Self}` on this dialect",
36    label = "aggregate result type is not defined for this SQL type/dialect"
37)]
38pub trait AggregatePolicy<D>: Numeric {
39    type Sum: crate::types::DataType;
40    type Avg: crate::types::DataType;
41}
42
43#[diagnostic::on_unimplemented(
44    message = "no statistical aggregate policy for `{Self}` on this dialect",
45    label = "stddev/variance result type is not defined for this SQL type/dialect"
46)]
47pub trait StatisticalAggregatePolicy<D>: Numeric {
48    type StddevPop: crate::types::DataType;
49    type StddevSamp: crate::types::DataType;
50    type VarPop: crate::types::DataType;
51    type VarSamp: crate::types::DataType;
52}
53
54#[diagnostic::on_unimplemented(
55    message = "boolean aggregates are not supported for `{Self}` on this dialect",
56    label = "use a boolean expression with a dialect that supports BOOL_AND/BOOL_OR"
57)]
58pub trait BooleanAggregatePolicy<D>: crate::types::DataType {}
59
60#[diagnostic::on_unimplemented(
61    message = "this aggregate is not available for this dialect",
62    label = "use a dialect-specific alternative"
63)]
64pub trait PostgresAggregateSupport {}
65
66#[diagnostic::on_unimplemented(
67    message = "this aggregate is not available for this dialect",
68    label = "use a dialect-specific alternative"
69)]
70pub trait SQLiteAggregateSupport {}
71
72#[diagnostic::on_unimplemented(
73    message = "no COUNT return type defined for this dialect",
74    label = "COUNT result type is not configured for this dialect marker"
75)]
76pub trait CountPolicy {
77    /// The integer type returned by COUNT (e.g. Integer on `SQLite`, Int8 on `PostgreSQL`).
78    type Count: crate::types::DataType;
79}
80
81impl CountPolicy for SQLiteDialect {
82    type Count = drizzle_types::sqlite::types::Integer;
83}
84
85impl CountPolicy for PostgresDialect {
86    type Count = drizzle_types::postgres::types::Int8;
87}
88
89#[diagnostic::on_unimplemented(
90    message = "no floating-point return type defined for this dialect",
91    label = "PERCENT_RANK/CUME_DIST result type is not configured for this dialect marker"
92)]
93pub trait FloatPolicy {
94    /// The floating-point type returned by distribution window functions
95    /// like `PERCENT_RANK` and `CUME_DIST` (Real on `SQLite`, Float8 on `PostgreSQL`).
96    type Float: crate::types::DataType;
97}
98
99impl FloatPolicy for SQLiteDialect {
100    type Float = drizzle_types::sqlite::types::Real;
101}
102
103impl FloatPolicy for PostgresDialect {
104    type Float = drizzle_types::postgres::types::Float8;
105}
106
107impl AggregatePolicy<SQLiteDialect> for SqliteInteger {
108    type Sum = Self;
109    type Avg = SqliteReal;
110}
111impl AggregatePolicy<SQLiteDialect> for SqliteReal {
112    type Sum = Self;
113    type Avg = Self;
114}
115impl AggregatePolicy<SQLiteDialect> for SqliteNumeric {
116    type Sum = Self;
117    type Avg = SqliteReal;
118}
119impl AggregatePolicy<SQLiteDialect> for drizzle_types::sqlite::types::Any {
120    type Sum = Self;
121    type Avg = SqliteReal;
122}
123
124impl StatisticalAggregatePolicy<PostgresDialect> for Int2 {
125    type StddevPop = Float8;
126    type StddevSamp = Float8;
127    type VarPop = Float8;
128    type VarSamp = Float8;
129}
130impl StatisticalAggregatePolicy<PostgresDialect> for Int4 {
131    type StddevPop = Float8;
132    type StddevSamp = Float8;
133    type VarPop = Float8;
134    type VarSamp = Float8;
135}
136impl StatisticalAggregatePolicy<PostgresDialect> for Int8 {
137    type StddevPop = Float8;
138    type StddevSamp = Float8;
139    type VarPop = Float8;
140    type VarSamp = Float8;
141}
142impl StatisticalAggregatePolicy<PostgresDialect> for Float4 {
143    type StddevPop = Float8;
144    type StddevSamp = Float8;
145    type VarPop = Float8;
146    type VarSamp = Float8;
147}
148impl StatisticalAggregatePolicy<PostgresDialect> for Float8 {
149    type StddevPop = Self;
150    type StddevSamp = Self;
151    type VarPop = Self;
152    type VarSamp = Self;
153}
154impl StatisticalAggregatePolicy<PostgresDialect> for PgNumeric {
155    type StddevPop = Float8;
156    type StddevSamp = Float8;
157    type VarPop = Float8;
158    type VarSamp = Float8;
159}
160
161impl BooleanAggregatePolicy<PostgresDialect> for PgBoolean {}
162
163impl PostgresAggregateSupport for PostgresDialect {}
164impl SQLiteAggregateSupport for SQLiteDialect {}
165
166impl AggregatePolicy<PostgresDialect> for Int2 {
167    type Sum = Int8;
168    type Avg = Float8;
169}
170impl AggregatePolicy<PostgresDialect> for Int4 {
171    type Sum = Int8;
172    type Avg = Float8;
173}
174impl AggregatePolicy<PostgresDialect> for Int8 {
175    type Sum = Self;
176    type Avg = Float8;
177}
178impl AggregatePolicy<PostgresDialect> for Float4 {
179    type Sum = Float8;
180    type Avg = Float8;
181}
182impl AggregatePolicy<PostgresDialect> for Float8 {
183    type Sum = Self;
184    type Avg = Self;
185}
186impl AggregatePolicy<PostgresDialect> for PgNumeric {
187    type Sum = Self;
188    type Avg = Self;
189}
190
191// =============================================================================
192// COUNT
193// =============================================================================
194
195/// COUNT(*) - counts all rows.
196///
197/// Returns a `BigInt`, `NonNull` (count is never NULL), Aggregate expression.
198///
199/// # Example
200///
201/// ```rust
202/// # let _ = r####"
203/// use drizzle_core::expr::count_all;
204///
205/// let total = count_all();
206/// // Generates: COUNT(*)
207/// # "####;
208/// ```
209#[must_use]
210pub fn count_all<'a, V>() -> SQLExpr<'a, V, <V::DialectMarker as CountPolicy>::Count, NonNull, Agg>
211where
212    V: SQLParam + 'a,
213    V::DialectMarker: CountPolicy,
214{
215    SQLExpr::new(SQL::raw("COUNT(*)"))
216}
217
218/// COUNT(expr) - counts non-null values.
219///
220/// Returns a `BigInt`, `NonNull` (count is never NULL), Aggregate expression.
221/// Works with any expression type.
222///
223/// # Example
224///
225/// ```rust
226/// # let _ = r####"
227/// use drizzle_core::expr::count;
228///
229/// let count = count(users.email);
230/// // Generates: COUNT("users"."email")
231/// # "####;
232/// ```
233pub fn count<'a, V, E>(
234    expr: E,
235) -> SQLExpr<'a, V, <V::DialectMarker as CountPolicy>::Count, NonNull, Agg>
236where
237    V: SQLParam + 'a,
238    V::DialectMarker: CountPolicy,
239    E: Expr<'a, V>,
240{
241    SQLExpr::new(SQL::func("COUNT", expr.into_sql()))
242}
243
244/// COUNT(DISTINCT expr) - counts distinct non-null values.
245///
246/// Returns a `BigInt`, `NonNull`, Aggregate expression.
247/// Works with any expression type.
248pub fn count_distinct<'a, V, E>(
249    expr: E,
250) -> SQLExpr<'a, V, <V::DialectMarker as CountPolicy>::Count, NonNull, Agg>
251where
252    V: SQLParam + 'a,
253    V::DialectMarker: CountPolicy,
254    E: Expr<'a, V>,
255{
256    SQLExpr::new(SQL::func(
257        "COUNT",
258        SQL::raw("DISTINCT").append(expr.into_sql()),
259    ))
260}
261
262// =============================================================================
263// SUM
264// =============================================================================
265
266/// SUM(expr) - sums numeric values.
267///
268/// Requires the expression to be `Numeric` (Int, `BigInt`, Float, Double).
269/// Result type is dialect-aware.
270/// Returns a nullable expression (empty set returns NULL).
271///
272/// # Type Safety
273///
274/// ```rust
275/// # let _ = r####"
276/// // ✅ OK: Numeric column
277/// sum(orders.amount);
278/// // SQLite: same width for integer sums
279/// // PostgreSQL: Int/SmallInt promote to BigInt
280///
281/// // ❌ Compile error: Text is not Numeric
282/// sum(users.name);
283/// # "####;
284/// ```
285pub fn sum<'a, V, E>(
286    expr: E,
287) -> SQLExpr<'a, V, <E::SQLType as AggregatePolicy<V::DialectMarker>>::Sum, Null, Agg>
288where
289    V: SQLParam + 'a,
290    E: Expr<'a, V>,
291    E::SQLType: AggregatePolicy<V::DialectMarker>,
292{
293    SQLExpr::new(SQL::func("SUM", expr.into_sql()))
294}
295
296/// SUM(DISTINCT expr) - sums distinct numeric values.
297///
298/// Requires the expression to be `Numeric`.
299/// Result type is dialect-aware.
300pub fn sum_distinct<'a, V, E>(
301    expr: E,
302) -> SQLExpr<'a, V, <E::SQLType as AggregatePolicy<V::DialectMarker>>::Sum, Null, Agg>
303where
304    V: SQLParam + 'a,
305    E: Expr<'a, V>,
306    E::SQLType: AggregatePolicy<V::DialectMarker>,
307{
308    SQLExpr::new(SQL::func(
309        "SUM",
310        SQL::raw("DISTINCT").append(expr.into_sql()),
311    ))
312}
313
314// =============================================================================
315// AVG
316// =============================================================================
317
318/// AVG(expr) - calculates average of numeric values.
319///
320/// Requires the expression to be `Numeric`.
321/// Always returns Double (SQL standard behavior), nullable.
322///
323/// # Type Safety
324///
325/// ```rust
326/// # let _ = r####"
327/// // ✅ OK: Numeric column
328/// avg(products.price);
329///
330/// // ❌ Compile error: Text is not Numeric
331/// avg(users.name);
332/// # "####;
333/// ```
334pub fn avg<'a, V, E>(
335    expr: E,
336) -> SQLExpr<'a, V, <E::SQLType as AggregatePolicy<V::DialectMarker>>::Avg, Null, Agg>
337where
338    V: SQLParam + 'a,
339    E: Expr<'a, V>,
340    E::SQLType: AggregatePolicy<V::DialectMarker>,
341{
342    SQLExpr::new(SQL::func("AVG", expr.into_sql()))
343}
344
345/// AVG(DISTINCT expr) - calculates average of distinct numeric values.
346///
347/// Requires the expression to be `Numeric`.
348pub fn avg_distinct<'a, V, E>(
349    expr: E,
350) -> SQLExpr<'a, V, <E::SQLType as AggregatePolicy<V::DialectMarker>>::Avg, Null, Agg>
351where
352    V: SQLParam + 'a,
353    E: Expr<'a, V>,
354    E::SQLType: AggregatePolicy<V::DialectMarker>,
355{
356    SQLExpr::new(SQL::func(
357        "AVG",
358        SQL::raw("DISTINCT").append(expr.into_sql()),
359    ))
360}
361
362// =============================================================================
363// MIN / MAX
364// =============================================================================
365
366/// MIN(expr) - finds minimum value.
367///
368/// Works with any expression type (ordered types in SQL).
369/// Preserves the input expression's SQL type.
370/// Result is nullable (empty set returns NULL).
371///
372/// # Example
373///
374/// ```rust
375/// # let _ = r####"
376/// use drizzle_core::expr::min;
377///
378/// let cheapest = min(products.price);
379/// // Generates: MIN("products"."price")
380/// // Returns the same SQL type as products.price
381/// # "####;
382/// ```
383pub fn min<'a, V, E>(expr: E) -> SQLExpr<'a, V, E::SQLType, Null, Agg>
384where
385    V: SQLParam + 'a,
386    E: Expr<'a, V>,
387{
388    SQLExpr::new(SQL::func("MIN", expr.into_sql()))
389}
390
391/// MAX(expr) - finds maximum value.
392///
393/// Works with any expression type (ordered types in SQL).
394/// Preserves the input expression's SQL type.
395/// Result is nullable (empty set returns NULL).
396///
397/// # Example
398///
399/// ```rust
400/// # let _ = r####"
401/// use drizzle_core::expr::max;
402///
403/// let most_expensive = max(products.price);
404/// // Generates: MAX("products"."price")
405/// // Returns the same SQL type as products.price
406/// # "####;
407/// ```
408pub fn max<'a, V, E>(expr: E) -> SQLExpr<'a, V, E::SQLType, Null, Agg>
409where
410    V: SQLParam + 'a,
411    E: Expr<'a, V>,
412{
413    SQLExpr::new(SQL::func("MAX", expr.into_sql()))
414}
415
416// =============================================================================
417// STATISTICAL FUNCTIONS
418// =============================================================================
419
420/// `STDDEV_POP` - population standard deviation.
421///
422/// Calculates the population standard deviation of numeric values.
423/// Requires the expression to be `Numeric`.
424/// Returns Double, nullable (empty set returns NULL).
425///
426/// Note: This function is available in `PostgreSQL`. `SQLite` does not have it built-in.
427///
428/// # Example
429///
430/// ```rust
431/// # let _ = r####"
432/// use drizzle_core::expr::stddev_pop;
433///
434/// let deviation = stddev_pop(measurements.value);
435/// // Generates: STDDEV_POP("measurements"."value")
436/// # "####;
437/// ```
438pub fn stddev_pop<'a, V, E>(
439    expr: E,
440) -> SQLExpr<
441    'a,
442    V,
443    <E::SQLType as StatisticalAggregatePolicy<V::DialectMarker>>::StddevPop,
444    Null,
445    Agg,
446>
447where
448    V: SQLParam + 'a,
449    E: Expr<'a, V>,
450    E::SQLType: StatisticalAggregatePolicy<V::DialectMarker>,
451{
452    SQLExpr::new(SQL::func("STDDEV_POP", expr.into_sql()))
453}
454
455/// `STDDEV_SAMP` / STDDEV - sample standard deviation.
456///
457/// Calculates the sample standard deviation of numeric values.
458/// Requires the expression to be `Numeric`.
459/// Returns Double, nullable (empty set returns NULL).
460///
461/// Note: This function is available in `PostgreSQL`. `SQLite` does not have it built-in.
462///
463/// # Example
464///
465/// ```rust
466/// # let _ = r####"
467/// use drizzle_core::expr::stddev_samp;
468///
469/// let deviation = stddev_samp(measurements.value);
470/// // Generates: STDDEV_SAMP("measurements"."value")
471/// # "####;
472/// ```
473pub fn stddev_samp<'a, V, E>(
474    expr: E,
475) -> SQLExpr<
476    'a,
477    V,
478    <E::SQLType as StatisticalAggregatePolicy<V::DialectMarker>>::StddevSamp,
479    Null,
480    Agg,
481>
482where
483    V: SQLParam + 'a,
484    E: Expr<'a, V>,
485    E::SQLType: StatisticalAggregatePolicy<V::DialectMarker>,
486{
487    SQLExpr::new(SQL::func("STDDEV_SAMP", expr.into_sql()))
488}
489
490/// `VAR_POP` - population variance.
491///
492/// Calculates the population variance of numeric values.
493/// Requires the expression to be `Numeric`.
494/// Returns Double, nullable (empty set returns NULL).
495///
496/// Note: This function is available in `PostgreSQL`. `SQLite` does not have it built-in.
497///
498/// # Example
499///
500/// ```rust
501/// # let _ = r####"
502/// use drizzle_core::expr::var_pop;
503///
504/// let variance = var_pop(measurements.value);
505/// // Generates: VAR_POP("measurements"."value")
506/// # "####;
507/// ```
508pub fn var_pop<'a, V, E>(
509    expr: E,
510) -> SQLExpr<'a, V, <E::SQLType as StatisticalAggregatePolicy<V::DialectMarker>>::VarPop, Null, Agg>
511where
512    V: SQLParam + 'a,
513    E: Expr<'a, V>,
514    E::SQLType: StatisticalAggregatePolicy<V::DialectMarker>,
515{
516    SQLExpr::new(SQL::func("VAR_POP", expr.into_sql()))
517}
518
519/// `VAR_SAMP` / VARIANCE - sample variance.
520///
521/// Calculates the sample variance of numeric values.
522/// Requires the expression to be `Numeric`.
523/// Returns Double, nullable (empty set returns NULL).
524///
525/// Note: This function is available in `PostgreSQL`. `SQLite` does not have it built-in.
526///
527/// # Example
528///
529/// ```rust
530/// # let _ = r####"
531/// use drizzle_core::expr::var_samp;
532///
533/// let variance = var_samp(measurements.value);
534/// // Generates: VAR_SAMP("measurements"."value")
535/// # "####;
536/// ```
537pub fn var_samp<'a, V, E>(
538    expr: E,
539) -> SQLExpr<'a, V, <E::SQLType as StatisticalAggregatePolicy<V::DialectMarker>>::VarSamp, Null, Agg>
540where
541    V: SQLParam + 'a,
542    E: Expr<'a, V>,
543    E::SQLType: StatisticalAggregatePolicy<V::DialectMarker>,
544{
545    SQLExpr::new(SQL::func("VAR_SAMP", expr.into_sql()))
546}
547
548/// VARIANCE - `PostgreSQL` alias for sample variance (`VAR_SAMP`).
549pub fn variance<'a, V, E>(
550    expr: E,
551) -> SQLExpr<'a, V, <E::SQLType as StatisticalAggregatePolicy<V::DialectMarker>>::VarSamp, Null, Agg>
552where
553    V: SQLParam + 'a,
554    E: Expr<'a, V>,
555    E::SQLType: StatisticalAggregatePolicy<V::DialectMarker>,
556{
557    SQLExpr::new(SQL::func("VARIANCE", expr.into_sql()))
558}
559
560/// `BOOL_AND` - true if all non-null inputs are true (`PostgreSQL`).
561pub fn bool_and<'a, V, E>(
562    expr: E,
563) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, Null, Agg>
564where
565    V: SQLParam + 'a,
566    V::DialectMarker: PostgresAggregateSupport,
567    E: Expr<'a, V>,
568    E::SQLType: BooleanAggregatePolicy<V::DialectMarker>,
569{
570    SQLExpr::new(SQL::func("BOOL_AND", expr.into_sql()))
571}
572
573/// `BOOL_OR` - true if any non-null input is true (`PostgreSQL`).
574pub fn bool_or<'a, V, E>(
575    expr: E,
576) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, Null, Agg>
577where
578    V: SQLParam + 'a,
579    V::DialectMarker: PostgresAggregateSupport,
580    E: Expr<'a, V>,
581    E::SQLType: BooleanAggregatePolicy<V::DialectMarker>,
582{
583    SQLExpr::new(SQL::func("BOOL_OR", expr.into_sql()))
584}
585
586/// `JSON_AGG` - aggregates values into a JSON array (`PostgreSQL`).
587pub fn json_agg<'a, V, E>(
588    expr: E,
589) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Json, Null, Agg>
590where
591    V: SQLParam + 'a,
592    V::DialectMarker: PostgresAggregateSupport,
593    E: Expr<'a, V>,
594{
595    SQLExpr::new(SQL::func("JSON_AGG", expr.into_sql()))
596}
597
598/// `JSONB_AGG` - aggregates values into a JSONB array (`PostgreSQL`).
599pub fn jsonb_agg<'a, V, E>(
600    expr: E,
601) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Jsonb, Null, Agg>
602where
603    V: SQLParam + 'a,
604    V::DialectMarker: PostgresAggregateSupport,
605    E: Expr<'a, V>,
606{
607    SQLExpr::new(SQL::func("JSONB_AGG", expr.into_sql()))
608}
609
610/// `ARRAY_AGG` - aggregates values into a SQL array (`PostgreSQL`).
611pub fn array_agg<'a, V, E>(expr: E) -> SQLExpr<'a, V, Array<E::SQLType>, Null, Agg>
612where
613    V: SQLParam + 'a,
614    V::DialectMarker: PostgresAggregateSupport,
615    E: Expr<'a, V>,
616{
617    SQLExpr::new(SQL::func("ARRAY_AGG", expr.into_sql()))
618}
619
620// =============================================================================
621// TOTAL (SQLite)
622// =============================================================================
623
624/// TOTAL - sums numeric values, returning 0.0 for empty sets (`SQLite`).
625///
626/// Unlike `SUM`, which returns NULL for an empty result set,
627/// `TOTAL` always returns a floating-point value (0.0 for empty sets).
628///
629/// # Example
630///
631/// ```rust
632/// # let _ = r####"
633/// use drizzle_core::expr::total;
634///
635/// // SELECT TOTAL(orders.amount)
636/// let total_amount = total(orders.amount);
637/// # "####;
638/// ```
639pub fn total<'a, V, E>(
640    expr: E,
641) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Double, NonNull, Agg>
642where
643    V: SQLParam + 'a,
644    V::DialectMarker: SQLiteAggregateSupport,
645    E: Expr<'a, V>,
646    E::SQLType: Numeric,
647{
648    SQLExpr::new(SQL::func("TOTAL", expr.into_sql()))
649}
650
651// =============================================================================
652// GROUP_CONCAT / STRING_AGG
653// =============================================================================
654
655/// `GROUP_CONCAT` - concatenates values into a string (`SQLite`).
656///
657/// Returns Text type, nullable.
658pub fn group_concat<'a, V, E>(
659    expr: E,
660) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Text, Null, Agg>
661where
662    V: SQLParam + 'a,
663    V::DialectMarker: SQLiteAggregateSupport,
664    E: Expr<'a, V>,
665    E::SQLType: crate::types::Textual,
666{
667    SQLExpr::new(SQL::func("GROUP_CONCAT", expr.into_sql()))
668}
669
670/// `STRING_AGG` - concatenates text values using a delimiter (`PostgreSQL`).
671pub fn string_agg<'a, V, E, D>(
672    expr: E,
673    delimiter: D,
674) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Text, Null, Agg>
675where
676    V: SQLParam + 'a,
677    V::DialectMarker: PostgresAggregateSupport,
678    E: Expr<'a, V>,
679    E::SQLType: crate::types::Textual,
680    D: Expr<'a, V>,
681    D::SQLType: crate::types::Textual,
682{
683    SQLExpr::new(SQL::func(
684        "STRING_AGG",
685        expr.into_sql()
686            .push(crate::Token::COMMA)
687            .append(delimiter.into_sql()),
688    ))
689}
690
691// =============================================================================
692// PostgreSQL Aggregate Functions
693// =============================================================================
694
695/// EVERY - true if all non-null inputs are true (`PostgreSQL`).
696///
697/// SQL standard alias for `BOOL_AND`.
698///
699/// # Example
700///
701/// ```rust
702/// # let _ = r####"
703/// use drizzle_core::expr::every;
704///
705/// // SELECT EVERY(orders.is_paid)
706/// let all_paid = every(orders.is_paid);
707/// # "####;
708/// ```
709pub fn every<'a, V, E>(
710    expr: E,
711) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, Null, Agg>
712where
713    V: SQLParam + 'a,
714    V::DialectMarker: PostgresAggregateSupport,
715    E: Expr<'a, V>,
716    E::SQLType: BooleanAggregatePolicy<V::DialectMarker>,
717{
718    SQLExpr::new(SQL::func("EVERY", expr.into_sql()))
719}
720
721/// `JSON_OBJECT_AGG` - aggregates key/value pairs into a JSON object (`PostgreSQL`).
722///
723/// # Example
724///
725/// ```rust
726/// # let _ = r####"
727/// use drizzle_core::expr::json_object_agg;
728///
729/// // SELECT JSON_OBJECT_AGG(settings.key, settings.value)
730/// let obj = json_object_agg(settings.key, settings.value);
731/// # "####;
732/// ```
733pub fn json_object_agg<'a, V, K, Val>(
734    key: K,
735    value: Val,
736) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Json, Null, Agg>
737where
738    V: SQLParam + 'a,
739    V::DialectMarker: PostgresAggregateSupport,
740    K: Expr<'a, V>,
741    Val: Expr<'a, V>,
742{
743    SQLExpr::new(SQL::func(
744        "JSON_OBJECT_AGG",
745        key.into_sql()
746            .push(crate::Token::COMMA)
747            .append(value.into_sql()),
748    ))
749}
750
751/// `JSONB_OBJECT_AGG` - aggregates key/value pairs into a JSONB object (`PostgreSQL`).
752///
753/// # Example
754///
755/// ```rust
756/// # let _ = r####"
757/// use drizzle_core::expr::jsonb_object_agg;
758///
759/// // SELECT JSONB_OBJECT_AGG(settings.key, settings.value)
760/// let obj = jsonb_object_agg(settings.key, settings.value);
761/// # "####;
762/// ```
763pub fn jsonb_object_agg<'a, V, K, Val>(
764    key: K,
765    value: Val,
766) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Jsonb, Null, Agg>
767where
768    V: SQLParam + 'a,
769    V::DialectMarker: PostgresAggregateSupport,
770    K: Expr<'a, V>,
771    Val: Expr<'a, V>,
772{
773    SQLExpr::new(SQL::func(
774        "JSONB_OBJECT_AGG",
775        key.into_sql()
776            .push(crate::Token::COMMA)
777            .append(value.into_sql()),
778    ))
779}
780
781// =============================================================================
782// Distinct Wrapper
783// =============================================================================
784
785/// DISTINCT - marks an expression as DISTINCT.
786///
787/// Typically used inside aggregate functions.
788pub fn distinct<'a, V, E>(expr: E) -> SQLExpr<'a, V, E::SQLType, E::Nullable, Scalar>
789where
790    V: SQLParam + 'a,
791    E: Expr<'a, V>,
792{
793    SQLExpr::new(SQL::raw("DISTINCT").append(expr.into_sql()))
794}