ormlite_core/
model.rs

1/// A model is a struct that represents a row in a relational database table.
2/// Using the `[derive(ormlite::Model)]` macro, it will acquire the following traits:
3///
4///  - `ormlite::Model`, giving it direct database access, e.g. `insert`, `update_all_fields`, etc.
5///  - `ormlite::HasModelBuilder`, letting it build partials, so you can insert or update some
6///    fields instead of all of them at once, e.g. `model.name("John").update()`
7///  - `ormlite::TableMeta`, which you typically don't use directly, but provides table metadata
8///    (e.g. table name)
9///
10use crate::Result;
11use crate::SelectQueryBuilder;
12use futures::future::BoxFuture;
13
14/// A struct that is `Insert` is expected to have same fields as the model, excluding fields
15/// that have sane defaults at the database level. Concretely, if you have a Person struct:
16/// #[derive(ormlite::Model)]
17/// struct Person {
18///     id: i32,
19///     name: String,
20///     age: i32,
21/// }
22///
23/// Then the `Insert` struct looks like:
24/// struct InsertPerson {
25///     name: String,
26///     age: i32,
27/// }
28pub trait Insert<DB>
29where
30    Self: Sized + Send + Sync,
31    DB: sqlx::Database,
32{
33    type Model;
34    fn insert<'e, A>(self, conn: A) -> BoxFuture<'e, Result<Self::Model>>
35    where
36        A: 'e + Send + sqlx::Acquire<'e, Database = DB>;
37}
38
39/// A struct that implements `ModelBuilder` implements the builder pattern for a model.
40pub trait ModelBuilder<'a, DB>
41where
42    Self: Sized + Send + Sync,
43    DB: sqlx::Database,
44{
45    type Model;
46
47    fn insert<'e: 'a, E>(self, db: E) -> BoxFuture<'a, Result<Self::Model>>
48    where
49        E: 'e + sqlx::Executor<'e, Database = DB>;
50
51    fn update<'e: 'a, E>(self, db: E) -> BoxFuture<'a, Result<Self::Model>>
52    where
53        E: 'e + sqlx::Executor<'e, Database = DB>;
54
55    /// All fields that will be modified in the query.
56    fn modified_fields(&self) -> Vec<&'static str>;
57
58    /// Build the model, don't insert or update it.
59    fn build(self) -> Self::Model;
60}
61
62/// The core trait. a struct that implements `Model` can also implement `HasModelBuilder`, (and is required to implement `Insertable`)
63pub trait Model<DB>
64where
65    DB: sqlx::Database,
66    Self: Sized + TableMeta,
67{
68    type ModelBuilder<'a>: ModelBuilder<'a, DB>
69    where
70        Self: 'a;
71
72    /// Insert the model into the database.
73    fn insert<'a, A>(self, conn: A) -> crate::insert::Insertion<'a, A, Self, DB>
74    where
75        A: 'a + Send + sqlx::Acquire<'a, Database = DB>,
76        Self: Send;
77
78    fn insert_many<'e, E>(values: Vec<Self>, db: E) -> BoxFuture<'e, Result<Vec<Self>>>
79    where
80        E: 'e + sqlx::Executor<'e, Database = DB>;
81
82    /// `Model` objects can't track what fields are updated, so this method will update all fields.
83    /// If you want to update only some fields, use `update_partial` instead.
84    fn update_all_fields<'e, E>(self, db: E) -> BoxFuture<'e, Result<Self>>
85    where
86        E: 'e + Send + sqlx::Executor<'e, Database = DB>;
87
88    fn delete<'e, E>(self, db: E) -> BoxFuture<'e, Result<()>>
89    where
90        E: 'e + sqlx::Executor<'e, Database = DB>;
91
92    /// Get by primary key.
93    fn fetch_one<'e, 'a, Arg, E>(id: Arg, db: E) -> BoxFuture<'e, Result<Self>>
94    where
95        'a: 'e,
96        E: 'e + sqlx::Executor<'e, Database = DB>,
97        Arg: 'a + Send + sqlx::Encode<'a, DB> + sqlx::Type<DB>;
98
99    /// If query building isn't meeting your needs, use this method to query the table using raw SQL.
100    fn query(query: &str) -> sqlx::query::QueryAs<DB, Self, DB::Arguments<'_>>;
101
102    /// Create a `SelectQueryBuilder` to build a query.
103    fn select<'args>() -> SelectQueryBuilder<'args, DB, Self>;
104
105    /// Create a builder-pattern object to update one or more columns.
106    /// You can also use `update_all_fields` to update all columns.
107    fn update_partial(&self) -> Self::ModelBuilder<'_>;
108
109    fn builder() -> Self::ModelBuilder<'static>;
110}
111
112pub trait TableMeta {
113    fn table_name() -> &'static str;
114    fn table_columns() -> &'static [&'static str];
115    fn primary_key() -> Option<&'static str>;
116    fn primary_key_placeholder_idx() -> Option<usize> {
117        let col = Self::primary_key()?;
118        Self::table_columns().iter().position(|&c| c == col).map(|i| i + 1)
119    }
120}