toql_core/
key.rs

1//! Table mapping information for keys.
2//!
3//! The key trait is implemented for every key struct the the Toql derive gernerates..
4//! It is used for internal purposes to build key predicates and for trait bounds.
5//!
6//! Library users may also use it for trait bounds.
7//!
8//! The trait cannot be used to get a key from an entity. This can be done with the [Keyed](crate::keyed::Keyed) trait.
9
10use crate::{sql_arg::SqlArg, sql_expr::SqlExpr};
11
12/// Trait to provide the entity type for a key. This is only used
13/// for ergonomics of the api.
14pub trait Key {
15    type Entity;
16
17    /// Return primary key columns for a given entity.
18    fn columns() -> Vec<String>;
19
20    /// Return foreign key columns that match the primary keys for a given entity.
21    /// This is only needed to merge entities.
22    /// The names are calculated and do not necessarily match
23    /// the actual foreign keys on the other table.
24    /// The translation rules are (for snake case column format):
25    ///
26    /// | Type          | Guessing rule             | Example      |
27    /// | --------------|---------------------------|---------------|
28    /// | Normal fields |  tablename + normal field | `id` -> `user_id`, `access_code` -> `user_access_code` |
29    /// | Joins         |  *No change* | `language_id` -> `language_id` |
30    ///
31    /// If the automatic generated names are not correct, the user is required to correct them by attributing
32    /// the relevant field with
33    ///  
34    /// `#[toql( merge( columns( self = "id", other = "user_code")))]`
35    ///
36    fn default_inverse_columns() -> Vec<String>;
37
38    /// Return key values as params. Useful to loop across a composite key.
39    fn params(&self) -> Vec<SqlArg>;
40
41    fn unaliased_predicate_expr(&self) -> SqlExpr {
42        let columns = Self::columns();
43        let mut params = self.params().into_iter();
44        let mut expr = SqlExpr::new();
45
46        for c in columns {
47            if !expr.is_empty() {
48                expr.push_literal(" AND ".to_string());
49            }
50            expr.push_literal(c);
51            expr.push_literal(" = ".to_string());
52            expr.push_arg(params.next().unwrap_or(SqlArg::Null));
53        }
54        expr
55    }
56}