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 client;
12mod db;
13mod dummy_impl;
14mod hash;
15mod migrate;
16mod mymap;
17mod query;
18mod ref_cast_impl;
19mod rows;
20mod schema_pragma;
21mod transaction;
22mod value;
23mod writable;
24
25pub use client::LocalClient;
26pub use db::TableRow;
27pub use dummy_impl::{IntoSelect, IntoSelectExt, Select};
28use hash::TypBuilder;
29use private::Reader;
30use ref_cast::RefCast;
31use rows::Rows;
32pub use rust_query_macros::{FromExpr, Select};
33pub use transaction::{Database, Transaction, TransactionMut, 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
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::{Config, Migrated, Migrator, TransactionMigrate};
57    pub use rust_query_macros::schema;
58}
59
60/// These items are only exposed for use by the proc macros.
61/// Direct use is unsupported.
62#[doc(hidden)]
63pub mod private {
64    use std::marker::PhantomData;
65
66    pub use crate::db::Col;
67    pub use crate::hash::TypBuilder;
68    pub use crate::migrate::{Migration, Schema, SchemaBuilder, SchemaMigration, TableTypBuilder};
69    pub use crate::query::show_sql;
70    pub use crate::value::{
71        MyTyp, Typed, ValueBuilder, adhoc_expr, assume_expr, into_owned, new_column, new_dummy,
72    };
73    pub use crate::writable::{Reader, TableInsert};
74
75    pub use ref_cast::RefCast;
76    pub use rust_query_macros::fields;
77    pub use sea_query::SimpleExpr;
78
79    pub struct Native<'t>(PhantomData<&'t ()>);
80    pub struct Ignore;
81    pub struct Custom<T>(PhantomData<T>);
82    pub struct Update<'t>(PhantomData<&'t ()>);
83    pub struct AsExpr<'t>(PhantomData<&'t ()>);
84
85    pub trait Apply {
86        type Out<T: MyTyp, S>;
87    }
88
89    impl<'t> Apply for Native<'t> {
90        type Out<T: MyTyp, S> = T::Out<'t>;
91    }
92
93    impl Apply for Ignore {
94        type Out<T: MyTyp, S> = ();
95    }
96
97    impl<X> Apply for Custom<X> {
98        type Out<T: MyTyp, S> = X;
99    }
100
101    impl<'t> Apply for Update<'t> {
102        type Out<T: MyTyp, S> = crate::Update<'t, S, T>;
103    }
104
105    impl<'t> Apply for AsExpr<'t> {
106        type Out<T: MyTyp, S> = crate::Expr<'t, S, T>;
107    }
108
109    pub trait Instantiate<const STRUCT_ID: usize, Params> {
110        type Out;
111    }
112
113    pub mod doctest {
114        use crate::{LocalClient, TransactionMut, migrate::Config, migration};
115
116        #[migration::schema(Empty)]
117        pub mod vN {
118            pub struct User {
119                #[unique]
120                pub name: String,
121            }
122        }
123        pub use v0::*;
124
125        pub fn get_client() -> LocalClient {
126            LocalClient::try_new().unwrap()
127        }
128        pub fn get_txn(client: &mut LocalClient) -> TransactionMut<Empty> {
129            let db = client
130                .migrator(Config::open_in_memory())
131                .unwrap()
132                .finish()
133                .unwrap();
134            let mut txn = client.transaction_mut(&db);
135            txn.insert(User { name: "Alice" }).unwrap();
136            txn
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    /// The associated type [Table::Ext] is used as the deref target by several types that implement [IntoExpr].
146    /// This adds convenient methods to access related tables that have a foreign key constraint.
147    #[doc(hidden)]
148    type Ext<T>: RefCast<From = T>;
149
150    /// The schema that this table is a part of.
151    type Schema;
152
153    #[doc(hidden)]
154    /// The table that this table can be migrated from.
155    type MigrateFrom: MyTyp;
156
157    /// Please refer to [Rows::join].
158    fn join<'inner>(rows: &mut Rows<'inner, Self::Schema>) -> Expr<'inner, Self::Schema, Self> {
159        rows.join()
160    }
161
162    /// The type of conflict that can result from inserting a row in this table.
163    /// This is the same type that is used for row updates too.
164    type Conflict<'t>;
165
166    /// The type of updates used by [TransactionMut::update_ok].
167    type UpdateOk<'t>;
168    /// The type of updates used by [TransactionMut::update].
169    type Update<'t>;
170    /// The type of error when a delete fails due to a foreign key constraint.
171    type Referer;
172
173    #[doc(hidden)]
174    type Insert<'t>;
175
176    #[doc(hidden)]
177    fn read<'t>(val: &Self::Insert<'t>, f: &Reader<'t, Self::Schema>);
178
179    #[doc(hidden)]
180    fn get_conflict_unchecked<'t>(val: &Self::Insert<'t>) -> Self::Conflict<'t>;
181
182    #[doc(hidden)]
183    fn update_into_try_update<'t>(val: Self::UpdateOk<'t>) -> Self::Update<'t>;
184
185    #[doc(hidden)]
186    fn apply_try_update<'t>(
187        val: Self::Update<'t>,
188        old: Expr<'t, Self::Schema, Self>,
189    ) -> Self::Insert<'t>;
190
191    #[doc(hidden)]
192    fn get_referer_unchecked() -> Self::Referer;
193
194    // used for the first join (useful for pragmas)
195    #[doc(hidden)]
196    fn name(&self) -> String {
197        Self::NAME.to_owned()
198    }
199    #[doc(hidden)]
200    fn typs(f: &mut TypBuilder<Self::Schema>);
201
202    #[doc(hidden)]
203    const ID: &'static str;
204    #[doc(hidden)]
205    const NAME: &'static str;
206}
207
208#[test]
209fn compile_tests() {
210    let t = trybuild::TestCases::new();
211    t.compile_fail("tests/compile/*.rs");
212}