-
Notifications
You must be signed in to change notification settings - Fork 212
/
relation.rs
85 lines (75 loc) 路 3.38 KB
/
relation.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
use prisma_models::{ModelProjection, Relation, RelationField, RelationLinkManifestation, RelationSide};
use quaint::{ast::Table, prelude::Column};
use RelationLinkManifestation::*;
use crate::model_extensions::AsColumns;
use super::{AsTable, ColumnIterator};
pub trait RelationFieldExt {
fn m2m_columns(&self) -> Vec<Column<'static>>;
fn join_columns(&self) -> ColumnIterator;
fn identifier_columns(&self) -> ColumnIterator;
fn as_table(&self) -> Table<'static>;
}
impl RelationFieldExt for RelationField {
fn m2m_columns(&self) -> Vec<Column<'static>> {
let references = &self.relation_info.references;
let prefix = if self.relation_side.is_a() { "B" } else { "A" };
if references.len() > 1 {
references
.iter()
.map(|to_field| format!("{}_{}", prefix, to_field))
.map(|name| Column::from(name).table(self.as_table()))
.collect()
} else {
vec![Column::from(prefix).table(self.as_table())]
}
}
fn join_columns(&self) -> ColumnIterator {
match (&self.relation().manifestation, &self.relation_side) {
(RelationTable(ref m), RelationSide::A) => ColumnIterator::from(vec![m.model_b_column.clone().into()]),
(RelationTable(ref m), RelationSide::B) => ColumnIterator::from(vec![m.model_a_column.clone().into()]),
_ => ModelProjection::from(self.linking_fields()).as_columns(),
}
}
fn identifier_columns(&self) -> ColumnIterator {
match (&self.relation().manifestation, &self.relation_side) {
(RelationTable(ref m), RelationSide::A) => ColumnIterator::from(vec![m.model_a_column.clone().into()]),
(RelationTable(ref m), RelationSide::B) => ColumnIterator::from(vec![m.model_b_column.clone().into()]),
_ => ModelProjection::from(self.model().primary_identifier()).as_columns(),
}
}
fn as_table(&self) -> Table<'static> {
if self.relation().is_many_to_many() {
self.related_field().relation().as_table()
} else {
self.model().as_table()
}
}
}
impl AsTable for Relation {
/// The `Table` with the foreign keys are written. Can either be:
///
/// - A separate table for many-to-many relations.
/// - One of the model tables for one-to-many or one-to-one relations.
/// - A separate relation table for all relations, if using the deprecated
/// data model syntax.
fn as_table(&self) -> Table<'static> {
match self.manifestation {
// In this case we must define our unique indices for the relation
// table, so MSSQL can convert the `INSERT .. ON CONFLICT IGNORE` into
// a `MERGE` statement.
RelationLinkManifestation::RelationTable(ref m) => {
let model_a = self.model_a();
let prefix = model_a
.schema_name()
.unwrap_or_else(|| model_a.internal_data_model().db_name.clone());
let table: Table = (prefix, m.table.clone()).into();
table.add_unique_index(vec![Column::from("A"), Column::from("B")])
}
RelationLinkManifestation::Inline(ref m) => self
.internal_data_model()
.find_model(&m.in_table_of_model_name)
.unwrap()
.as_table(),
}
}
}