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