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    /// `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 — so a column in a hole is
92    /// quoted by the same code that quotes it anywhere else, and counts
93    /// 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; `0.0 == -0.0` while `double precision` keeps the
277    /// 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's checked against a query's actual scope
386/// at the point the expression is used, not at the point it's built. This
387/// is what lets `orders::user_id.eq(users::id)` be a plain, portable value
388/// 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()`, and assigning it is `null::<Text>()` — `= NULL` is never true in SQL"
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 — which is what lets a
423    /// mismatch report itself as `Comparable`/`AssignsTo` rather than as
424    /// an 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), which 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 — not tied
484/// to any particular query — which is what lets it be reused across queries
485/// and passed as an ordinary function argument instead of through a
486/// scope-bound cursor 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 — except that
670/// `Anon` is not `Spelled`, so it can't be looked up or matched by name.
671pub type Declared<Req, S> = Keyed<crate::row::Anon, Req, S>;
672
673impl<Req, S: SqlType> Expr<Req, S> {
674    /// States what this expression decodes to, which is what makes it
675    /// selectable: `S` was inferred from whatever built the expression, and
676    /// an inference can contradict the join the query actually has.
677    pub fn decodes_as<S2: SqlType>(self) -> Declared<Req, S2> {
678        Keyed {
679            kind: self.kind,
680            _marker: PhantomData,
681        }
682    }
683}
684
685/// A selected item filed under a `LabelKey` instead of under its own
686/// identity, and rendered with that name as its `AS`.
687pub struct Labeled<K, Inner> {
688    pub(crate) inner: Inner,
689    _key: PhantomData<fn() -> K>,
690}
691
692impl<K, Inner: Clone> Clone for Labeled<K, Inner> {
693    fn clone(&self) -> Self {
694        Labeled::new(self.inner.clone())
695    }
696}
697
698impl<K, Inner> Labeled<K, Inner> {
699    pub(crate) fn new(inner: Inner) -> Self {
700        Labeled {
701            inner,
702            _key: PhantomData,
703        }
704    }
705}
706
707/// Files a selected item under a declared name: the way to select the same
708/// expression twice, and the way out of two tables' same-named columns
709/// colliding.
710pub trait LabelExt: Sized {
711    fn label<K: LabelKey>(self, _key: K) -> Labeled<K, Self> {
712        Labeled::new(self)
713    }
714}
715impl<C: ColumnKey> LabelExt for Column<C> {}
716impl<K, Req, S: SqlType> LabelExt for Keyed<K, Req, S> {}
717// A bare `Expr` isn't selectable — it has to state its decoded type first —
718// but labelling one has to *reach* that rule to report it. Without this
719// impl, `.label(..)` on an inferred expression is a missing method and the
720// sentence about `.decodes_as::<..>()` is never printed.
721impl<Req, S: SqlType> LabelExt for Expr<Req, S> {}
722
723/// Comparison/boolean-combinator methods, blanket-implemented for anything
724/// convertible to a typed expression (columns, literals, and `Expr` itself).
725/// Kept separate from `IntoExpr` so one blanket impl can serve all three.
726// Every combinator here consumes `self`, this crate's builders being
727// by-value throughout; `is_null`/`is_in` are combinators, not predicates on
728// an existing value.
729#[allow(clippy::wrong_self_convention)]
730pub trait ExprMethods: IntoExpr + Sized {
731    fn eq<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
732    where
733        Self::Sql: Comparable<Rhs::Sql>,
734        Self::Req: Concat<Rhs::Req>,
735    {
736        bin_op(BinOp::Eq, self, rhs)
737    }
738
739    fn ne<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
740    where
741        Self::Sql: Comparable<Rhs::Sql>,
742        Self::Req: Concat<Rhs::Req>,
743    {
744        bin_op(BinOp::Ne, self, rhs)
745    }
746
747    fn lt<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
748    where
749        Self::Sql: Comparable<Rhs::Sql>,
750        Self::Req: Concat<Rhs::Req>,
751    {
752        bin_op(BinOp::Lt, self, rhs)
753    }
754
755    fn lte<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
756    where
757        Self::Sql: Comparable<Rhs::Sql>,
758        Self::Req: Concat<Rhs::Req>,
759    {
760        bin_op(BinOp::Lte, self, rhs)
761    }
762
763    fn gt<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
764    where
765        Self::Sql: Comparable<Rhs::Sql>,
766        Self::Req: Concat<Rhs::Req>,
767    {
768        bin_op(BinOp::Gt, self, rhs)
769    }
770
771    fn gte<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
772    where
773        Self::Sql: Comparable<Rhs::Sql>,
774        Self::Req: Concat<Rhs::Req>,
775    {
776        bin_op(BinOp::Gte, self, rhs)
777    }
778
779    /// `x IS NULL`. Not expressible as `.eq(..)`: comparing to NULL with `=`
780    /// yields NULL, never true, so the two are different questions.
781    fn is_null(self) -> Expr<Self::Req, Bool> {
782        Expr::from_kind(ExprKind::IsNull {
783            expr: Box::new(self.into_expr().kind),
784            negated: false,
785        })
786    }
787
788    fn is_not_null(self) -> Expr<Self::Req, Bool> {
789        Expr::from_kind(ExprKind::IsNull {
790            expr: Box::new(self.into_expr().kind),
791            negated: true,
792        })
793    }
794
795    /// `a AND b`. The boolean requirement is on the method rather than on
796    /// the receiver's type, so every spelling a condition has — a
797    /// comparison, a `sql!` fragment, a `Nullable<Bool>` column — combines
798    /// with every other, the way `.filter` accepts them all.
799    fn and<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
800    where
801        Self::Sql: BoolLike,
802        Rhs::Sql: BoolLike,
803        Self::Req: Concat<Rhs::Req>,
804    {
805        Expr::from_kind(ExprKind::And(
806            Box::new(self.into_expr().kind),
807            Box::new(rhs.into_expr().kind),
808        ))
809    }
810
811    /// `a OR b` — see `and`.
812    fn or<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
813    where
814        Self::Sql: BoolLike,
815        Rhs::Sql: BoolLike,
816        Self::Req: Concat<Rhs::Req>,
817    {
818        Expr::from_kind(ExprKind::Or(
819            Box::new(self.into_expr().kind),
820            Box::new(rhs.into_expr().kind),
821        ))
822    }
823
824    /// `x LIKE 'pattern'`. The text requirement is on the method rather
825    /// than on a trait of its own, so a non-text operand reports `TextLike`
826    /// instead of a missing method.
827    fn like<Rhs: IntoExpr>(self, rhs: Rhs) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
828    where
829        Self::Sql: TextLike,
830        Rhs::Sql: TextLike,
831        Self::Req: Concat<Rhs::Req>,
832    {
833        bin_op(BinOp::Like, self, rhs)
834    }
835
836    /// `x IN (a, b, ..)` over a runtime-length list of literals, each bound
837    /// as its own parameter. An empty list renders `FALSE`.
838    ///
839    /// **Known limitation**: the list holds values, not expressions — a
840    /// column reference on the right needs the table it belongs to folded
841    /// into `Req`, which is the same design `sql!{}` covers today.
842    fn is_in<I>(self, values: I) -> Expr<Self::Req, Bool>
843    where
844        I: IntoIterator,
845        I::Item: IntoExpr<Req = Nil>,
846        Self::Sql: Comparable<<I::Item as IntoExpr>::Sql>,
847    {
848        let values: Vec<ExprKind> = values.into_iter().map(|v| v.into_expr().kind).collect();
849        // `IN ()` is not SQL, and matching nothing is what it would mean.
850        if values.is_empty() {
851            return Expr::from_kind(ExprKind::Always(false));
852        }
853        Expr::from_kind(ExprKind::InList {
854            expr: Box::new(self.into_expr().kind),
855            values,
856        })
857    }
858
859    /// `x = ANY(<array>)` — is this value one of the elements of that array
860    /// column. The mirror of [`is_in`](Self::is_in), which asks the same
861    /// question of a list the statement writes out: here the list is one
862    /// value the database unnests, so the array can be a column.
863    ///
864    /// `!` it for "not one of them": that is `NOT (x = ANY(a))`, which SQL
865    /// also spells `x <> ALL(a)` — and not `x <> ANY(a)`, which is true as
866    /// soon as *some* element differs.
867    fn eq_any<Rhs: IntoExpr>(
868        self,
869        array: Rhs,
870    ) -> Expr<<Self::Req as Concat<Rhs::Req>>::Output, Bool>
871    where
872        Rhs::Sql: ArrayOf<Self::Sql>,
873        Self::Req: Concat<Rhs::Req>,
874    {
875        Expr::from_kind(ExprKind::EqAny {
876            expr: Box::new(self.into_expr().kind),
877            array: Box::new(array.into_expr().kind),
878        })
879    }
880}
881
882/// True when any of the conditions is. Takes a runtime-length collection,
883/// the way `is_in` takes a runtime-length list of values, so the `OR` a
884/// search box needs doesn't have to be folded by hand — folding one by one
885/// grows `Req` and stops type-checking after the first pair. An empty
886/// collection matches nothing, which is what `is_in([])` says too.
887pub fn any_of<Req, C: IntoExpr<Req = Req>>(conds: impl IntoIterator<Item = C>) -> Expr<Req, Bool>
888where
889    C::Sql: BoolLike,
890{
891    combine(conds, false)
892}
893
894/// True when all of them are. An empty collection matches everything, which
895/// is what a `WHERE` with no conditions does.
896pub fn all_of<Req, C: IntoExpr<Req = Req>>(conds: impl IntoIterator<Item = C>) -> Expr<Req, Bool>
897where
898    C::Sql: BoolLike,
899{
900    combine(conds, true)
901}
902
903fn combine<Req, C: IntoExpr<Req = Req>>(
904    conds: impl IntoIterator<Item = C>,
905    all: bool,
906) -> Expr<Req, Bool>
907where
908    C::Sql: BoolLike,
909{
910    Expr::from_kind(fold_conditions(
911        conds.into_iter().map(|c| c.into_expr().kind),
912        all,
913    ))
914}
915
916/// AND- or OR-folds conditions, answering `TRUE`/`FALSE` for an empty
917/// collection — "all of nothing" matches everything, "any of nothing"
918/// matches nothing. Shared with `select::Predicate`, which folds the same
919/// way once the scope requirement is discharged.
920pub(crate) fn fold_conditions(kinds: impl IntoIterator<Item = ExprKind>, all: bool) -> ExprKind {
921    let mut folded: Option<ExprKind> = None;
922    for kind in kinds {
923        folded = Some(match folded {
924            None => kind,
925            Some(acc) if all => ExprKind::And(Box::new(acc), Box::new(kind)),
926            Some(acc) => ExprKind::Or(Box::new(acc), Box::new(kind)),
927        });
928    }
929    folded.unwrap_or(ExprKind::Always(all))
930}
931
932impl<T: IntoExpr> ExprMethods for T {}
933
934fn bin_op<Lhs, Rhs>(
935    op: BinOp,
936    lhs: Lhs,
937    rhs: Rhs,
938) -> Expr<<Lhs::Req as Concat<Rhs::Req>>::Output, Bool>
939where
940    Lhs: IntoExpr,
941    Rhs: IntoExpr,
942    Lhs::Req: Concat<Rhs::Req>,
943{
944    Expr::from_kind(ExprKind::BinOp {
945        op,
946        lhs: Box::new(lhs.into_expr().kind),
947        rhs: Box::new(rhs.into_expr().kind),
948    })
949}
950
951/// What `LIKE` accepts: a text expression, nullable or not. Its own marker
952/// rather than `Comparable<Text>` so the failure says what the operator
953/// needs instead of talking about comparison.
954#[diagnostic::on_unimplemented(
955    message = "`LIKE` needs a text expression, and `{Self}` isn't one",
956    label = "only `Text` and `Nullable<Text>` columns and expressions accept `.like(..)`"
957)]
958pub trait TextLike: SqlType {}
959
960impl TextLike for Text {}
961impl TextLike for crate::scope::Nullable<Text> {}
962
963/// What a `WHERE`/`HAVING`/`ON` clause accepts. `Nullable<Bool>` belongs
964/// here because SQL takes it: a NULL condition selects no row, which is
965/// the same answer `IS NOT TRUE` would give.
966#[diagnostic::on_unimplemented(
967    message = "a condition has to be a boolean expression, and `{Self}` isn't one",
968    label = "expected `Bool` or `Nullable<Bool>`"
969)]
970pub trait BoolLike: SqlType {}
971
972impl BoolLike for Bool {}
973impl BoolLike for crate::scope::Nullable<Bool> {}
974
975/// `!condition`, not `condition.not()`: the standard `Not` trait reads more
976/// naturally at call sites than a same-named inherent method. Implemented
977/// for all three spellings `.filter` takes, each keeping its own type —
978/// `NOT` of a `Nullable<Bool>` is still nullable, and a `sql!` fragment
979/// stays the same fragment.
980impl<Req, S: BoolLike> std::ops::Not for Expr<Req, S> {
981    type Output = Expr<Req, S>;
982    fn not(self) -> Self::Output {
983        Expr::from_kind(ExprKind::Not(Box::new(self.kind)))
984    }
985}
986
987impl<K, Req, S: BoolLike> std::ops::Not for Keyed<K, Req, S> {
988    type Output = Keyed<K, Req, S>;
989    fn not(self) -> Self::Output {
990        Keyed::from_kind(ExprKind::Not(Box::new(self.kind)))
991    }
992}
993
994impl<C: ColumnKey> std::ops::Not for Column<C>
995where
996    C::Sql: BoolLike,
997{
998    type Output = Expr<Cons<C::Table, Nil>, C::Sql>;
999    fn not(self) -> Self::Output {
1000        Expr::from_kind(ExprKind::Not(Box::new(self.into_expr().kind)))
1001    }
1002}
1003
1004/// A base SQL type's typed NULL — see `Value::NullI32` etc. for why this
1005/// can't just be a single untyped `Value::Null`.
1006pub trait NullValue: SqlType {
1007    const NULL_VALUE: Value;
1008}
1009
1010/// A typed SQL `NULL`, for the one position an `Option` can't say it:
1011/// `SET column = NULL` assigns, and an assignment has no `Option` to be
1012/// `None`. `null::<Text>()` is `Nullable<Text>`, so only a nullable column
1013/// accepts it.
1014pub fn null<S: NullValue>() -> Expr<Nil, crate::scope::Nullable<S>> {
1015    Expr::from_kind(ExprKind::Value(S::NULL_VALUE))
1016}
1017
1018/// Declares a leaf (base) SQL type: the marker struct, its `SqlType` impl,
1019/// its `WrapNullable<MaybeNull>` impl, and `IntoExpr` from its native Rust
1020/// type. One concrete, non-generic impl per type — a blanket
1021/// `impl<T: SqlType> WrapNullable<MaybeNull> for T` would conflict with
1022/// `Nullable<T>`'s own impl (see `scope::WrapNullable`).
1023mod raw_arg {
1024    /// Sealed for the reason `select::ColumnList` is: `Req` is a free
1025    /// parameter, and a slot's value can be delegated to a real column — so
1026    /// a hand-written impl could claim `Nil` while naming a table, which is
1027    /// exactly the scope check a `sql!` slot exists to keep.
1028    pub trait Sealed {}
1029    impl<T: super::IntoExpr> Sealed for T {}
1030}
1031
1032macro_rules! sql_leaf_type {
1033    ($name:ident, $native:ty, $null_variant:ident) => {
1034        pub struct $name;
1035
1036        impl sql_type::Sealed for $name {}
1037
1038        impl SqlType for $name {
1039            type Native = $native;
1040        }
1041
1042        impl crate::scope::wrap::Sealed<MaybeNull> for $name {}
1043
1044        impl crate::scope::WrapNullable<MaybeNull> for $name {
1045            type Output = crate::scope::Nullable<$name>;
1046        }
1047
1048        impl IntoExpr for $native {
1049            type Sql = $name;
1050            type Req = Nil;
1051            fn into_expr(self) -> Expr<Nil, $name> {
1052                Expr::from_kind(ExprKind::Value(Value::from(self)))
1053            }
1054        }
1055
1056        impl crate::select::SingleColumn for $native {}
1057        impl crate::select::SingleColumn for ::std::option::Option<$native> {}
1058
1059        impl NullValue for $name {
1060            const NULL_VALUE: Value = Value::$null_variant;
1061        }
1062
1063        impl crate::insert::IntoColumnValue<$native> for $native {
1064            fn into_column_value(self) -> $native {
1065                self
1066            }
1067        }
1068
1069        impl crate::insert::IntoColumnValue<::std::option::Option<$native>> for $native {
1070            fn into_column_value(self) -> ::std::option::Option<$native> {
1071                ::std::option::Option::Some(self)
1072            }
1073        }
1074
1075        impl crate::insert::IntoColumnValue<::std::option::Option<$native>>
1076            for ::std::option::Option<$native>
1077        {
1078            fn into_column_value(self) -> ::std::option::Option<$native> {
1079                self
1080            }
1081        }
1082
1083        impl crate::insert::IntoColumnValue<crate::insert::Defaultable<$native>> for $native {
1084            fn into_column_value(self) -> crate::insert::Defaultable<$native> {
1085                crate::insert::Defaultable::Value(self)
1086            }
1087        }
1088
1089        impl crate::insert::IntoColumnValue<crate::insert::Defaultable<$native>>
1090            for ::std::option::Option<$native>
1091        {
1092            fn into_column_value(self) -> crate::insert::Defaultable<$native> {
1093                match self {
1094                    ::std::option::Option::Some(v) => crate::insert::Defaultable::Value(v),
1095                    ::std::option::Option::None => crate::insert::Defaultable::Default,
1096                }
1097            }
1098        }
1099
1100        impl
1101            crate::insert::IntoColumnValue<
1102                crate::insert::Defaultable<::std::option::Option<$native>>,
1103            > for $native
1104        {
1105            fn into_column_value(
1106                self,
1107            ) -> crate::insert::Defaultable<::std::option::Option<$native>> {
1108                crate::insert::Defaultable::Value(::std::option::Option::Some(self))
1109            }
1110        }
1111
1112        impl
1113            crate::insert::IntoColumnValue<
1114                crate::insert::Defaultable<::std::option::Option<$native>>,
1115            > for ::std::option::Option<$native>
1116        {
1117            fn into_column_value(
1118                self,
1119            ) -> crate::insert::Defaultable<::std::option::Option<$native>> {
1120                match self {
1121                    ::std::option::Option::Some(v) => {
1122                        crate::insert::Defaultable::Value(::std::option::Option::Some(v))
1123                    }
1124                    ::std::option::Option::None => crate::insert::Defaultable::Default,
1125                }
1126            }
1127        }
1128
1129        impl raw_arg::Sealed for ::std::option::Option<$native> {}
1130
1131        impl RawArg for ::std::option::Option<$native> {
1132            type Req = Nil;
1133            fn into_raw_arg(self) -> RawSlot {
1134                RawSlot(ExprKind::Value(Value::from(self)))
1135            }
1136        }
1137
1138        impl crate::row::SameShape<$native> for $native {}
1139        impl crate::row::SameShape<::std::option::Option<$native>>
1140            for ::std::option::Option<$native>
1141        {
1142        }
1143
1144        // A nullable `prepare!{}` parameter binds through here, which is what
1145        // the typed `NullX` variants exist for.
1146        impl From<::std::option::Option<$native>> for Value {
1147            fn from(v: ::std::option::Option<$native>) -> Self {
1148                match v {
1149                    ::std::option::Option::Some(x) => Value::from(x),
1150                    ::std::option::Option::None => Value::$null_variant,
1151                }
1152            }
1153        }
1154    };
1155}
1156
1157sql_leaf_type!(Integer, i32, NullI32);
1158sql_leaf_type!(BigInt, i64, NullI64);
1159sql_leaf_type!(Real, f64, NullF64);
1160sql_leaf_type!(Text, String, NullText);
1161sql_leaf_type!(Bool, bool, NullBool);
1162sql_leaf_type!(Bytes, Vec<u8>, NullBytes);
1163
1164// Postgres arrays, over the four element types a schema reaches for.
1165//
1166// **Known limitations**: `BOOLEAN[]`, `DOUBLE PRECISION[]`, `TIMESTAMPTZ[]`
1167// and `NUMERIC[]` have no marker, and neither does an array whose elements
1168// can be NULL — a `Vec<T>` column decodes every element, so a row holding
1169// one fails to decode rather than arriving as `None`. Both wait for a
1170// schema that needs them. Arrays are Postgres's alone; an `Expr` carries no
1171// dialect, so rendering one for MySQL or SQLite is a bind their driver
1172// refuses rather than a compile error.
1173sql_leaf_type!(TextArray, Vec<String>, NullTextArray);
1174sql_leaf_type!(IntegerArray, Vec<i32>, NullIntegerArray);
1175sql_leaf_type!(BigIntArray, Vec<i64>, NullBigIntArray);
1176#[cfg(feature = "uuid")]
1177sql_leaf_type!(UuidArray, Vec<uuid::Uuid>, NullUuidArray);
1178
1179// A JSON document, Postgres's `jsonb`. Opaque: it goes in and comes back,
1180// and `->`, `->>`, `@>` and the rest of the operators that look inside one
1181// are deferred to `sql!{}` rather than half-built.
1182//
1183// **Known limitations**: a `json` column binds and decodes through this
1184// marker too, since the two are one wire format and one Rust type, but
1185// `json` has neither an equality nor an ordering operator — `.eq(..)`,
1186// `.asc()` and `GROUP BY` on one compile here and are rejected by the
1187// server. Which of the two a column is is a fact about the schema that
1188// nothing in a query can read, so it is `jsonb` that this marker claims.
1189#[cfg(feature = "json")]
1190sql_leaf_type!(Json, serde_json::Value, NullJson);
1191
1192// Types a database has and Rust doesn't: each decodes to the crate its
1193// feature names, so a schema that has no `timestamptz` column pays for none
1194// of it.
1195#[cfg(feature = "chrono")]
1196sql_leaf_type!(Timestamptz, chrono::DateTime<chrono::Utc>, NullTimestamptz);
1197#[cfg(feature = "chrono")]
1198sql_leaf_type!(Date, chrono::NaiveDate, NullDate);
1199#[cfg(feature = "uuid")]
1200sql_leaf_type!(Uuid, uuid::Uuid, NullUuid);
1201#[cfg(feature = "decimal")]
1202sql_leaf_type!(Numeric, rust_decimal::Decimal, NullNumeric);
1203
1204// Ergonomic extra: allow `&str` literals directly, without forcing
1205// `.to_string()` at every call site.
1206impl IntoExpr for &String {
1207    type Sql = Text;
1208    type Req = Nil;
1209    fn into_expr(self) -> Expr<Nil, Text> {
1210        Expr::from_kind(ExprKind::Value(Value::Text(self.clone())))
1211    }
1212}
1213
1214impl IntoExpr for &str {
1215    type Sql = Text;
1216    type Req = Nil;
1217    fn into_expr(self) -> Expr<Nil, Text> {
1218        Expr::from_kind(ExprKind::Value(Value::Text(self.to_string())))
1219    }
1220}
1221
1222/// Text's borrowed forms, at every slot a `String` column has. The leaf
1223/// macro can't generate these: only `Text` has a borrowed spelling.
1224macro_rules! text_column_value {
1225    ($borrowed:ty) => {
1226        impl crate::insert::IntoColumnValue<String> for $borrowed {
1227            fn into_column_value(self) -> String {
1228                self.to_string()
1229            }
1230        }
1231
1232        impl crate::insert::IntoColumnValue<Option<String>> for $borrowed {
1233            fn into_column_value(self) -> Option<String> {
1234                Some(self.to_string())
1235            }
1236        }
1237
1238        impl crate::insert::IntoColumnValue<crate::insert::Defaultable<String>> for $borrowed {
1239            fn into_column_value(self) -> crate::insert::Defaultable<String> {
1240                crate::insert::Defaultable::Value(self.to_string())
1241            }
1242        }
1243
1244        impl crate::insert::IntoColumnValue<crate::insert::Defaultable<Option<String>>>
1245            for $borrowed
1246        {
1247            fn into_column_value(self) -> crate::insert::Defaultable<Option<String>> {
1248                crate::insert::Defaultable::Value(Some(self.to_string()))
1249            }
1250        }
1251    };
1252}
1253
1254text_column_value!(&str);
1255text_column_value!(&String);
1256
1257impl<S: SqlType> sql_type::Sealed for crate::scope::Nullable<S> {}
1258
1259impl<S: SqlType> SqlType for crate::scope::Nullable<S> {
1260    type Native = Option<S::Native>;
1261}
1262
1263crate::row::expr_key!(
1264    Count,
1265    HasCount,
1266    count,
1267    "The identity a selected `count(*)` is filed under in a row.",
1268    'c',
1269    'o',
1270    'u',
1271    'n',
1272    't'
1273);
1274
1275/// `count(*)` as a rendered selection item, for `Select::count_sql`.
1276pub(crate) fn count_item() -> crate::render::SelectItem {
1277    crate::render::SelectItem::bare(count_star())
1278}
1279
1280fn count_star() -> ExprKind {
1281    ExprKind::Func {
1282        name: "count",
1283        arg: None,
1284    }
1285}
1286
1287/// Counts rows. `count_of(column)` counts that column's non-NULL values,
1288/// which is the different question a `LEFT JOIN` makes visible.
1289pub fn count() -> Keyed<Count, Nil, BigInt> {
1290    Keyed::from_kind(count_star())
1291}
1292
1293/// What `min`/`max` accept: a type the databases order. Its own marker for
1294/// the reason `Summable` is one — `WrapNullable<MaybeNull>`, which stood
1295/// here before, is implemented for every leaf type, so it gated nothing and
1296/// `max(bool_column)` rendered SQL Postgres has no aggregate for.
1297///
1298/// The set is Postgres's, the narrowest of the three: no `boolean`, no
1299/// `bytea`, and no `uuid` before PG 18.
1300#[diagnostic::on_unimplemented(
1301    message = "`min`/`max` need an ordered expression, and `{Self}` isn't one",
1302    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"
1303)]
1304pub trait Ordered: SqlType + WrapNullable<MaybeNull> {}
1305
1306impl Ordered for Integer {}
1307impl Ordered for BigInt {}
1308impl Ordered for Real {}
1309impl Ordered for Text {}
1310#[cfg(feature = "decimal")]
1311impl Ordered for Numeric {}
1312#[cfg(feature = "chrono")]
1313impl Ordered for Timestamptz {}
1314#[cfg(feature = "chrono")]
1315impl Ordered for Date {}
1316
1317/// A nullable column orders like its base type — the NULLs sort, they don't
1318/// stop the aggregate from existing.
1319impl<S: Ordered> Ordered for crate::scope::Nullable<S> {}
1320
1321/// What `sum(..)` of a column decodes to. `sum` is NULL over zero rows, so
1322/// every result is nullable however the column was declared.
1323/// `CAST` keeps the widened type a database picks for a sum inside the
1324/// closed set of types this crate has: Postgres returns `numeric` for
1325/// `sum(bigint)` and `avg(int)`, neither of which has a native here.
1326#[diagnostic::on_unimplemented(
1327    message = "`sum`/`avg` need a numeric expression, and `{Self}` isn't one",
1328    label = "only `Integer`, `BigInt` and `Real` columns and expressions (and `Numeric`, with the `decimal` feature) can be summed or averaged"
1329)]
1330pub trait Summable: SqlType {
1331    type Sum: SqlType;
1332    const SUM_CAST: Option<CastTarget>;
1333    const AVG_CAST: Option<CastTarget> = Some(CastTarget::Double);
1334}
1335impl Summable for Integer {
1336    type Sum = crate::scope::Nullable<BigInt>;
1337    const SUM_CAST: Option<CastTarget> = None;
1338}
1339impl Summable for BigInt {
1340    type Sum = crate::scope::Nullable<BigInt>;
1341    const SUM_CAST: Option<CastTarget> = Some(CastTarget::BigInt);
1342}
1343impl Summable for Real {
1344    type Sum = crate::scope::Nullable<Real>;
1345    const SUM_CAST: Option<CastTarget> = None;
1346    const AVG_CAST: Option<CastTarget> = None;
1347}
1348// `sum(numeric)` stays numeric, so it needs no cast; `avg` decodes as `f64`
1349// for every column type, so a numeric one is cast like the rest.
1350#[cfg(feature = "decimal")]
1351impl Summable for Numeric {
1352    type Sum = crate::scope::Nullable<Numeric>;
1353    const SUM_CAST: Option<CastTarget> = None;
1354    const AVG_CAST: Option<CastTarget> = Some(CastTarget::Double);
1355}
1356impl<T: Summable> Summable for crate::scope::Nullable<T> {
1357    type Sum = T::Sum;
1358    const SUM_CAST: Option<CastTarget> = T::SUM_CAST;
1359    const AVG_CAST: Option<CastTarget> = T::AVG_CAST;
1360}
1361
1362/// The row key an aggregate over `C` is filed under: distinct per function
1363/// *and* per column, so `sum(a)` and `sum(b)` don't collide, and named after
1364/// the column so a DTO field or a CTE column can match it.
1365pub struct Agg<Op, C>(PhantomData<fn() -> (Op, C)>);
1366
1367// An aggregate is filed under the column it aggregates: `sum(orders::total)`
1368// reads back as `total`, and matches a CTE or DTO field of that name.
1369//
1370// **Known limitation**: by *name*, not by key — `Agg<Sum, total>` is its own
1371// key type, so `row.get(sum(orders::total))` and `#[derive(FromRow)]` find
1372// it and the generated `row.total()` accessor does not.
1373#[doc(hidden)]
1374impl<Op, C: crate::row::Named> crate::row::NamedSealed for Agg<Op, C> {}
1375
1376#[doc(hidden)]
1377impl<Op: 'static, C: crate::row::Named + 'static> crate::row::Named for Agg<Op, C> {
1378    type Name = <C as crate::row::Named>::Name;
1379    const NAME: &'static str = <C as crate::row::Named>::NAME;
1380}
1381
1382#[doc(hidden)]
1383impl<Op: 'static, C: crate::row::Spelled + 'static> crate::row::Spelled for Agg<Op, C> {}
1384
1385fn aggregate_kind<C: ColumnKey>(name: &'static str, cast: Option<CastTarget>) -> ExprKind {
1386    let call = ExprKind::Func {
1387        name,
1388        arg: Some(Box::new(ExprKind::Column {
1389            table: <C::Table as Table>::NAME,
1390            name: <C as crate::row::Named>::NAME,
1391        })),
1392    };
1393    match cast {
1394        Some(target) => ExprKind::Cast {
1395            expr: Box::new(call),
1396            target,
1397        },
1398        None => call,
1399    }
1400}
1401
1402macro_rules! aggregate {
1403    ($op:ident, $func:ident, $sql:literal, $out:ty, $bound:path, $cast:expr, $doc:literal) => {
1404        #[doc = $doc]
1405        pub struct $op;
1406
1407        #[doc = $doc]
1408        pub fn $func<C: ColumnKey>(
1409            _column: Column<C>,
1410        ) -> Keyed<Agg<$op, C>, Cons<C::Table, Nil>, $out>
1411        where
1412            C::Sql: $bound,
1413            $out: SqlType,
1414        {
1415            Keyed::from_kind(aggregate_kind::<C>($sql, $cast))
1416        }
1417    };
1418}
1419
1420aggregate!(
1421    Sum,
1422    sum,
1423    "sum",
1424    <C::Sql as Summable>::Sum,
1425    Summable,
1426    <C::Sql as Summable>::SUM_CAST,
1427    "`sum(column)`. NULL over zero rows, so the result is always nullable."
1428);
1429aggregate!(
1430    Min,
1431    min,
1432    "min",
1433    <C::Sql as WrapNullable<MaybeNull>>::Output,
1434    Ordered,
1435    None,
1436    "`min(column)`. NULL over zero rows."
1437);
1438aggregate!(
1439    Max,
1440    max,
1441    "max",
1442    <C::Sql as WrapNullable<MaybeNull>>::Output,
1443    Ordered,
1444    None,
1445    "`max(column)`. NULL over zero rows."
1446);
1447aggregate!(
1448    Avg,
1449    avg,
1450    "avg",
1451    crate::scope::Nullable<Real>,
1452    Summable,
1453    <C::Sql as Summable>::AVG_CAST,
1454    "`avg(column)`. NULL over zero rows."
1455);
1456aggregate!(
1457    CountOf,
1458    count_of,
1459    "count",
1460    BigInt,
1461    SqlType,
1462    None,
1463    "`count(column)` — non-NULL values, unlike `count()`'s `count(*)` rows."
1464);
1465
1466/// What `string_agg` accepts. Postgres defines it for `text` and for
1467/// `bytea` — and the `bytea` one concatenates bytes and returns `bytea`,
1468/// which is a different question than the one this asks — so text is the
1469/// set, as it is the set the other two dialects coerce their arguments
1470/// into anyway.
1471#[diagnostic::on_unimplemented(
1472    message = "`string_agg` concatenates text, and `{Self}` isn't text",
1473    label = "reach for a cast, or a raw fragment, in front of a column that isn't"
1474)]
1475pub trait Concatenable: SqlType {}
1476
1477impl Concatenable for Text {}
1478
1479/// A nullable column concatenates like its base type: `string_agg` skips
1480/// the NULLs rather than being undefined over them.
1481impl<S: Concatenable> Concatenable for crate::scope::Nullable<S> {}
1482
1483/// `string_agg(column, ", ")` — a group's values run together, separated.
1484/// NULL over zero rows, and over a group whose every value is NULL.
1485///
1486/// The separator binds like any other value under Postgres and SQLite,
1487/// which take it as an ordinary argument. MySQL's grammar takes a literal
1488/// after `SEPARATOR` and rejects a parameter, so there alone it is written
1489/// into the SQL and escaped — which is why it is a `&'static str` at all,
1490/// and why a MySQL session running `NO_BACKSLASH_ESCAPES` renders a
1491/// separator containing a backslash as more backslashes than were asked
1492/// for. `&'static str` is a nudge and not a guarantee, since `Box::leak`
1493/// reaches it; the guarantee is that the two dialects this crate executes
1494/// never write it out at all.
1495///
1496/// Two `string_agg`s over one column key alike, since the separator is not
1497/// part of the key — give one a `label!{}` name to read both back.
1498///
1499/// **Known limitation**: no `ORDER BY` inside the call
1500/// (`string_agg(x, ',' ORDER BY x)`) and no `DISTINCT`. Ordering inside an
1501/// aggregate reached SQLite only in 3.44, past the 3.39 this crate targets,
1502/// and MySQL spells it before the separator rather than after the
1503/// argument — three spellings of a clause two of the dialects would have
1504/// to be told to skip. Reach for `sql!{}` where the order matters.
1505pub struct StringAgg;
1506
1507/// `string_agg(column, ", ")`. See [`StringAgg`].
1508pub fn string_agg<C: ColumnKey>(
1509    _column: Column<C>,
1510    separator: &'static str,
1511) -> Keyed<Agg<StringAgg, C>, Cons<C::Table, Nil>, crate::scope::Nullable<Text>>
1512where
1513    C::Sql: Concatenable,
1514{
1515    Keyed::from_kind(ExprKind::StringAgg {
1516        arg: Box::new(ExprKind::Column {
1517            table: <C::Table as Table>::NAME,
1518            name: <C as crate::row::Named>::NAME,
1519        }),
1520        separator,
1521    })
1522}
1523
1524/// One `?` slot of a `sql!{}` fragment: every expression, plus the `Option`
1525/// a request field already holds — a slot is the one place a NULL arrives
1526/// as data rather than as a written `null::<..>()`. A slot that isn't one
1527/// reports `IntoExpr`, since that is the bound this one is built on.
1528pub trait RawArg: raw_arg::Sealed {
1529    type Req;
1530    #[doc(hidden)]
1531    fn into_raw_arg(self) -> RawSlot;
1532}
1533
1534impl<T: IntoExpr> RawArg for T {
1535    type Req = T::Req;
1536    fn into_raw_arg(self) -> RawSlot {
1537        RawSlot(self.into_expr().kind)
1538    }
1539}
1540
1541/// What a slot holds, opaque outside this crate: the `RawArg` impls are the
1542/// only way to make one, so a slot always holds something the renderer can
1543/// write.
1544pub struct RawSlot(ExprKind);
1545
1546impl RawSlot {
1547    fn into_kind(self) -> ExprKind {
1548        self.0
1549    }
1550}
1551
1552/// The whole slot list of one `sql!{}`, whose `Req` is every table its
1553/// slots name.
1554#[diagnostic::on_unimplemented(
1555    message = "a `sql!` fragment takes at most 8 `?` slots",
1556    label = "split the fragment, or fold part of it into the builder"
1557)]
1558pub trait RawArgs {
1559    type Req;
1560    #[doc(hidden)]
1561    fn into_raw_args(self) -> Vec<RawSlot>;
1562}
1563
1564impl RawArgs for () {
1565    type Req = Nil;
1566    fn into_raw_args(self) -> Vec<RawSlot> {
1567        Vec::new()
1568    }
1569}
1570
1571macro_rules! raw_args_tuple {
1572    ($head:ident $(, $rest:ident)*) => {
1573        #[allow(non_snake_case)]
1574        impl<$head: RawArg $(, $rest: RawArg)*> RawArgs for ($head, $($rest,)*)
1575        where
1576            ($($rest,)*): RawArgs,
1577            $head::Req: Concat<<($($rest,)*) as RawArgs>::Req>,
1578        {
1579            type Req = <$head::Req as Concat<<($($rest,)*) as RawArgs>::Req>>::Output;
1580            fn into_raw_args(self) -> Vec<RawSlot> {
1581                let ($head, $($rest,)*) = self;
1582                let mut kinds = ::std::vec![RawArg::into_raw_arg($head)];
1583                kinds.extend(RawArgs::into_raw_args(($($rest,)*)));
1584                kinds
1585            }
1586        }
1587    };
1588}
1589raw_args_tuple!(A);
1590raw_args_tuple!(A, B);
1591raw_args_tuple!(A, B, C);
1592raw_args_tuple!(A, B, C, D);
1593raw_args_tuple!(A, B, C, D, E);
1594raw_args_tuple!(A, B, C, D, E, F);
1595raw_args_tuple!(A, B, C, D, E, F, G);
1596raw_args_tuple!(A, B, C, D, E, F, G, H);
1597
1598/// Counts the `?` slots in a `sql!` text, so the macro can compare that
1599/// count with the number of arguments it was handed while both are still
1600/// constants.
1601#[doc(hidden)]
1602pub const fn placeholder_count(sql: &str) -> usize {
1603    let bytes = sql.as_bytes();
1604    let mut i = 0;
1605    let mut count = 0;
1606    while i < bytes.len() {
1607        if bytes[i] == b'?' {
1608            count += 1;
1609        }
1610        i += 1;
1611    }
1612    count
1613}
1614
1615/// The one door into `ExprKind` from outside the crate, and the only shape
1616/// that needs one: `sql!{}` expands in the caller's. `Req` is the union of
1617/// the slots' own, so a fragment carries exactly the tables its `?`s name.
1618/// Reached through `sql!`, which is what checks that every `?` has a value.
1619#[doc(hidden)]
1620pub fn raw_expr<S: SqlType, Args: RawArgs>(
1621    sql: &'static str,
1622    args: Args,
1623) -> Declared<Args::Req, S> {
1624    Keyed::from_kind(template(sql, args.into_raw_args()))
1625}
1626
1627/// Splits authored text on its `?` slots and pairs each with its argument.
1628/// `sql!` checks the two counts against each other while both are still
1629/// constants, which is why leftovers here can't happen through it.
1630fn template(sql: &'static str, args: Vec<RawSlot>) -> ExprKind {
1631    let mut pieces: Vec<String> = vec![String::new()];
1632    for c in sql.chars() {
1633        match c {
1634            '?' => pieces.push(String::new()),
1635            c => pieces.last_mut().expect("one piece to start").push(c),
1636        }
1637    }
1638
1639    let mut pieces = pieces.into_iter();
1640    let head = pieces.next().unwrap_or_default();
1641    let rest = args
1642        .into_iter()
1643        .map(RawSlot::into_kind)
1644        .zip(pieces)
1645        .collect();
1646    ExprKind::Template { head, rest }
1647}
1648
1649/// A named, typed placeholder: usable anywhere a value of type `S` is
1650/// expected (`.eq(placeholder::<Integer>("id"))`), rendered as a normal
1651/// bound parameter but resolved to a concrete value at
1652/// `Prepared::load()` time. `prepare!{}` is the intended entry point
1653/// rather than this function, since it also generates the typed `Params`
1654/// struct that makes a missing or misspelled placeholder a compile error.
1655#[doc(hidden)]
1656pub fn placeholder<S: SqlType>(name: &'static str) -> Expr<Nil, S> {
1657    Expr::from_kind(ExprKind::Value(Value::Placeholder(name)))
1658}