rust_query/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#![allow(private_bounds)]
#![doc = include_str!("../README.md")]

extern crate self as rust_query;

mod aggregate;
mod alias;
mod ast;
mod client;
mod db;
mod dummy;
mod exec;
mod hash;
mod insert;
mod migrate;
mod mymap;
mod pragma;
mod ref_cast_impl;
mod rows;
mod token;
mod transaction;
mod value;

pub use crate::dummy::Dummy;
pub use aggregate::aggregate;
pub use db::TableRow;
use hash::TypBuilder;
use ref_cast::RefCast;
pub use rows::Rows;
pub use rust_query_macros::FromDummy;
pub use token::LocalClient;
pub use transaction::{Database, Transaction, TransactionMut};
pub use value::{Column, IntoColumn, UnixEpoch};

/// Types that are used as closure arguments.
///
/// You generally don't need to import these types.
pub mod args {
    pub use crate::aggregate::Aggregate;
    pub use crate::exec::Query;
}

/// Types to declare schemas and migrations.
///
/// A good starting point is too look at [crate::migration::schema].
pub mod migration {
    pub use crate::migrate::{Alter, Config, Create, Migrator, NoTable};
    pub use expect_test::expect;
    pub use rust_query_macros::schema;
}

/// These items are only exposed for use by the proc macros.
/// Direct use is unsupported.
#[doc(hidden)]
pub mod private {
    pub use crate::db::Col;
    pub use crate::dummy::{Cached, Cacher, Dummy, Row};
    pub use crate::exec::show_sql;
    pub use crate::hash::TypBuilder;
    pub use crate::hash::{hash_schema, KangarooHasher};
    pub use crate::insert::{Reader, Writable};
    pub use crate::migrate::{
        Migration, Schema, SchemaBuilder, TableCreation, TableMigration, TableTypBuilder, C, M,
    };
    pub use crate::value::{MyTyp, Typed, ValueBuilder};

    pub use expect_test::Expect;
    pub use ref_cast::RefCast;
    pub use sea_query::SimpleExpr;

    struct Null;
    struct NotNull;

    // TODO: maybe remove this trait?
    // currently this prevents storing booleans and nested enums.
    trait ValidInSchema<S> {
        type N;
    }

    impl<S> ValidInSchema<S> for String {
        type N = NotNull;
    }
    impl<S> ValidInSchema<S> for i64 {
        type N = NotNull;
    }
    impl<S> ValidInSchema<S> for f64 {
        type N = NotNull;
    }
    impl<S, T: ValidInSchema<S, N = NotNull>> ValidInSchema<S> for Option<T> {
        type N = Null;
    }
    impl<T: crate::Table> ValidInSchema<T::Schema> for T {
        type N = NotNull;
    }

    pub fn valid_in_schema<S, T: ValidInSchema<S>>() {}

    pub fn valid_in_unique<S, T: ValidInSchema<S, N = NotNull>>() {}
}

/// This trait is implemented for all table types as generated by the [crate::migration::schema] macro.
///
/// **You can not implement this trait yourself!**
pub trait Table: Sized + 'static {
    /// The associated type [Table::Ext] is used as the deref target by several types that implement [IntoColumn].
    /// This adds convenient methods to access related tables that have a foreign key constraint.
    type Ext<T>: RefCast<From = T>;

    /// The schema that this table is a part of.
    type Schema;

    /// Please refer to [Rows::join].
    fn join<'inner>(rows: &mut Rows<'inner, Self::Schema>) -> Column<'inner, Self::Schema, Self> {
        rows.join()
    }

    /// The type returned by the [Table::dummy] method.
    type Dummy<'t>;

    /// Create a dummy that can be used for [TransactionMut::try_insert] and [TransactionMut::try_update] etc.
    /// ```rust,ignore
    /// txn.find_and_update(User {
    ///     email: new_email,
    ///     ..user.dummy()
    /// })
    /// .unwrap();
    /// ```
    /// Note that all fields of the dummy have type [Column], so if you want to change the value to something that is not
    /// a [Column], then you need to do one of the following:
    /// - Turn the value into a [Column] with [IntoColumn::into_column].
    /// - Use `#![feature(type_changing_struct_update)]`.
    fn dummy<'t>(val: impl IntoColumn<'t, Self::Schema, Typ = Self>) -> Self::Dummy<'t>;

    // used for the first join (useful for pragmas)
    #[doc(hidden)]
    fn name(&self) -> String {
        Self::NAME.to_owned()
    }
    #[doc(hidden)]
    fn typs(f: &mut TypBuilder);

    #[doc(hidden)]
    const ID: &'static str = "";
    #[doc(hidden)]
    const NAME: &'static str = "";
}