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