Skip to main content

rust_query/
lib.rs

1#![allow(private_bounds, private_interfaces)]
2#![doc = include_str!("../README.md")]
3#![cfg_attr(not(docsrs), cfg(feature = "base0"))]
4#![cfg_attr(docsrs, feature(doc_cfg))]
5
6extern crate self as rust_query;
7
8#[macro_use]
9extern crate static_assertions;
10
11#[cfg(doc)]
12#[doc = include_str!("_guide.md")]
13pub mod _guide {}
14// mod ast;
15mod async_db;
16mod db;
17mod error;
18mod joinable;
19mod lazy;
20mod lower;
21mod migrate;
22mod mutable;
23#[cfg(feature = "__mutants")]
24mod mutants;
25mod pool;
26mod query;
27mod rows;
28mod schema;
29mod select;
30mod transaction;
31mod value;
32mod writable;
33
34use private::Reader;
35use schema::from_macro::TypBuilder;
36use std::ops::Deref;
37
38pub use async_db::DatabaseAsync;
39pub use db::TableRow;
40pub use error::Conflict;
41pub use lazy::Lazy;
42pub use mutable::Mutable;
43pub use select::{IntoSelect, Select};
44pub use transaction::{Database, Transaction, TransactionWeak};
45pub use value::aggregate::aggregate;
46pub use value::from_expr::FromExpr;
47pub use value::{Expr, into_expr::IntoExpr, optional::optional};
48
49/// Derive [derive@Select] to create a new `*Select` struct.
50///
51/// This `*Select` struct will implement the [IntoSelect] trait and can be used
52/// with [args::Query::into_iter], [Transaction::query_one] etc.
53///
54/// Usage can also be nested.
55///
56/// ```
57/// #[rust_query::migration::schema(Schema)]
58/// pub mod vN {
59///     pub struct Thing {
60///         pub details: rust_query::TableRow<Details>,
61///         pub beta: f64,
62///         pub seconds: i64,
63///     }
64///     pub struct Details {
65///         pub name: String,
66///     }
67/// }
68/// use v0::*;
69/// use rust_query::{Table, Select, Transaction};
70///
71/// #[derive(Select)]
72/// struct MyData {
73///     seconds: i64,
74///     is_it_real: bool,
75///     name: String,
76///     other: OtherData
77/// }
78///
79/// #[derive(Select)]
80/// struct OtherData {
81///     alpha: f64,
82///     beta: f64,
83/// }
84///
85/// fn do_query(db: &Transaction<Schema>) -> Vec<MyData> {
86///     db.query(|rows| {
87///         let thing = rows.join(Thing);
88///
89///         rows.into_vec(MyDataSelect {
90///             seconds: &thing.seconds,
91///             is_it_real: thing.seconds.lt(100),
92///             name: &thing.details.name,
93///             other: OtherDataSelect {
94///                 alpha: thing.beta.add(2.0),
95///                 beta: &thing.beta,
96///             },
97///         })
98///     })
99/// }
100/// # fn main() {}
101/// ```
102pub use rust_query_macros::Select;
103
104/// Use in combination with `#[rust_query(From = Thing)]` to specify which tables
105/// this struct should implement [trait@FromExpr] for.
106///
107/// The implementation of [trait@FromExpr] will initialize every field from the column with
108/// the corresponding name. It is also possible to change the type of each field
109/// as long as the new field type implements [trait@FromExpr].
110///
111/// ```
112/// # use rust_query::migration::schema;
113/// # use rust_query::{TableRow, FromExpr};
114/// #[schema(Example)]
115/// pub mod vN {
116///     pub struct User {
117///         pub name: String,
118///         pub score: i64,
119///         pub best_game: Option<rust_query::TableRow<Game>>,
120///     }
121///     pub struct Game;
122/// }
123///
124/// #[derive(FromExpr)]
125/// #[rust_query(From = v0::User)]
126/// struct MyUserFields {
127///     name: String,
128///     best_game: Option<TableRow<v0::Game>>,
129/// }
130/// # fn main() {}
131/// ```
132pub use rust_query_macros::FromExpr;
133
134use crate::error::FromConflict;
135
136/// Types that are used as closure arguments.
137///
138/// You generally don't need to import these types.
139pub mod args {
140    pub use crate::query::{OrderBy, Query};
141    pub use crate::rows::Rows;
142    pub use crate::value::aggregate::Aggregate;
143    pub use crate::value::optional::Optional;
144}
145
146/// Types to declare schemas and migrations.
147///
148/// A good starting point is too look at [crate::migration::schema].
149pub mod migration {
150    pub use crate::migrate::{
151        Migrator,
152        config::{Config, ForeignKeys, Synchronous},
153        migration::{Migrated, TransactionMigrate},
154    };
155    #[cfg(feature = "dev")]
156    pub use crate::schema::dev::hash_schema;
157
158    #[doc = include_str!("schema/_schema.md")]
159    pub use rust_query_macros::schema;
160}
161
162/// These items are only exposed for use by the proc macros.
163/// Direct use is unsupported.
164#[doc(hidden)]
165pub mod private {
166
167    pub use crate::joinable::{IntoJoinable, Joinable};
168    pub use crate::migrate::{
169        Schema, SchemaMigration, TableTypBuilder,
170        migration::{Migration, SchemaBuilder},
171        with_test_renderer,
172    };
173    pub use crate::query::get_plan;
174    pub use crate::schema::from_macro::{SchemaType, TypBuilder};
175    pub use crate::schema::tokenizer::{Token, get_token};
176    pub use crate::value::{DbTyp, adhoc_expr, new_column, unique_from_joinable};
177    pub use crate::writable::Reader;
178
179    // pub trait Apply {
180    //     type Out<T: MigrateTyp>;
181    // }
182
183    // pub struct AsNormal;
184    // impl Apply for AsNormal {
185    //     type Out<T: MigrateTyp> = T;
186    // }
187
188    // struct AsExpr<'x, S>(PhantomData<(&'x (), S)>);
189    // impl<'x, S> Apply for AsExpr<'x, S> {
190    //     type Out<T: MigrateTyp> = crate::Expr<'x, S, T::ExprTyp>;
191    // }
192
193    // struct AsLazy<'x>(PhantomData<&'x ()>);
194    // impl<'x> Apply for AsLazy<'x> {
195    //     type Out<T: MigrateTyp> = T::Lazy<'x>;
196    // }
197
198    pub mod doctest_aggregate {
199        #[crate::migration::schema(M)]
200        pub mod vN {
201            pub struct Val {
202                pub x: i64,
203            }
204        }
205        pub use crate::aggregate;
206        pub use v0::*;
207
208        #[cfg_attr(false, mutants::skip)]
209        pub fn get_txn(f: impl Send + FnOnce(&'static mut crate::Transaction<M>)) {
210            crate::Database::new(rust_query::migration::Config::open_in_memory())
211                .transaction_mut_ok(f)
212        }
213    }
214
215    pub mod doctest {
216        use crate::{Database, Transaction, migrate::config::Config, migration};
217
218        #[migration::schema(Empty)]
219        pub mod vN {
220            pub struct User {
221                #[unique]
222                pub name: String,
223            }
224        }
225        pub use v0::*;
226
227        #[cfg_attr(false, mutants::skip)]
228        pub fn get_txn(f: impl Send + FnOnce(&'static mut Transaction<Empty>)) {
229            let db = Database::new(Config::open_in_memory());
230            db.transaction_mut_ok(|txn| {
231                txn.insert(User {
232                    name: "Alice".to_owned(),
233                })
234                .unwrap();
235                f(txn)
236            })
237        }
238    }
239}
240
241/// This trait is implemented for all table types as generated by the [crate::migration::schema] macro.
242///
243/// **You can not implement this trait yourself!**
244pub trait Table: Sized + 'static {
245    #[doc(hidden)]
246    type Ext2<'t>;
247
248    #[doc(hidden)]
249    fn covariant_ext<'x, 't>(val: &'x Self::Ext2<'static>) -> &'x Self::Ext2<'t>;
250
251    #[doc(hidden)]
252    fn build_ext2<'t>(val: &Expr<'t, Self::Schema, TableRow<Self>>) -> Self::Ext2<'t>;
253
254    /// The schema that this table is a part of.
255    type Schema;
256
257    #[doc(hidden)]
258    /// The table that this table can be migrated from.
259    type MigrateFrom: Table;
260
261    /// The type of conflict that can result from inserting a row in this table.
262    /// This is the same type that is used for row updates too.
263    type Conflict: FromConflict;
264    /// The type of error when a delete fails due to a foreign key constraint.
265    type Referer;
266
267    #[doc(hidden)]
268    type Mutable: Deref;
269    #[doc(hidden)]
270    type Lazy<'t>;
271
272    #[doc(hidden)]
273    fn read(&self, f: &mut Reader);
274
275    #[doc(hidden)]
276    type Select;
277
278    #[doc(hidden)]
279    fn into_select(
280        val: Expr<'_, Self::Schema, TableRow<Self>>,
281    ) -> Select<'_, Self::Schema, Self::Select>;
282
283    #[doc(hidden)]
284    fn select_mutable(select: Self::Select) -> Self::Mutable;
285
286    #[doc(hidden)]
287    fn select_lazy<'t>(select: Self::Select) -> Self::Lazy<'t>;
288
289    #[doc(hidden)]
290    fn mutable_as_unique(val: &mut Self::Mutable) -> &mut <Self::Mutable as Deref>::Target;
291
292    #[doc(hidden)]
293    fn mutable_into_insert(val: Self::Mutable) -> Self
294    where
295        Self: Sized;
296
297    #[doc(hidden)]
298    fn get_referer_unchecked() -> Self::Referer;
299
300    #[doc(hidden)]
301    fn typs(f: &mut TypBuilder<Self::Schema>);
302
303    #[doc(hidden)]
304    const SPAN: (usize, usize);
305
306    #[doc(hidden)]
307    const ID: &'static str;
308    #[doc(hidden)]
309    const NAME: &'static str;
310}
311
312trait CustomJoin: Table {
313    fn name(&self) -> lower::JoinableTable;
314    fn main_column(&self) -> &'static str;
315}
316
317#[test]
318#[cfg(feature = "jiff-02")]
319fn compile_tests() {
320    let t = trybuild::TestCases::new();
321    t.compile_fail("tests/compile/*.rs");
322}