rust_query/
lib.rs

1#![allow(private_bounds, private_interfaces)]
2#![doc = include_str!("../README.md")]
3
4extern crate self as rust_query;
5
6#[macro_use]
7extern crate static_assertions;
8
9mod alias;
10mod ast;
11mod async_db;
12mod db;
13mod joinable;
14mod lazy;
15mod migrate;
16mod mymap;
17mod pool;
18mod query;
19mod rows;
20mod schema;
21mod select;
22mod transaction;
23mod value;
24mod writable;
25
26pub use async_db::DatabaseAsync;
27pub use db::TableRow;
28pub use lazy::Lazy;
29use private::Reader;
30pub use rust_query_macros::{FromExpr, Select};
31use schema::from_macro::TypBuilder;
32pub use select::{IntoSelect, Select};
33pub use transaction::{Database, Transaction, TransactionWeak};
34use value::MyTyp;
35pub use value::aggregate::aggregate;
36pub use value::trivial::FromExpr;
37pub use value::{Expr, IntoExpr, UnixEpoch, optional::optional};
38pub use writable::Update;
39
40use crate::alias::JoinableTable;
41
42/// Types that are used as closure arguments.
43///
44/// You generally don't need to import these types.
45pub mod args {
46    pub use crate::query::Query;
47    pub use crate::rows::Rows;
48    pub use crate::value::aggregate::Aggregate;
49    pub use crate::value::optional::Optional;
50}
51
52/// Types to declare schemas and migrations.
53///
54/// A good starting point is too look at [crate::migration::schema].
55pub mod migration {
56    pub use crate::migrate::{
57        Migrator,
58        config::{Config, ForeignKeys, Synchronous},
59        migration::{Migrated, TransactionMigrate},
60    };
61    #[cfg(feature = "dev")]
62    pub use crate::schema::dev::hash_schema;
63    pub use rust_query_macros::schema;
64}
65
66/// These items are only exposed for use by the proc macros.
67/// Direct use is unsupported.
68#[doc(hidden)]
69pub mod private {
70    use std::marker::PhantomData;
71
72    pub use crate::joinable::Joinable;
73    pub use crate::migrate::{
74        Schema, SchemaMigration, TableTypBuilder,
75        migration::{Migration, SchemaBuilder},
76    };
77    pub use crate::query::get_plan;
78    pub use crate::schema::from_macro::TypBuilder;
79    pub use crate::value::{
80        DynTypedExpr, MyTyp, Typed, ValueBuilder, adhoc_expr, new_column, unique_from_joinable,
81    };
82    pub use crate::writable::{Reader, TableInsert};
83
84    pub struct Lazy<'t>(PhantomData<&'t ()>);
85    pub struct Ignore;
86    pub struct Custom<T>(PhantomData<T>);
87    pub struct AsUpdate;
88    pub struct AsExpr<'t>(PhantomData<&'t ()>);
89
90    pub trait Apply {
91        type Out<T: MyTyp, S>;
92    }
93
94    impl<'t> Apply for Lazy<'t> {
95        type Out<T: MyTyp, S> = T::Lazy<'t>;
96    }
97
98    impl Apply for Ignore {
99        type Out<T: MyTyp, S> = ();
100    }
101
102    impl<X> Apply for Custom<X> {
103        type Out<T: MyTyp, S> = X;
104    }
105
106    impl Apply for AsUpdate {
107        type Out<T: MyTyp, S> = crate::Update<S, T>;
108    }
109
110    impl<'t> Apply for AsExpr<'t> {
111        type Out<T: MyTyp, S> = crate::Expr<'t, S, T>;
112    }
113
114    pub trait UpdateOrUnit<S, T>: Default {}
115    impl<S, T: MyTyp> UpdateOrUnit<S, T> for crate::Update<S, T> {}
116    impl<S, T> UpdateOrUnit<S, T> for () {}
117
118    pub mod doctest {
119        use crate::{Database, Transaction, migrate::config::Config, migration};
120
121        #[migration::schema(Empty)]
122        pub mod vN {
123            pub struct User {
124                #[unique]
125                pub name: String,
126            }
127        }
128        pub use v0::*;
129
130        pub fn get_txn(f: impl Send + FnOnce(&'static mut Transaction<Empty>)) {
131            let db = Database::new(Config::open_in_memory());
132            db.transaction_mut_ok(|txn| {
133                txn.insert(User { name: "Alice" }).unwrap();
134                f(txn)
135            })
136        }
137    }
138}
139
140/// This trait is implemented for all table types as generated by the [crate::migration::schema] macro.
141///
142/// **You can not implement this trait yourself!**
143pub trait Table: Sized + 'static {
144    #[doc(hidden)]
145    type Ext2<'t>;
146
147    #[doc(hidden)]
148    fn covariant_ext<'x, 't>(val: &'x Self::Ext2<'static>) -> &'x Self::Ext2<'t>;
149
150    #[doc(hidden)]
151    fn build_ext2<'t>(val: &Expr<'t, Self::Schema, Self>) -> Self::Ext2<'t>;
152
153    /// The schema that this table is a part of.
154    type Schema;
155
156    #[doc(hidden)]
157    /// The table that this table can be migrated from.
158    type MigrateFrom: MyTyp;
159
160    /// The type of conflict that can result from inserting a row in this table.
161    /// This is the same type that is used for row updates too.
162    type Conflict;
163
164    /// The type of updates used by [Transaction::update_ok].
165    type UpdateOk;
166    /// The type of updates used by [Transaction::update].
167    type Update;
168    /// The type of error when a delete fails due to a foreign key constraint.
169    type Referer;
170
171    #[doc(hidden)]
172    type Lazy<'t>;
173    #[doc(hidden)]
174    type Insert;
175
176    #[doc(hidden)]
177    fn read(val: &Self::Insert, f: &mut Reader<Self::Schema>);
178
179    #[doc(hidden)]
180    fn get_conflict_unchecked(
181        txn: &Transaction<Self::Schema>,
182        val: &Self::Insert,
183    ) -> Self::Conflict;
184
185    #[doc(hidden)]
186    fn update_into_try_update(val: Self::UpdateOk) -> Self::Update;
187
188    #[doc(hidden)]
189    fn apply_try_update(val: Self::Update, old: Expr<'static, Self::Schema, Self>) -> Self::Insert;
190
191    #[doc(hidden)]
192    fn get_referer_unchecked() -> Self::Referer;
193
194    #[doc(hidden)]
195    fn get_lazy<'t>(txn: &'t Transaction<Self::Schema>, row: TableRow<Self>) -> Self::Lazy<'t>;
196
197    // used for the first join (useful for pragmas)
198    #[doc(hidden)]
199    fn name(&self) -> JoinableTable {
200        JoinableTable::Normal(Self::NAME.into())
201    }
202    #[doc(hidden)]
203    fn typs(f: &mut TypBuilder<Self::Schema>);
204
205    #[doc(hidden)]
206    const SPAN: (usize, usize);
207
208    #[doc(hidden)]
209    const ID: &'static str;
210    #[doc(hidden)]
211    const NAME: &'static str;
212}
213
214#[test]
215fn compile_tests() {
216    let t = trybuild::TestCases::new();
217    t.compile_fail("tests/compile/*.rs");
218}