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