nautilus_core/args.rs
1//! Structured argument types for query operations.
2
3use std::collections::HashMap;
4
5use crate::{Expr, OrderBy, Value};
6
7/// Arguments for eagerly loading a single relation in a query.
8///
9/// ```text
10/// include: { posts: { where: { published: true } } }
11/// ```
12#[derive(Debug, Default, Clone)]
13pub struct IncludeRelation {
14 /// Optional filter to apply to the included child records.
15 pub where_: Option<Expr>,
16}
17
18impl IncludeRelation {
19 /// Create a plain include with no child filter.
20 pub fn plain() -> Self {
21 IncludeRelation { where_: None }
22 }
23
24 /// Create an include with a child filter.
25 pub fn with_filter(filter: Expr) -> Self {
26 IncludeRelation {
27 where_: Some(filter),
28 }
29 }
30}
31
32/// Arguments accepted by `find_unique` and `find_unique_or_throw` delegate methods.
33///
34/// Uses a required `where_` filter (no ordering/pagination — implicit LIMIT 1).
35///
36/// # Example
37/// ```rust,ignore
38/// let args = FindUniqueArgs::new(
39/// User::columns().email.eq("alice@example.com"),
40/// );
41/// let user = client.user.find_unique(args).await?;
42/// ```
43#[derive(Debug, Clone)]
44pub struct FindUniqueArgs {
45 /// WHERE filter expression (required — must reference a unique/PK field).
46 pub where_: Expr,
47 /// Projection: only return the specified fields.
48 ///
49 /// If empty, all columns are returned. When specified, PK columns are
50 /// always included regardless. Cannot be used together with `include`.
51 pub select: HashMap<String, bool>,
52}
53
54impl FindUniqueArgs {
55 /// Construct with a required filter expression.
56 pub fn new(filter: Expr) -> Self {
57 FindUniqueArgs {
58 where_: filter,
59 select: HashMap::new(),
60 }
61 }
62}
63
64/// Arguments accepted by `find_many` and `find_first` delegate methods.
65///
66/// All fields are optional and default to "no constraint".
67///
68/// # Example
69/// ```rust,ignore
70/// let args = FindManyArgs {
71/// where_: Some(User::columns().email.eq("alice@example.com")),
72/// take: Some(10),
73/// ..Default::default()
74/// };
75/// let users = client.user.find_many(args).await?;
76/// ```
77#[derive(Debug, Default, Clone)]
78pub struct FindManyArgs {
79 /// Optional WHERE filter expression.
80 pub where_: Option<Expr>,
81 /// ORDER BY clauses (applied in order).
82 pub order_by: Vec<OrderBy>,
83 /// Maximum number of rows to return (LIMIT).
84 ///
85 /// Positive values paginate **forward**; negative values paginate
86 /// **backward** (reverses the result set in application code after
87 /// flipping `ORDER BY` directions — no DB-specific SQL needed).
88 /// Only meaningful when `cursor` is also set.
89 pub take: Option<i32>,
90 /// Number of rows to skip (OFFSET), applied relative to the cursor position
91 /// when `cursor` is set, or from the start of the result set otherwise.
92 pub skip: Option<u32>,
93 /// Relations to eager-load, with optional per-relation filters.
94 ///
95 /// Key is the relation field name (e.g. `"posts"`), value controls
96 /// how that relation is included (filter, etc.).
97 ///
98 /// Cannot be used together with `select`.
99 pub include: HashMap<String, IncludeRelation>,
100 /// Projection: only return the specified scalar fields.
101 ///
102 /// Key is the field name (logical name), value must be `true` to include
103 /// the field. PK fields are always returned regardless. When empty, all
104 /// columns are returned.
105 ///
106 /// Cannot be used together with `include`.
107 pub select: HashMap<String, bool>,
108 /// Cursor for stable (keyset) pagination.
109 ///
110 /// A map of **primary-key field name → value** that identifies the record
111 /// from which the page should start. When
112 /// combined with `take` / `skip`, they are applied relative to this anchor
113 /// record rather than from the absolute start of the table.
114 ///
115 /// All primary-key fields of the model must be present in the map.
116 pub cursor: Option<HashMap<String, Value>>,
117 /// Columns to deduplicate on (SELECT DISTINCT / DISTINCT ON).
118 ///
119 /// Specifying one or more field names activates column-level deduplication:
120 /// - **Postgres**: rendered as `SELECT DISTINCT ON (col, ...)` with those
121 /// columns automatically prepended to `ORDER BY` as required by Postgres.
122 /// - **SQLite / MySQL**: rendered as plain `SELECT DISTINCT` (full-row
123 /// deduplication — most effective when combined with `select` projection).
124 ///
125 /// When empty (the default), no deduplication is applied.
126 pub distinct: Vec<String>,
127}