Skip to main content

qbrs_core/
expr.rs

1//! SQL types, columns, and the typed expression AST.
2//!
3//! `Expr<Req, S>` carries two purely phantom compile-time tags: `Req` (the
4//! flat cons-list of tables this expression touches — see `scope::Superset`)
5//! and `S` (its SQL type). The actual payload, `ExprKind`, is a plain closed
6//! enum with no generics at all, so the renderer is never re-monomorphized
7//! per query shape.
8
9use std::marker::PhantomData;
10
11use crate::scope::{Concat, Cons, MaybeNull, Nil, Table, WrapNullable};
12
13mod sql_type {
14    /// Sealed because the set really is closed: `Value` is a closed enum,
15    /// so a type this crate can't render has nothing to be — and an open
16    /// `SqlType` is what lets a schema crate pair a lying
17    /// `WrapNullable<MaybeNull>` with a column type of its own.
18    pub trait Sealed {}
19}
20
21/// A SQL scalar type. Implemented only by the closed set of leaf types
22/// declared via `sql_leaf_type!` below, plus `Nullable<T>`.
23pub trait SqlType: 'static + sql_type::Sealed {
24    type Native;
25}
26
27/// The non-generic expression payload, constructible only inside this
28/// crate: the typed `Expr<Req, S>` wrapper is the one way to build one,
29/// which is what makes its `Req`/`S` tags mean anything.
30#[derive(Debug, Clone)]
31pub(crate) enum ExprKind {
32    Column {
33        table: &'static str,
34        name: &'static str,
35    },
36    Value(Value),
37    BinOp {
38        op: BinOp,
39        lhs: Box<ExprKind>,
40        rhs: Box<ExprKind>,
41    },
42    And(Box<ExprKind>, Box<ExprKind>),
43    Or(Box<ExprKind>, Box<ExprKind>),
44    /// A condition with no operands left to check: what an empty `any_of`,
45    /// `all_of` or `is_in` means.
46    Always(bool),
47    Not(Box<ExprKind>),
48    /// `x IS NULL` / `x IS NOT NULL`. A separate node because `x = NULL` is
49    /// never true in SQL, so equality can't stand in for it.
50    IsNull {
51        expr: Box<ExprKind>,
52        negated: bool,
53    },
54    /// `x IN (a, b, ..)`. An empty list renders `FALSE`, which is what
55    /// `IN ()` means and what SQL itself won't parse.
56    InList {
57        expr: Box<ExprKind>,
58        values: Vec<ExprKind>,
59    },
60    /// `EXISTS (<subquery>)`. Held unrendered, because an `Expr` carries
61    /// no dialect: rendering it here would let a subquery written for one
62    /// dialect be filtered onto a statement of another.
63    Exists {
64        body: Box<crate::select::SelectBody>,
65        selection: Vec<crate::render::SelectItem>,
66        negated: bool,
67    },
68    /// `x IN (<subquery>)` / `x NOT IN (<subquery>)`. Held unrendered for
69    /// the same reason `Exists` is: an `Expr` carries no dialect, and a
70    /// subquery built for one dialect must not be filtered onto a statement
71    /// of another.
72    InSubquery {
73        lhs: Box<ExprKind>,
74        body: Box<crate::select::SelectBody>,
75        selection: Vec<crate::render::SelectItem>,
76        negated: bool,
77    },
78    /// `sql!{}`: authored text with a hole at each `?`, each hole holding an
79    /// expression the renderer recurses into — so a column in a hole is
80    /// quoted by the same code that quotes it anywhere else, and counts
81    /// toward the fragment's `Req`.
82    Template {
83        head: String,
84        rest: Vec<(ExprKind, String)>,
85    },
86    /// `CAST(expr AS type)`. The target is a kind rather than a string
87    /// because each dialect spells the type differently and the dialect
88    /// isn't known until the query renders.
89    Cast {
90        expr: Box<ExprKind>,
91        target: CastTarget,
92    },
93    /// `name(arg)`, or `name(*)` where there is no argument — the
94    /// aggregates. A real node rather than a raw fragment because an
95    /// argument is an expression the renderer has to recurse into, and
96    /// because that is what lets its column count toward the expression's
97    /// `Req`.
98    Func {
99        name: &'static str,
100        arg: Option<Box<ExprKind>>,
101    },
102    /// `string_agg(x, ', ')` and the two other spellings of it. Its own
103    /// node rather than a `Func`, because the dialects disagree on the
104    /// function's name and on where the separator goes, and an `Expr`
105    /// carries no dialect to decide that when it is built. The separator is
106    /// a `&'static str` written into the SQL rather than a bound value:
107    /// MySQL's `SEPARATOR` takes a literal and rejects a parameter, so
108    /// binding it would make the node unrenderable in one of the three.
109    StringAgg {
110        arg: Box<ExprKind>,
111        separator: &'static str,
112    },
113    /// `func OVER (PARTITION BY .. ORDER BY ..)`. `func` is rendered
114    /// literally: it's always one of the closed set of niladic ranking
115    /// functions, so there's no sub-expression to recurse into.
116    /// `partition_by`/`order_by` *are* full `ExprKind`s, since they can
117    /// reference real columns.
118    Window {
119        func: &'static str,
120        partition_by: Vec<ExprKind>,
121        order_by: Vec<(ExprKind, SortDir)>,
122    },
123}
124
125/// Sort direction. Shared by `ORDER BY` (`select::OrderKey`) and window
126/// functions' `OVER (.. ORDER BY ..)` (`window::Window`), hence living here
127/// rather than in either module.
128#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129pub enum SortDir {
130    Asc,
131    Desc,
132}
133
134/// The types an aggregate is cast back into, so its result stays inside the
135/// closed set of types this crate has natives for.
136#[doc(hidden)]
137#[derive(Debug, Clone, Copy, PartialEq, Eq)]
138pub enum CastTarget {
139    BigInt,
140    Double,
141}
142
143#[derive(Debug, Clone, Copy, PartialEq, Eq)]
144pub enum BinOp {
145    Eq,
146    Ne,
147    Lt,
148    Lte,
149    Gt,
150    Gte,
151    Like,
152}
153
154/// A closed, non-generic sum of every literal value the crate can bind as a
155/// query parameter. Deliberately not `Box<dyn ToSql>`: a plain enum keeps
156/// the renderer free of vtable dispatch and lets it stay a single
157/// non-generic function no matter how many query shapes exist.
158#[derive(Debug, Clone, PartialEq)]
159pub enum Value {
160    I32(i32),
161    I64(i64),
162    F64(f64),
163    Text(String),
164    Bool(bool),
165    Bytes(Vec<u8>),
166    /// A NULL of a specific base type, *not* a single untyped `Null`: a
167    /// Postgres bind declares a parameter type even when the value is NULL,
168    /// and a mismatched one can fail query planning. Each `NullX` variant
169    /// lets the execution layer bind `Option::<X>::None` with the right
170    /// type.
171    NullI32,
172    NullI64,
173    NullF64,
174    NullText,
175    NullBool,
176    NullBytes,
177    #[cfg(feature = "chrono")]
178    Timestamptz(chrono::DateTime<chrono::Utc>),
179    #[cfg(feature = "chrono")]
180    NullTimestamptz,
181    #[cfg(feature = "chrono")]
182    Date(chrono::NaiveDate),
183    #[cfg(feature = "chrono")]
184    NullDate,
185    #[cfg(feature = "uuid")]
186    Uuid(uuid::Uuid),
187    #[cfg(feature = "uuid")]
188    NullUuid,
189    #[cfg(feature = "decimal")]
190    Numeric(rust_decimal::Decimal),
191    #[cfg(feature = "decimal")]
192    NullNumeric,
193    /// Postgres array values: a `Vec<T>` binds as `T[]`, one variant per
194    /// element type.
195    TextArray(Vec<String>),
196    NullTextArray,
197    IntegerArray(Vec<i32>),
198    NullIntegerArray,
199    BigIntArray(Vec<i64>),
200    NullBigIntArray,
201    #[cfg(feature = "uuid")]
202    UuidArray(Vec<uuid::Uuid>),
203    #[cfg(feature = "uuid")]
204    NullUuidArray,
205    /// A JSON document, opaque to this crate: it binds and decodes, and the
206    /// operators that look inside one go through `sql!{}`.
207    #[cfg(feature = "json")]
208    Json(serde_json::Value),
209    #[cfg(feature = "json")]
210    NullJson,
211    /// A named placeholder in a `prepare!{}`-built query, not yet resolved
212    /// to a concrete value. It rides the existing `Vec<Value>` parameter
213    /// pipeline: rendering doesn't care what's *inside* a `Value`, only that
214    /// there's one per placeholder position. `select::Prepared` substitutes
215    /// real values before binding.
216    Placeholder(&'static str),
217}
218
219/// What a `json` column stores of a document, which is the text as given:
220/// `serde_json::Value`'s own `==` is structural and calls `0.0` and `-0.0`
221/// one value, and key order is a build-wide choice of `serde_json`'s. Both
222/// halves of the parameter index read a document through here, so what is
223/// compared and what is hashed cannot drift apart.
224#[cfg(feature = "json")]
225fn json_as_written(value: &serde_json::Value) -> String {
226    value.to_string()
227}
228
229impl Value {
230    /// The SQL type this value came from, for the one error that has to name
231    /// it: a column type enabled in this crate and not in the execution
232    /// crate. Lives here because the feature-gated variants do.
233    pub fn type_name(&self) -> &'static str {
234        match self {
235            Value::I32(_) | Value::NullI32 => "Integer",
236            Value::I64(_) | Value::NullI64 => "BigInt",
237            Value::F64(_) | Value::NullF64 => "Real",
238            Value::Text(_) | Value::NullText => "Text",
239            Value::Bool(_) | Value::NullBool => "Bool",
240            Value::Bytes(_) | Value::NullBytes => "Bytes",
241            Value::TextArray(_) | Value::NullTextArray => "TextArray",
242            Value::IntegerArray(_) | Value::NullIntegerArray => "IntegerArray",
243            Value::BigIntArray(_) | Value::NullBigIntArray => "BigIntArray",
244            #[cfg(feature = "uuid")]
245            Value::UuidArray(_) | Value::NullUuidArray => "UuidArray",
246            #[cfg(feature = "json")]
247            Value::Json(_) | Value::NullJson => "Json",
248            Value::Placeholder(_) => "placeholder",
249            #[cfg(feature = "chrono")]
250            Value::Timestamptz(_) | Value::NullTimestamptz => "Timestamptz",
251            #[cfg(feature = "chrono")]
252            Value::Date(_) | Value::NullDate => "Date",
253            #[cfg(feature = "uuid")]
254            Value::Uuid(_) | Value::NullUuid => "Uuid",
255            #[cfg(feature = "decimal")]
256            Value::Numeric(_) | Value::NullNumeric => "Numeric",
257        }
258    }
259
260    /// Whether these two values reach the database as the same parameter.
261    /// Not `==`, which calls values equal that a column then stores apart:
262    /// a `Decimal` compares by numeric value while Postgres's `numeric`
263    /// keeps the scale it was handed, so `1.0` and `1.00` are equal and are
264    /// stored as written; `0.0 == -0.0` while `double precision` keeps the
265    /// sign. Sharing a parameter between two such values would bind the
266    /// first one twice.
267    pub(crate) fn binds_same_as(&self, other: &Value) -> bool {
268        match (self, other) {
269            (Value::F64(a), Value::F64(b)) => a.to_bits() == b.to_bits(),
270            #[cfg(feature = "decimal")]
271            (Value::Numeric(a), Value::Numeric(b)) => a.serialize() == b.serialize(),
272            #[cfg(feature = "json")]
273            (Value::Json(a), Value::Json(b)) => json_as_written(a) == json_as_written(b),
274            _ => self == other,
275        }
276    }
277
278    /// Hashes what `binds_same_as` compares, so a statement can bucket the
279    /// parameters it holds. Not a `Hash` impl: it answers `binds_same_as`,
280    /// which is finer than `PartialEq`, and a `Hash` disagreeing with
281    /// `PartialEq` breaks the contract one owes its callers. The caller
282    /// supplies the hasher so the bucketing is keyed by the map's own
283    /// `RandomState` — with a fixed seed, colliding text chosen by whoever
284    /// supplies the values would walk the bucket the index exists to avoid.
285    pub(crate) fn hash_into<H: std::hash::Hasher>(&self, hasher: &mut H) {
286        use std::hash::Hash as _;
287        std::mem::discriminant(self).hash(hasher);
288        match self {
289            Value::I32(v) => v.hash(hasher),
290            Value::I64(v) => v.hash(hasher),
291            Value::F64(v) => v.to_bits().hash(hasher),
292            Value::Text(v) => v.hash(hasher),
293            Value::Bool(v) => v.hash(hasher),
294            Value::Bytes(v) => v.hash(hasher),
295            Value::Placeholder(v) => v.hash(hasher),
296            Value::TextArray(v) => v.hash(hasher),
297            Value::IntegerArray(v) => v.hash(hasher),
298            Value::BigIntArray(v) => v.hash(hasher),
299            #[cfg(feature = "uuid")]
300            Value::UuidArray(v) => v.hash(hasher),
301            #[cfg(feature = "json")]
302            Value::Json(v) => json_as_written(v).hash(hasher),
303            #[cfg(feature = "chrono")]
304            Value::Timestamptz(v) => v.hash(hasher),
305            #[cfg(feature = "chrono")]
306            Value::Date(v) => v.hash(hasher),
307            #[cfg(feature = "uuid")]
308            Value::Uuid(v) => v.hash(hasher),
309            #[cfg(feature = "decimal")]
310            Value::Numeric(v) => v.serialize().hash(hasher),
311            Value::NullI32
312            | Value::NullI64
313            | Value::NullF64
314            | Value::NullText
315            | Value::NullBool
316            | Value::NullBytes
317            | Value::NullTextArray
318            | Value::NullIntegerArray
319            | Value::NullBigIntArray => {}
320            #[cfg(feature = "uuid")]
321            Value::NullUuidArray => {}
322            #[cfg(feature = "json")]
323            Value::NullJson => {}
324            #[cfg(feature = "chrono")]
325            Value::NullTimestamptz | Value::NullDate => {}
326            #[cfg(feature = "uuid")]
327            Value::NullUuid => {}
328            #[cfg(feature = "decimal")]
329            Value::NullNumeric => {}
330        }
331    }
332}
333
334macro_rules! value_from {
335    ($ty:ty, $variant:ident) => {
336        impl From<$ty> for Value {
337            fn from(v: $ty) -> Self {
338                Value::$variant(v)
339            }
340        }
341    };
342}
343value_from!(i32, I32);
344value_from!(i64, I64);
345value_from!(f64, F64);
346value_from!(String, Text);
347value_from!(bool, Bool);
348value_from!(Vec<u8>, Bytes);
349#[cfg(feature = "chrono")]
350value_from!(chrono::DateTime<chrono::Utc>, Timestamptz);
351#[cfg(feature = "chrono")]
352value_from!(chrono::NaiveDate, Date);
353#[cfg(feature = "uuid")]
354value_from!(uuid::Uuid, Uuid);
355#[cfg(feature = "decimal")]
356value_from!(rust_decimal::Decimal, Numeric);
357value_from!(Vec<String>, TextArray);
358value_from!(Vec<i32>, IntegerArray);
359value_from!(Vec<i64>, BigIntArray);
360#[cfg(feature = "uuid")]
361value_from!(Vec<uuid::Uuid>, UuidArray);
362#[cfg(feature = "json")]
363value_from!(serde_json::Value, Json);
364
365impl From<&str> for Value {
366    fn from(v: &str) -> Self {
367        Value::Text(v.to_string())
368    }
369}
370
371/// A typed SQL expression. `Req` is the (possibly empty) flat list of
372/// tables this expression references — see the module docs and
373/// `scope::Superset` for how that's checked against a query's actual scope
374/// at the point the expression is used, not at the point it's built. This
375/// is what lets `orders::user_id.eq(users::id)` be a plain, portable value
376/// with no dependency on which query it'll eventually be used in.
377pub struct Expr<Req, S: SqlType> {
378    pub(crate) kind: ExprKind,
379    _marker: PhantomData<fn() -> (Req, S)>,
380}
381
382impl<Req, S: SqlType> Expr<Req, S> {
383    pub(crate) fn from_kind(kind: ExprKind) -> Self {
384        Expr {
385            kind,
386            _marker: PhantomData,
387        }
388    }
389}
390
391// Manual Clone: `#[derive(Clone)]` would incorrectly require `Req: Clone`
392// and `S: Clone`, even though both are purely phantom tags.
393impl<Req, S: SqlType> Clone for Expr<Req, S> {
394    fn clone(&self) -> Self {
395        Expr::from_kind(self.kind.clone())
396    }
397}
398
399/// Converts a value into a typed expression, tagging it with the set of
400/// tables it references (`Nil` for a plain literal, `Cons<T, Nil>` for a
401/// bare column, or whatever `Req` an already-built `Expr` carries).
402#[diagnostic::on_unimplemented(
403    message = "`{Self}` isn't a SQL expression",
404    label = "a column, a literal, an aggregate, or a `sql!{{}}` fragment is; a `label!` name is not",
405    note = "an `Option` isn't one either: asking about NULL is `.is_null()`, and assigning it is `null::<Text>()` — `= NULL` is never true in SQL"
406)]
407pub trait IntoExpr {
408    /// The SQL type this expression has. An associated type rather than a
409    /// parameter because every implementor has exactly one — a column its
410    /// declared type, a literal its leaf type — which is what lets a
411    /// mismatch report itself as `Comparable`/`AssignsTo` rather than as
412    /// an inference failure on a type nobody wrote.
413    type Sql: SqlType;
414    type Req;
415    fn into_expr(self) -> Expr<Self::Req, Self::Sql>;
416}
417
418impl<Req, S: SqlType> IntoExpr for Expr<Req, S> {
419    type Sql = S;
420    type Req = Req;
421    fn into_expr(self) -> Expr<Req, S> {
422        self
423    }
424}
425
426/// What an expression can be assigned *to*. The value's type is `Self` and
427/// the column's is the parameter, which is the direction assignment runs
428/// in: a `Text` value goes into a `Nullable<Text>` column and a narrower
429/// number into a wider one, never the reverse. (`Comparable` is the
430/// symmetric, nullability-blind relation, and a comparison is symmetric.)
431#[diagnostic::on_unimplemented(
432    message = "a `{Self}` expression can't be assigned to a `{Column}` column",
433    label = "the value has to fit the column: the same type, a narrower number, or a non-null value for a nullable column"
434)]
435pub trait AssignsTo<Column: SqlType>: SqlType {}
436
437impl<T: SqlType> AssignsTo<T> for T {}
438impl<T: SqlType> AssignsTo<crate::scope::Nullable<T>> for T {}
439
440mod writable {
441    /// Sealed like the other markers a derive emits: the door is
442    /// `#[doc(hidden)]`, so writing to a generated column is something a
443    /// caller can only do on purpose, never by forgetting an attribute.
444    pub trait Sealed {}
445}
446
447#[doc(hidden)]
448pub use writable::Sealed as WritableSealed;
449
450/// A column a statement may write to: `#[derive(Table)]` emits this for
451/// every column except the generated and primary-key ones, which are the
452/// same set `*Update` leaves out.
453#[diagnostic::on_unimplemented(
454    message = "`{Self}` isn't a column a statement can assign to",
455    label = "a primary-key or generated column is the database's to write, which is why `*Update` leaves it out too"
456)]
457pub trait Writable: WritableSealed {}
458
459/// A column's compile-time identity. One implementor per column in the
460/// schema, generated by `#[derive(Table)]` (and by `with!{}` for a CTE's
461/// pseudo-columns), which is what lets a column be a *key* — two columns of
462/// the same table and SQL type are still distinct types here, so a row can
463/// be indexed by column without ambiguity.
464pub trait ColumnKey: crate::row::Spelled + Copy + 'static {
465    type Table: Table;
466    type Sql: SqlType;
467}
468
469/// A column reference, identified entirely by its `ColumnKey`. Generated
470/// per-field by `#[derive(Table)]` as a `pub const NAME: Column<..>` inside
471/// each table's module (e.g. `users::id`). A plain, `Copy` value — not tied
472/// to any particular query — which is what lets it be reused across queries
473/// and passed as an ordinary function argument instead of through a
474/// scope-bound cursor closure.
475pub struct Column<C: ColumnKey>(PhantomData<C>);
476
477impl<C: ColumnKey> Column<C> {
478    pub const fn new() -> Self {
479        Column(PhantomData)
480    }
481}
482
483impl<C: ColumnKey> Default for Column<C> {
484    fn default() -> Self {
485        Self::new()
486    }
487}
488
489impl<C: ColumnKey> Clone for Column<C> {
490    fn clone(&self) -> Self {
491        *self
492    }
493}
494impl<C: ColumnKey> Copy for Column<C> {}
495
496impl<C: ColumnKey> IntoExpr for Column<C> {
497    type Sql = C::Sql;
498    type Req = Cons<C::Table, Nil>;
499    fn into_expr(self) -> Expr<Self::Req, C::Sql> {
500        Expr::from_kind(ExprKind::Column {
501            table: <C::Table as Table>::NAME,
502            name: <C as crate::row::Named>::NAME,
503        })
504    }
505}
506
507/// An expression that carries its own row key `K`: `count()` and the window
508/// functions, whose identity is the function that produced them. Selecting
509/// two of the same one into a row is what `row::Row::get` rejects, and what
510/// `LabelExt::label` exists to resolve.
511pub struct Keyed<K, Req, S: SqlType> {
512    pub(crate) kind: ExprKind,
513    _marker: PhantomData<fn() -> (K, Req, S)>,
514}
515
516impl<K, Req, S: SqlType> Keyed<K, Req, S> {
517    pub(crate) fn from_kind(kind: ExprKind) -> Self {
518        Keyed {
519            kind,
520            _marker: PhantomData,
521        }
522    }
523}
524
525impl<K, Req, S: SqlType> Clone for Keyed<K, Req, S> {
526    fn clone(&self) -> Self {
527        Keyed::from_kind(self.kind.clone())
528    }
529}
530
531impl<K, Req, S: SqlType> IntoExpr for Keyed<K, Req, S> {
532    type Sql = S;
533    type Req = Req;
534    fn into_expr(self) -> Expr<Req, S> {
535        Expr::from_kind(self.kind)
536    }
537}
538
539/// Which SQL types may be compared with each other. A nullable column and a
540/// non-nullable one hold the same values, so `users::manager_id.eq(users::id)`
541/// is an ordinary join predicate; without this relation the two would be
542/// unrelated types and every optional foreign key would be unwritable.
543///
544/// `Option` still isn't an expression, so `.eq(None)` remains unwritable:
545/// `x = NULL` is never true, and `.is_null()` is the question that was meant.
546#[diagnostic::on_unimplemented(
547    message = "`{Self}` and `{Other}` aren't comparable",
548    label = "both sides of a comparison must be the same SQL type, or two numeric ones",
549    note = "nullability doesn't matter here: a `Nullable<T>` compares with a `T`",
550    note = "an unannotated `vec![1, 2]` is an `integer[]`, since that is what an integer literal defaults to — a `bytea` takes `vec![1u8, 2]`"
551)]
552pub trait Comparable<Other: SqlType>: SqlType {}
553
554impl<T: SqlType> Comparable<T> for T {}
555impl<T: SqlType> Comparable<crate::scope::Nullable<T>> for T {}
556impl<T: SqlType> Comparable<T> for crate::scope::Nullable<T> {}
557
558/// Numeric widths compare across each other, so an untyped literal doesn't
559/// have to be annotated to match the column it's tested against.
560macro_rules! comparable_across {
561    ($($a:ty => $b:ty),+ $(,)?) => {
562        $(
563            impl Comparable<$b> for $a {}
564            impl Comparable<$b> for crate::scope::Nullable<$a> {}
565            impl Comparable<crate::scope::Nullable<$b>> for $a {}
566            impl Comparable<crate::scope::Nullable<$b>> for crate::scope::Nullable<$a> {}
567        )+
568    };
569}
570comparable_across!(
571    Integer => BigInt,
572    BigInt => Integer,
573    Integer => Real,
574    Real => Integer,
575    BigInt => Real,
576    Real => BigInt,
577);
578
579macro_rules! assigns_across {
580    ($($from:ty => $to:ty),+ $(,)?) => {
581        $(
582            impl AssignsTo<$to> for $from {}
583            impl AssignsTo<crate::scope::Nullable<$to>> for $from {}
584            impl AssignsTo<crate::scope::Nullable<$to>> for crate::scope::Nullable<$from> {}
585        )+
586    };
587}
588// Widening only: an `Integer` expression fits a `BigInt` column, not the
589// other way round.
590assigns_across!(
591    Integer => BigInt,
592    Integer => Real,
593    BigInt => Real,
594);
595
596#[cfg(feature = "decimal")]
597assigns_across!(
598    Integer => Numeric,
599    BigInt => Numeric,
600    Real => Numeric,
601);
602
603// A money column is compared against a literal more than it is compared
604// against another money column, and every database this crate speaks
605// compares numeric with the integers and floats.
606#[cfg(feature = "decimal")]
607comparable_across!(
608    Numeric => Integer,
609    Integer => Numeric,
610    Numeric => BigInt,
611    BigInt => Numeric,
612    Numeric => Real,
613    Real => Numeric,
614);
615
616/// A caller-declared output-column name, generated by `label!{}`. Being a
617/// marker over `Named` is what keeps `label!{}` the only way to make one,
618/// and `Named::NAME` the only place the name is written.
619pub trait LabelKey: crate::row::Spelled + Copy + 'static {}
620
621/// An expression that has stated what it decodes to but has no name: the
622/// anonymous `Keyed`, and so selectable, labellable and usable in a slot on
623/// exactly the same terms as any other keyed expression — except that
624/// `Anon` is not `Spelled`, so it can't be looked up or matched by name.
625pub type Declared<Req, S> = Keyed<crate::row::Anon, Req, S>;
626
627impl<Req, S: SqlType> Expr<Req, S> {
628    /// States what this expression decodes to, which is what makes it
629    /// selectable: `S` was inferred from whatever built the expression, and
630    /// an inference can contradict the join the query actually has.
631    pub fn decodes_as<S2: SqlType>(self) -> Declared<Req, S2> {
632        Keyed {
633            kind: self.kind,
634            _marker: PhantomData,
635        }
636    }
637}
638
639/// A selected item filed under a `LabelKey` instead of under its own
640/// identity, and rendered with that name as its `AS`.
641pub struct Labeled<K, Inner> {
642    pub(crate) inner: Inner,
643    _key: PhantomData<fn() -> K>,
644}
645
646impl<K, Inner: Clone> Clone for Labeled<K, Inner> {
647    fn clone(&self) -> Self {
648        Labeled::new(self.inner.clone())
649    }
650}
651
652impl<K, Inner> Labeled<K, Inner> {
653    pub(crate) fn new(inner: Inner) -> Self {
654        Labeled {
655            inner,
656            _key: PhantomData,
657        }
658    }
659}
660
661/// Files a selected item under a declared name: the way to select the same
662/// expression twice, and the way out of two tables' same-named columns
663/// colliding.
664pub trait LabelExt: Sized {
665    fn label<K: LabelKey>(self, _key: K) -> Labeled<K, Self> {
666        Labeled::new(self)
667    }
668}
669impl<C: ColumnKey> LabelExt for Column<C> {}
670impl<K, Req, S: SqlType> LabelExt for Keyed<K, Req, S> {}
671// A bare `Expr` isn't selectable — it has to state its decoded type first —
672// but labelling one has to *reach* that rule to report it. Without this
673// impl, `.label(..)` on an inferred expression is a missing method and the
674// sentence about `.decodes_as::<..>()` is never printed.
675impl<Req, S: SqlType> LabelExt for Expr<Req, S> {}
676
677/// Comparison/boolean-combinator methods, blanket-implemented for anything
678/// convertible to a typed expression (columns, literals, and `Expr` itself).
679/// Kept separate from `IntoExpr` so one blanket impl can serve all three.
680// Every combinator here consumes `self`, this crate's builders being
681// by-value throughout; `is_null`/`is_in` are combinators, not predicates on
682// an existing value.
683#[allow(clippy::wrong_self_convention)]
684pub trait ExprMethods: IntoExpr + Sized {
685    fn eq<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
686    where
687        Self::Sql: Comparable<Rhs::Sql>,
688        Self::Req: Concat<Rhs::Req>,
689    {
690        bin_op(BinOp::Eq, self, rhs)
691    }
692
693    fn ne<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
694    where
695        Self::Sql: Comparable<Rhs::Sql>,
696        Self::Req: Concat<Rhs::Req>,
697    {
698        bin_op(BinOp::Ne, self, rhs)
699    }
700
701    fn lt<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
702    where
703        Self::Sql: Comparable<Rhs::Sql>,
704        Self::Req: Concat<Rhs::Req>,
705    {
706        bin_op(BinOp::Lt, self, rhs)
707    }
708
709    fn lte<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
710    where
711        Self::Sql: Comparable<Rhs::Sql>,
712        Self::Req: Concat<Rhs::Req>,
713    {
714        bin_op(BinOp::Lte, self, rhs)
715    }
716
717    fn gt<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
718    where
719        Self::Sql: Comparable<Rhs::Sql>,
720        Self::Req: Concat<Rhs::Req>,
721    {
722        bin_op(BinOp::Gt, self, rhs)
723    }
724
725    fn gte<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
726    where
727        Self::Sql: Comparable<Rhs::Sql>,
728        Self::Req: Concat<Rhs::Req>,
729    {
730        bin_op(BinOp::Gte, self, rhs)
731    }
732
733    /// `x IS NULL`. Not expressible as `.eq(..)`: comparing to NULL with `=`
734    /// yields NULL, never true, so the two are different questions.
735    fn is_null(self) -> Expr<Self::Req, Bool> {
736        Expr::from_kind(ExprKind::IsNull {
737            expr: Box::new(self.into_expr().kind),
738            negated: false,
739        })
740    }
741
742    fn is_not_null(self) -> Expr<Self::Req, Bool> {
743        Expr::from_kind(ExprKind::IsNull {
744            expr: Box::new(self.into_expr().kind),
745            negated: true,
746        })
747    }
748
749    /// `a AND b`. The boolean requirement is on the method rather than on
750    /// the receiver's type, so every spelling a condition has — a
751    /// comparison, a `sql!` fragment, a `Nullable<Bool>` column — combines
752    /// with every other, the way `.filter` accepts them all.
753    fn and<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
754    where
755        Self::Sql: BoolLike,
756        Rhs::Sql: BoolLike,
757        Self::Req: Concat<Rhs::Req>,
758    {
759        Expr::from_kind(ExprKind::And(
760            Box::new(self.into_expr().kind),
761            Box::new(rhs.into_expr().kind),
762        ))
763    }
764
765    /// `a OR b` — see `and`.
766    fn or<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
767    where
768        Self::Sql: BoolLike,
769        Rhs::Sql: BoolLike,
770        Self::Req: Concat<Rhs::Req>,
771    {
772        Expr::from_kind(ExprKind::Or(
773            Box::new(self.into_expr().kind),
774            Box::new(rhs.into_expr().kind),
775        ))
776    }
777
778    /// `x LIKE 'pattern'`. The text requirement is on the method rather
779    /// than on a trait of its own, so a non-text operand reports `TextLike`
780    /// instead of a missing method.
781    fn like<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
782    where
783        Self::Sql: TextLike,
784        Rhs::Sql: TextLike,
785        Self::Req: Concat<Rhs::Req>,
786    {
787        bin_op(BinOp::Like, self, rhs)
788    }
789
790    /// `x IN (a, b, ..)` over a runtime-length list of literals, each bound
791    /// as its own parameter. An empty list renders `FALSE`.
792    ///
793    /// **Known limitation**: the list holds values, not expressions — a
794    /// column reference on the right needs the table it belongs to folded
795    /// into `Req`, which is the same design `sql!{}` covers today.
796    fn is_in<I>(self, values: I) -> Expr<Self::Req, Bool>
797    where
798        I: IntoIterator,
799        I::Item: IntoExpr<Req = Nil>,
800        Self::Sql: Comparable<<I::Item as IntoExpr>::Sql>,
801    {
802        let values: Vec<ExprKind> = values.into_iter().map(|v| v.into_expr().kind).collect();
803        // `IN ()` is not SQL, and matching nothing is what it would mean.
804        if values.is_empty() {
805            return Expr::from_kind(ExprKind::Always(false));
806        }
807        Expr::from_kind(ExprKind::InList {
808            expr: Box::new(self.into_expr().kind),
809            values,
810        })
811    }
812}
813
814/// True when any of the conditions is. Takes a runtime-length collection,
815/// the way `is_in` takes a runtime-length list of values, so the `OR` a
816/// search box needs doesn't have to be folded by hand — folding one by one
817/// grows `Req` and stops type-checking after the first pair. An empty
818/// collection matches nothing, which is what `is_in([])` says too.
819pub fn any_of<Req, C: IntoExpr<Req = Req>>(conds: impl IntoIterator<Item = C>) -> Expr<Req, Bool>
820where
821    C::Sql: BoolLike,
822{
823    combine(conds, false)
824}
825
826/// True when all of them are. An empty collection matches everything, which
827/// is what a `WHERE` with no conditions does.
828pub fn all_of<Req, C: IntoExpr<Req = Req>>(conds: impl IntoIterator<Item = C>) -> Expr<Req, Bool>
829where
830    C::Sql: BoolLike,
831{
832    combine(conds, true)
833}
834
835fn combine<Req, C: IntoExpr<Req = Req>>(
836    conds: impl IntoIterator<Item = C>,
837    all: bool,
838) -> Expr<Req, Bool>
839where
840    C::Sql: BoolLike,
841{
842    Expr::from_kind(fold_conditions(
843        conds.into_iter().map(|c| c.into_expr().kind),
844        all,
845    ))
846}
847
848/// AND- or OR-folds conditions, answering `TRUE`/`FALSE` for an empty
849/// collection — "all of nothing" matches everything, "any of nothing"
850/// matches nothing. Shared with `select::Predicate`, which folds the same
851/// way once the scope requirement is discharged.
852pub(crate) fn fold_conditions(kinds: impl IntoIterator<Item = ExprKind>, all: bool) -> ExprKind {
853    let mut folded: Option<ExprKind> = None;
854    for kind in kinds {
855        folded = Some(match folded {
856            None => kind,
857            Some(acc) if all => ExprKind::And(Box::new(acc), Box::new(kind)),
858            Some(acc) => ExprKind::Or(Box::new(acc), Box::new(kind)),
859        });
860    }
861    folded.unwrap_or(ExprKind::Always(all))
862}
863
864impl<T: IntoExpr> ExprMethods for T {}
865
866fn bin_op<Lhs, Rhs>(
867    op: BinOp,
868    lhs: Lhs,
869    rhs: Rhs,
870) -> Expr<<Lhs::Req as Concat<Rhs::Req>>::Output, Bool>
871where
872    Lhs: IntoExpr,
873    Rhs: IntoExpr,
874    Lhs::Req: Concat<Rhs::Req>,
875{
876    Expr::from_kind(ExprKind::BinOp {
877        op,
878        lhs: Box::new(lhs.into_expr().kind),
879        rhs: Box::new(rhs.into_expr().kind),
880    })
881}
882
883/// What `LIKE` accepts: a text expression, nullable or not. Its own marker
884/// rather than `Comparable<Text>` so the failure says what the operator
885/// needs instead of talking about comparison.
886#[diagnostic::on_unimplemented(
887    message = "`LIKE` needs a text expression, and `{Self}` isn't one",
888    label = "only `Text` and `Nullable<Text>` columns and expressions accept `.like(..)`"
889)]
890pub trait TextLike: SqlType {}
891
892impl TextLike for Text {}
893impl TextLike for crate::scope::Nullable<Text> {}
894
895/// What a `WHERE`/`HAVING`/`ON` clause accepts. `Nullable<Bool>` belongs
896/// here because SQL takes it: a NULL condition selects no row, which is
897/// the same answer `IS NOT TRUE` would give.
898#[diagnostic::on_unimplemented(
899    message = "a condition has to be a boolean expression, and `{Self}` isn't one",
900    label = "expected `Bool` or `Nullable<Bool>`"
901)]
902pub trait BoolLike: SqlType {}
903
904impl BoolLike for Bool {}
905impl BoolLike for crate::scope::Nullable<Bool> {}
906
907/// `!condition`, not `condition.not()`: the standard `Not` trait reads more
908/// naturally at call sites than a same-named inherent method. Implemented
909/// for all three spellings `.filter` takes, each keeping its own type —
910/// `NOT` of a `Nullable<Bool>` is still nullable, and a `sql!` fragment
911/// stays the same fragment.
912impl<Req, S: BoolLike> std::ops::Not for Expr<Req, S> {
913    type Output = Expr<Req, S>;
914    fn not(self) -> Self::Output {
915        Expr::from_kind(ExprKind::Not(Box::new(self.kind)))
916    }
917}
918
919impl<K, Req, S: BoolLike> std::ops::Not for Keyed<K, Req, S> {
920    type Output = Keyed<K, Req, S>;
921    fn not(self) -> Self::Output {
922        Keyed::from_kind(ExprKind::Not(Box::new(self.kind)))
923    }
924}
925
926impl<C: ColumnKey> std::ops::Not for Column<C>
927where
928    C::Sql: BoolLike,
929{
930    type Output = Expr<Cons<C::Table, Nil>, C::Sql>;
931    fn not(self) -> Self::Output {
932        Expr::from_kind(ExprKind::Not(Box::new(self.into_expr().kind)))
933    }
934}
935
936/// A base SQL type's typed NULL — see `Value::NullI32` etc. for why this
937/// can't just be a single untyped `Value::Null`.
938pub trait NullValue: SqlType {
939    const NULL_VALUE: Value;
940}
941
942/// A typed SQL `NULL`, for the one position an `Option` can't say it:
943/// `SET column = NULL` assigns, and an assignment has no `Option` to be
944/// `None`. `null::<Text>()` is `Nullable<Text>`, so only a nullable column
945/// accepts it.
946pub fn null<S: NullValue>() -> Expr<Nil, crate::scope::Nullable<S>> {
947    Expr::from_kind(ExprKind::Value(S::NULL_VALUE))
948}
949
950/// Declares a leaf (base) SQL type: the marker struct, its `SqlType` impl,
951/// its `WrapNullable<MaybeNull>` impl, and `IntoExpr` from its native Rust
952/// type. One concrete, non-generic impl per type — a blanket
953/// `impl<T: SqlType> WrapNullable<MaybeNull> for T` would conflict with
954/// `Nullable<T>`'s own impl (see `scope::WrapNullable`).
955mod raw_arg {
956    /// Sealed for the reason `select::ColumnList` is: `Req` is a free
957    /// parameter, and a slot's value can be delegated to a real column — so
958    /// a hand-written impl could claim `Nil` while naming a table, which is
959    /// exactly the scope check a `sql!` slot exists to keep.
960    pub trait Sealed {}
961    impl<T: super::IntoExpr> Sealed for T {}
962}
963
964macro_rules! sql_leaf_type {
965    ($name:ident, $native:ty, $null_variant:ident) => {
966        pub struct $name;
967
968        impl sql_type::Sealed for $name {}
969
970        impl SqlType for $name {
971            type Native = $native;
972        }
973
974        impl crate::scope::wrap::Sealed<MaybeNull> for $name {}
975
976        impl crate::scope::WrapNullable<MaybeNull> for $name {
977            type Output = crate::scope::Nullable<$name>;
978        }
979
980        impl IntoExpr for $native {
981            type Sql = $name;
982            type Req = Nil;
983            fn into_expr(self) -> Expr<Nil, $name> {
984                Expr::from_kind(ExprKind::Value(Value::from(self)))
985            }
986        }
987
988        impl crate::select::SingleColumn for $native {}
989        impl crate::select::SingleColumn for ::std::option::Option<$native> {}
990
991        impl NullValue for $name {
992            const NULL_VALUE: Value = Value::$null_variant;
993        }
994
995        impl crate::insert::IntoColumnValue<$native> for $native {
996            fn into_column_value(self) -> $native {
997                self
998            }
999        }
1000
1001        impl crate::insert::IntoColumnValue<::std::option::Option<$native>> for $native {
1002            fn into_column_value(self) -> ::std::option::Option<$native> {
1003                ::std::option::Option::Some(self)
1004            }
1005        }
1006
1007        impl crate::insert::IntoColumnValue<::std::option::Option<$native>>
1008            for ::std::option::Option<$native>
1009        {
1010            fn into_column_value(self) -> ::std::option::Option<$native> {
1011                self
1012            }
1013        }
1014
1015        impl crate::insert::IntoColumnValue<crate::insert::Defaultable<$native>> for $native {
1016            fn into_column_value(self) -> crate::insert::Defaultable<$native> {
1017                crate::insert::Defaultable::Value(self)
1018            }
1019        }
1020
1021        impl crate::insert::IntoColumnValue<crate::insert::Defaultable<$native>>
1022            for ::std::option::Option<$native>
1023        {
1024            fn into_column_value(self) -> crate::insert::Defaultable<$native> {
1025                match self {
1026                    ::std::option::Option::Some(v) => crate::insert::Defaultable::Value(v),
1027                    ::std::option::Option::None => crate::insert::Defaultable::Default,
1028                }
1029            }
1030        }
1031
1032        impl
1033            crate::insert::IntoColumnValue<
1034                crate::insert::Defaultable<::std::option::Option<$native>>,
1035            > for $native
1036        {
1037            fn into_column_value(
1038                self,
1039            ) -> crate::insert::Defaultable<::std::option::Option<$native>> {
1040                crate::insert::Defaultable::Value(::std::option::Option::Some(self))
1041            }
1042        }
1043
1044        impl
1045            crate::insert::IntoColumnValue<
1046                crate::insert::Defaultable<::std::option::Option<$native>>,
1047            > for ::std::option::Option<$native>
1048        {
1049            fn into_column_value(
1050                self,
1051            ) -> crate::insert::Defaultable<::std::option::Option<$native>> {
1052                match self {
1053                    ::std::option::Option::Some(v) => {
1054                        crate::insert::Defaultable::Value(::std::option::Option::Some(v))
1055                    }
1056                    ::std::option::Option::None => crate::insert::Defaultable::Default,
1057                }
1058            }
1059        }
1060
1061        impl raw_arg::Sealed for ::std::option::Option<$native> {}
1062
1063        impl RawArg for ::std::option::Option<$native> {
1064            type Req = Nil;
1065            fn into_raw_arg(self) -> RawSlot {
1066                RawSlot(ExprKind::Value(Value::from(self)))
1067            }
1068        }
1069
1070        impl crate::row::SameShape<$native> for $native {}
1071        impl crate::row::SameShape<::std::option::Option<$native>>
1072            for ::std::option::Option<$native>
1073        {
1074        }
1075
1076        // A nullable `prepare!{}` parameter binds through here, which is what
1077        // the typed `NullX` variants exist for.
1078        impl From<::std::option::Option<$native>> for Value {
1079            fn from(v: ::std::option::Option<$native>) -> Self {
1080                match v {
1081                    ::std::option::Option::Some(x) => Value::from(x),
1082                    ::std::option::Option::None => Value::$null_variant,
1083                }
1084            }
1085        }
1086    };
1087}
1088
1089sql_leaf_type!(Integer, i32, NullI32);
1090sql_leaf_type!(BigInt, i64, NullI64);
1091sql_leaf_type!(Real, f64, NullF64);
1092sql_leaf_type!(Text, String, NullText);
1093sql_leaf_type!(Bool, bool, NullBool);
1094sql_leaf_type!(Bytes, Vec<u8>, NullBytes);
1095
1096// Postgres arrays, over the four element types a schema reaches for.
1097//
1098// **Known limitations**: `BOOLEAN[]`, `DOUBLE PRECISION[]`, `TIMESTAMPTZ[]`
1099// and `NUMERIC[]` have no marker, and neither does an array whose elements
1100// can be NULL — a `Vec<T>` column decodes every element, so a row holding
1101// one fails to decode rather than arriving as `None`. Both wait for a
1102// schema that needs them. Arrays are Postgres's alone; an `Expr` carries no
1103// dialect, so rendering one for MySQL or SQLite is a bind their driver
1104// refuses rather than a compile error.
1105sql_leaf_type!(TextArray, Vec<String>, NullTextArray);
1106sql_leaf_type!(IntegerArray, Vec<i32>, NullIntegerArray);
1107sql_leaf_type!(BigIntArray, Vec<i64>, NullBigIntArray);
1108#[cfg(feature = "uuid")]
1109sql_leaf_type!(UuidArray, Vec<uuid::Uuid>, NullUuidArray);
1110
1111// A JSON document, Postgres's `jsonb`. Opaque: it goes in and comes back,
1112// and `->`, `->>`, `@>` and the rest of the operators that look inside one
1113// are deferred to `sql!{}` rather than half-built.
1114//
1115// **Known limitations**: a `json` column binds and decodes through this
1116// marker too, since the two are one wire format and one Rust type, but
1117// `json` has neither an equality nor an ordering operator — `.eq(..)`,
1118// `.asc()` and `GROUP BY` on one compile here and are rejected by the
1119// server. Which of the two a column is is a fact about the schema that
1120// nothing in a query can read, so it is `jsonb` that this marker claims.
1121#[cfg(feature = "json")]
1122sql_leaf_type!(Json, serde_json::Value, NullJson);
1123
1124// Types a database has and Rust doesn't: each decodes to the crate its
1125// feature names, so a schema that has no `timestamptz` column pays for none
1126// of it.
1127#[cfg(feature = "chrono")]
1128sql_leaf_type!(Timestamptz, chrono::DateTime<chrono::Utc>, NullTimestamptz);
1129#[cfg(feature = "chrono")]
1130sql_leaf_type!(Date, chrono::NaiveDate, NullDate);
1131#[cfg(feature = "uuid")]
1132sql_leaf_type!(Uuid, uuid::Uuid, NullUuid);
1133#[cfg(feature = "decimal")]
1134sql_leaf_type!(Numeric, rust_decimal::Decimal, NullNumeric);
1135
1136// Ergonomic extra: allow `&str` literals directly, without forcing
1137// `.to_string()` at every call site.
1138impl IntoExpr for &String {
1139    type Sql = Text;
1140    type Req = Nil;
1141    fn into_expr(self) -> Expr<Nil, Text> {
1142        Expr::from_kind(ExprKind::Value(Value::Text(self.clone())))
1143    }
1144}
1145
1146impl IntoExpr for &str {
1147    type Sql = Text;
1148    type Req = Nil;
1149    fn into_expr(self) -> Expr<Nil, Text> {
1150        Expr::from_kind(ExprKind::Value(Value::Text(self.to_string())))
1151    }
1152}
1153
1154/// Text's borrowed forms, at every slot a `String` column has. The leaf
1155/// macro can't generate these: only `Text` has a borrowed spelling.
1156macro_rules! text_column_value {
1157    ($borrowed:ty) => {
1158        impl crate::insert::IntoColumnValue<String> for $borrowed {
1159            fn into_column_value(self) -> String {
1160                self.to_string()
1161            }
1162        }
1163
1164        impl crate::insert::IntoColumnValue<Option<String>> for $borrowed {
1165            fn into_column_value(self) -> Option<String> {
1166                Some(self.to_string())
1167            }
1168        }
1169
1170        impl crate::insert::IntoColumnValue<crate::insert::Defaultable<String>> for $borrowed {
1171            fn into_column_value(self) -> crate::insert::Defaultable<String> {
1172                crate::insert::Defaultable::Value(self.to_string())
1173            }
1174        }
1175
1176        impl crate::insert::IntoColumnValue<crate::insert::Defaultable<Option<String>>>
1177            for $borrowed
1178        {
1179            fn into_column_value(self) -> crate::insert::Defaultable<Option<String>> {
1180                crate::insert::Defaultable::Value(Some(self.to_string()))
1181            }
1182        }
1183    };
1184}
1185
1186text_column_value!(&str);
1187text_column_value!(&String);
1188
1189impl<S: SqlType> sql_type::Sealed for crate::scope::Nullable<S> {}
1190
1191impl<S: SqlType> SqlType for crate::scope::Nullable<S> {
1192    type Native = Option<S::Native>;
1193}
1194
1195crate::row::expr_key!(
1196    Count,
1197    HasCount,
1198    count,
1199    "The identity a selected `count(*)` is filed under in a row.",
1200    'c',
1201    'o',
1202    'u',
1203    'n',
1204    't'
1205);
1206
1207/// `count(*)` as a rendered selection item, for `Select::count_sql`.
1208pub(crate) fn count_item() -> crate::render::SelectItem {
1209    crate::render::SelectItem::bare(count_star())
1210}
1211
1212fn count_star() -> ExprKind {
1213    ExprKind::Func {
1214        name: "count",
1215        arg: None,
1216    }
1217}
1218
1219/// Counts rows. `count_of(column)` counts that column's non-NULL values,
1220/// which is the different question a `LEFT JOIN` makes visible.
1221pub fn count() -> Keyed<Count, Nil, BigInt> {
1222    Keyed::from_kind(count_star())
1223}
1224
1225/// What `min`/`max` accept: a type the databases order. Its own marker for
1226/// the reason `Summable` is one — `WrapNullable<MaybeNull>`, which stood
1227/// here before, is implemented for every leaf type, so it gated nothing and
1228/// `max(bool_column)` rendered SQL Postgres has no aggregate for.
1229///
1230/// The set is Postgres's, the narrowest of the three: no `boolean`, no
1231/// `bytea`, and no `uuid` before PG 18.
1232#[diagnostic::on_unimplemented(
1233    message = "`min`/`max` need an ordered expression, and `{Self}` isn't one",
1234    label = "numbers, text, and dates/timestamps are ordered; booleans, bytes and UUIDs are not — `bool_or`/`bool_and` are the aggregate a flag wants, and aren't built yet"
1235)]
1236pub trait Ordered: SqlType + WrapNullable<MaybeNull> {}
1237
1238impl Ordered for Integer {}
1239impl Ordered for BigInt {}
1240impl Ordered for Real {}
1241impl Ordered for Text {}
1242#[cfg(feature = "decimal")]
1243impl Ordered for Numeric {}
1244#[cfg(feature = "chrono")]
1245impl Ordered for Timestamptz {}
1246#[cfg(feature = "chrono")]
1247impl Ordered for Date {}
1248
1249/// A nullable column orders like its base type — the NULLs sort, they don't
1250/// stop the aggregate from existing.
1251impl<S: Ordered> Ordered for crate::scope::Nullable<S> {}
1252
1253/// What `sum(..)` of a column decodes to. `sum` is NULL over zero rows, so
1254/// every result is nullable however the column was declared.
1255/// `CAST` keeps the widened type a database picks for a sum inside the
1256/// closed set of types this crate has: Postgres returns `numeric` for
1257/// `sum(bigint)` and `avg(int)`, neither of which has a native here.
1258#[diagnostic::on_unimplemented(
1259    message = "`sum`/`avg` need a numeric expression, and `{Self}` isn't one",
1260    label = "only `Integer`, `BigInt` and `Real` columns and expressions (and `Numeric`, with the `decimal` feature) can be summed or averaged"
1261)]
1262pub trait Summable: SqlType {
1263    type Sum: SqlType;
1264    const SUM_CAST: Option<CastTarget>;
1265    const AVG_CAST: Option<CastTarget> = Some(CastTarget::Double);
1266}
1267impl Summable for Integer {
1268    type Sum = crate::scope::Nullable<BigInt>;
1269    const SUM_CAST: Option<CastTarget> = None;
1270}
1271impl Summable for BigInt {
1272    type Sum = crate::scope::Nullable<BigInt>;
1273    const SUM_CAST: Option<CastTarget> = Some(CastTarget::BigInt);
1274}
1275impl Summable for Real {
1276    type Sum = crate::scope::Nullable<Real>;
1277    const SUM_CAST: Option<CastTarget> = None;
1278    const AVG_CAST: Option<CastTarget> = None;
1279}
1280// `sum(numeric)` stays numeric, so it needs no cast; `avg` decodes as `f64`
1281// for every column type, so a numeric one is cast like the rest.
1282#[cfg(feature = "decimal")]
1283impl Summable for Numeric {
1284    type Sum = crate::scope::Nullable<Numeric>;
1285    const SUM_CAST: Option<CastTarget> = None;
1286    const AVG_CAST: Option<CastTarget> = Some(CastTarget::Double);
1287}
1288impl<T: Summable> Summable for crate::scope::Nullable<T> {
1289    type Sum = T::Sum;
1290    const SUM_CAST: Option<CastTarget> = T::SUM_CAST;
1291    const AVG_CAST: Option<CastTarget> = T::AVG_CAST;
1292}
1293
1294/// The row key an aggregate over `C` is filed under: distinct per function
1295/// *and* per column, so `sum(a)` and `sum(b)` don't collide, and named after
1296/// the column so a DTO field or a CTE column can match it.
1297pub struct Agg<Op, C>(PhantomData<fn() -> (Op, C)>);
1298
1299// An aggregate is filed under the column it aggregates: `sum(orders::total)`
1300// reads back as `total`, and matches a CTE or DTO field of that name.
1301//
1302// **Known limitation**: by *name*, not by key — `Agg<Sum, total>` is its own
1303// key type, so `row.get(sum(orders::total))` and `#[derive(FromRow)]` find
1304// it and the generated `row.total()` accessor does not.
1305#[doc(hidden)]
1306impl<Op, C: crate::row::Named> crate::row::NamedSealed for Agg<Op, C> {}
1307
1308#[doc(hidden)]
1309impl<Op: 'static, C: crate::row::Named + 'static> crate::row::Named for Agg<Op, C> {
1310    type Name = <C as crate::row::Named>::Name;
1311    const NAME: &'static str = <C as crate::row::Named>::NAME;
1312}
1313
1314#[doc(hidden)]
1315impl<Op: 'static, C: crate::row::Spelled + 'static> crate::row::Spelled for Agg<Op, C> {}
1316
1317fn aggregate_kind<C: ColumnKey>(name: &'static str, cast: Option<CastTarget>) -> ExprKind {
1318    let call = ExprKind::Func {
1319        name,
1320        arg: Some(Box::new(ExprKind::Column {
1321            table: <C::Table as Table>::NAME,
1322            name: <C as crate::row::Named>::NAME,
1323        })),
1324    };
1325    match cast {
1326        Some(target) => ExprKind::Cast {
1327            expr: Box::new(call),
1328            target,
1329        },
1330        None => call,
1331    }
1332}
1333
1334macro_rules! aggregate {
1335    ($op:ident, $func:ident, $sql:literal, $out:ty, $bound:path, $cast:expr, $doc:literal) => {
1336        #[doc = $doc]
1337        pub struct $op;
1338
1339        #[doc = $doc]
1340        pub fn $func<C: ColumnKey>(
1341            _column: Column<C>,
1342        ) -> Keyed<Agg<$op, C>, Cons<C::Table, Nil>, $out>
1343        where
1344            C::Sql: $bound,
1345            $out: SqlType,
1346        {
1347            Keyed::from_kind(aggregate_kind::<C>($sql, $cast))
1348        }
1349    };
1350}
1351
1352aggregate!(
1353    Sum,
1354    sum,
1355    "sum",
1356    <C::Sql as Summable>::Sum,
1357    Summable,
1358    <C::Sql as Summable>::SUM_CAST,
1359    "`sum(column)`. NULL over zero rows, so the result is always nullable."
1360);
1361aggregate!(
1362    Min,
1363    min,
1364    "min",
1365    <C::Sql as WrapNullable<MaybeNull>>::Output,
1366    Ordered,
1367    None,
1368    "`min(column)`. NULL over zero rows."
1369);
1370aggregate!(
1371    Max,
1372    max,
1373    "max",
1374    <C::Sql as WrapNullable<MaybeNull>>::Output,
1375    Ordered,
1376    None,
1377    "`max(column)`. NULL over zero rows."
1378);
1379aggregate!(
1380    Avg,
1381    avg,
1382    "avg",
1383    crate::scope::Nullable<Real>,
1384    Summable,
1385    <C::Sql as Summable>::AVG_CAST,
1386    "`avg(column)`. NULL over zero rows."
1387);
1388aggregate!(
1389    CountOf,
1390    count_of,
1391    "count",
1392    BigInt,
1393    SqlType,
1394    None,
1395    "`count(column)` — non-NULL values, unlike `count()`'s `count(*)` rows."
1396);
1397
1398/// What `string_agg` accepts. Postgres defines it for `text` and for
1399/// `bytea` — and the `bytea` one concatenates bytes and returns `bytea`,
1400/// which is a different question than the one this asks — so text is the
1401/// set, as it is the set the other two dialects coerce their arguments
1402/// into anyway.
1403#[diagnostic::on_unimplemented(
1404    message = "`string_agg` concatenates text, and `{Self}` isn't text",
1405    label = "reach for a cast, or a raw fragment, in front of a column that isn't"
1406)]
1407pub trait Concatenable: SqlType {}
1408
1409impl Concatenable for Text {}
1410
1411/// A nullable column concatenates like its base type: `string_agg` skips
1412/// the NULLs rather than being undefined over them.
1413impl<S: Concatenable> Concatenable for crate::scope::Nullable<S> {}
1414
1415/// `string_agg(column, ", ")` — a group's values run together, separated.
1416/// NULL over zero rows, and over a group whose every value is NULL.
1417///
1418/// The separator binds like any other value under Postgres and SQLite,
1419/// which take it as an ordinary argument. MySQL's grammar takes a literal
1420/// after `SEPARATOR` and rejects a parameter, so there alone it is written
1421/// into the SQL and escaped — which is why it is a `&'static str` at all,
1422/// and why a MySQL session running `NO_BACKSLASH_ESCAPES` renders a
1423/// separator containing a backslash as more backslashes than were asked
1424/// for. `&'static str` is a nudge and not a guarantee, since `Box::leak`
1425/// reaches it; the guarantee is that the two dialects this crate executes
1426/// never write it out at all.
1427///
1428/// Two `string_agg`s over one column key alike, since the separator is not
1429/// part of the key — give one a `label!{}` name to read both back.
1430///
1431/// **Known limitation**: no `ORDER BY` inside the call
1432/// (`string_agg(x, ',' ORDER BY x)`) and no `DISTINCT`. Ordering inside an
1433/// aggregate reached SQLite only in 3.44, past the 3.39 this crate targets,
1434/// and MySQL spells it before the separator rather than after the
1435/// argument — three spellings of a clause two of the dialects would have
1436/// to be told to skip. Reach for `sql!{}` where the order matters.
1437pub struct StringAgg;
1438
1439/// `string_agg(column, ", ")`. See [`StringAgg`].
1440pub fn string_agg<C: ColumnKey>(
1441    _column: Column<C>,
1442    separator: &'static str,
1443) -> Keyed<Agg<StringAgg, C>, Cons<C::Table, Nil>, crate::scope::Nullable<Text>>
1444where
1445    C::Sql: Concatenable,
1446{
1447    Keyed::from_kind(ExprKind::StringAgg {
1448        arg: Box::new(ExprKind::Column {
1449            table: <C::Table as Table>::NAME,
1450            name: <C as crate::row::Named>::NAME,
1451        }),
1452        separator,
1453    })
1454}
1455
1456/// One `?` slot of a `sql!{}` fragment: every expression, plus the `Option`
1457/// a request field already holds — a slot is the one place a NULL arrives
1458/// as data rather than as a written `null::<..>()`. A slot that isn't one
1459/// reports `IntoExpr`, since that is the bound this one is built on.
1460pub trait RawArg: raw_arg::Sealed {
1461    type Req;
1462    #[doc(hidden)]
1463    fn into_raw_arg(self) -> RawSlot;
1464}
1465
1466impl<T: IntoExpr> RawArg for T {
1467    type Req = T::Req;
1468    fn into_raw_arg(self) -> RawSlot {
1469        RawSlot(self.into_expr().kind)
1470    }
1471}
1472
1473/// What a slot holds, opaque outside this crate: the `RawArg` impls are the
1474/// only way to make one, so a slot always holds something the renderer can
1475/// write.
1476pub struct RawSlot(ExprKind);
1477
1478impl RawSlot {
1479    fn into_kind(self) -> ExprKind {
1480        self.0
1481    }
1482}
1483
1484/// The whole slot list of one `sql!{}`, whose `Req` is every table its
1485/// slots name.
1486#[diagnostic::on_unimplemented(
1487    message = "a `sql!` fragment takes at most 8 `?` slots",
1488    label = "split the fragment, or fold part of it into the builder"
1489)]
1490pub trait RawArgs {
1491    type Req;
1492    #[doc(hidden)]
1493    fn into_raw_args(self) -> Vec<RawSlot>;
1494}
1495
1496impl RawArgs for () {
1497    type Req = Nil;
1498    fn into_raw_args(self) -> Vec<RawSlot> {
1499        Vec::new()
1500    }
1501}
1502
1503macro_rules! raw_args_tuple {
1504    ($head:ident $(, $rest:ident)*) => {
1505        #[allow(non_snake_case)]
1506        impl<$head: RawArg $(, $rest: RawArg)*> RawArgs for ($head, $($rest,)*)
1507        where
1508            ($($rest,)*): RawArgs,
1509            $head::Req: Concat<<($($rest,)*) as RawArgs>::Req>,
1510        {
1511            type Req = <$head::Req as Concat<<($($rest,)*) as RawArgs>::Req>>::Output;
1512            fn into_raw_args(self) -> Vec<RawSlot> {
1513                let ($head, $($rest,)*) = self;
1514                let mut kinds = ::std::vec![RawArg::into_raw_arg($head)];
1515                kinds.extend(RawArgs::into_raw_args(($($rest,)*)));
1516                kinds
1517            }
1518        }
1519    };
1520}
1521raw_args_tuple!(A);
1522raw_args_tuple!(A, B);
1523raw_args_tuple!(A, B, C);
1524raw_args_tuple!(A, B, C, D);
1525raw_args_tuple!(A, B, C, D, E);
1526raw_args_tuple!(A, B, C, D, E, F);
1527raw_args_tuple!(A, B, C, D, E, F, G);
1528raw_args_tuple!(A, B, C, D, E, F, G, H);
1529
1530/// Counts the `?` slots in a `sql!` text, so the macro can compare that
1531/// count with the number of arguments it was handed while both are still
1532/// constants.
1533#[doc(hidden)]
1534pub const fn placeholder_count(sql: &str) -> usize {
1535    let bytes = sql.as_bytes();
1536    let mut i = 0;
1537    let mut count = 0;
1538    while i < bytes.len() {
1539        if bytes[i] == b'?' {
1540            count += 1;
1541        }
1542        i += 1;
1543    }
1544    count
1545}
1546
1547/// The one door into `ExprKind` from outside the crate, and the only shape
1548/// that needs one: `sql!{}` expands in the caller's. `Req` is the union of
1549/// the slots' own, so a fragment carries exactly the tables its `?`s name.
1550/// Reached through `sql!`, which is what checks that every `?` has a value.
1551#[doc(hidden)]
1552pub fn raw_expr<S: SqlType, Args: RawArgs>(
1553    sql: &'static str,
1554    args: Args,
1555) -> Declared<Args::Req, S> {
1556    Keyed::from_kind(template(sql, args.into_raw_args()))
1557}
1558
1559/// Splits authored text on its `?` slots and pairs each with its argument.
1560/// `sql!` checks the two counts against each other while both are still
1561/// constants, which is why leftovers here can't happen through it.
1562fn template(sql: &'static str, args: Vec<RawSlot>) -> ExprKind {
1563    let mut pieces: Vec<String> = vec![String::new()];
1564    for c in sql.chars() {
1565        match c {
1566            '?' => pieces.push(String::new()),
1567            c => pieces.last_mut().expect("one piece to start").push(c),
1568        }
1569    }
1570
1571    let mut pieces = pieces.into_iter();
1572    let head = pieces.next().unwrap_or_default();
1573    let rest = args
1574        .into_iter()
1575        .map(RawSlot::into_kind)
1576        .zip(pieces)
1577        .collect();
1578    ExprKind::Template { head, rest }
1579}
1580
1581/// A named, typed placeholder: usable anywhere a value of type `S` is
1582/// expected (`.eq(placeholder::<Integer>("id"))`), rendered as a normal
1583/// bound parameter but resolved to a concrete value at
1584/// `Prepared::load()` time. `prepare!{}` is the intended entry point
1585/// rather than this function, since it also generates the typed `Params`
1586/// struct that makes a missing or misspelled placeholder a compile error.
1587#[doc(hidden)]
1588pub fn placeholder<S: SqlType>(name: &'static str) -> Expr<Nil, S> {
1589    Expr::from_kind(ExprKind::Value(Value::Placeholder(name)))
1590}