Skip to main content

sea_query/foreign_key/
create.rs

1use crate::{
2    ForeignKeyAction, SchemaStatementBuilder, TableForeignKey, backend::SchemaBuilder, types::*,
3};
4
5/// Create a foreign key constraint for an existing table. Unsupported by Sqlite
6///
7/// # Examples
8///
9/// ```
10/// use sea_query::{tests_cfg::*, *};
11///
12/// let foreign_key = ForeignKey::create()
13///     .name("FK_character_font")
14///     .from(Char::Table, Char::FontId)
15///     .to(Font::Table, Font::Id)
16///     .on_delete(ForeignKeyAction::Cascade)
17///     .on_update(ForeignKeyAction::Cascade)
18///     .to_owned();
19///
20/// assert_eq!(
21///     foreign_key.to_string(MysqlQueryBuilder),
22///     [
23///         r#"ALTER TABLE `character`"#,
24///         r#"ADD CONSTRAINT `FK_character_font`"#,
25///         r#"FOREIGN KEY (`font_id`) REFERENCES `font` (`id`)"#,
26///         r#"ON DELETE CASCADE ON UPDATE CASCADE"#,
27///     ]
28///     .join(" ")
29/// );
30/// assert_eq!(
31///     foreign_key.to_string(PostgresQueryBuilder),
32///     [
33///         r#"ALTER TABLE "character" ADD CONSTRAINT "FK_character_font""#,
34///         r#"FOREIGN KEY ("font_id") REFERENCES "font" ("id")"#,
35///         r#"ON DELETE CASCADE ON UPDATE CASCADE"#,
36///     ]
37///     .join(" ")
38/// );
39/// ```
40///
41/// Composite key
42/// ```
43/// use sea_query::{tests_cfg::*, *};
44///
45/// let foreign_key = ForeignKey::create()
46///     .name("FK_character_glyph")
47///     .from(Char::Table, (Char::FontId, Char::Id))
48///     .to(Glyph::Table, (Char::FontId, Glyph::Id))
49///     .on_delete(ForeignKeyAction::Cascade)
50///     .on_update(ForeignKeyAction::Cascade)
51///     .to_owned();
52///
53/// assert_eq!(
54///     foreign_key.to_string(MysqlQueryBuilder),
55///     [
56///         r#"ALTER TABLE `character`"#,
57///         r#"ADD CONSTRAINT `FK_character_glyph`"#,
58///         r#"FOREIGN KEY (`font_id`, `id`) REFERENCES `glyph` (`font_id`, `id`)"#,
59///         r#"ON DELETE CASCADE ON UPDATE CASCADE"#,
60///     ]
61///     .join(" ")
62/// );
63/// assert_eq!(
64///     foreign_key.to_string(PostgresQueryBuilder),
65///     [
66///         r#"ALTER TABLE "character" ADD CONSTRAINT "FK_character_glyph""#,
67///         r#"FOREIGN KEY ("font_id", "id") REFERENCES "glyph" ("font_id", "id")"#,
68///         r#"ON DELETE CASCADE ON UPDATE CASCADE"#,
69///     ]
70///     .join(" ")
71/// );
72/// ```
73#[derive(Default, Debug, Clone)]
74pub struct ForeignKeyCreateStatement {
75    pub(crate) foreign_key: TableForeignKey,
76}
77
78impl ForeignKeyCreateStatement {
79    /// Construct a new [`ForeignKeyCreateStatement`]
80    pub fn new() -> Self {
81        Self::default()
82    }
83
84    /// Set foreign key name
85    pub fn name<T>(&mut self, name: T) -> &mut Self
86    where
87        T: Into<String>,
88    {
89        self.foreign_key.name(name);
90        self
91    }
92
93    /// Set key table and columns
94    pub fn from<T, C>(&mut self, table: T, columns: C) -> &mut Self
95    where
96        T: IntoTableRef,
97        C: IdenList,
98    {
99        self.foreign_key.from_tbl(table);
100        for col in columns.into_iter() {
101            self.foreign_key.from_col(col);
102        }
103        self
104    }
105
106    /// Set referencing table and columns
107    pub fn to<T, C>(&mut self, table: T, columns: C) -> &mut Self
108    where
109        T: IntoTableRef,
110        C: IdenList,
111    {
112        self.foreign_key.to_tbl(table);
113        for col in columns.into_iter() {
114            self.foreign_key.to_col(col);
115        }
116        self
117    }
118
119    /// Set key table
120    pub fn from_tbl<T>(&mut self, table: T) -> &mut Self
121    where
122        T: IntoTableRef,
123    {
124        self.foreign_key.from_tbl(table);
125        self
126    }
127
128    /// Set referencing table
129    pub fn to_tbl<R>(&mut self, ref_table: R) -> &mut Self
130    where
131        R: IntoTableRef,
132    {
133        self.foreign_key.to_tbl(ref_table);
134        self
135    }
136
137    /// Add key column
138    pub fn from_col<T>(&mut self, column: T) -> &mut Self
139    where
140        T: IntoIden,
141    {
142        self.foreign_key.from_col(column);
143        self
144    }
145
146    /// Add referencing column
147    pub fn to_col<R>(&mut self, ref_column: R) -> &mut Self
148    where
149        R: IntoIden,
150    {
151        self.foreign_key.to_col(ref_column);
152        self
153    }
154
155    /// Set on delete action
156    pub fn on_delete(&mut self, action: ForeignKeyAction) -> &mut Self {
157        self.foreign_key.on_delete(action);
158        self
159    }
160
161    /// Set on update action
162    pub fn on_update(&mut self, action: ForeignKeyAction) -> &mut Self {
163        self.foreign_key.on_update(action);
164        self
165    }
166
167    pub fn get_foreign_key(&self) -> &TableForeignKey {
168        &self.foreign_key
169    }
170
171    pub fn take(&mut self) -> Self {
172        Self {
173            foreign_key: self.foreign_key.take(),
174        }
175    }
176}
177
178impl SchemaStatementBuilder for ForeignKeyCreateStatement {
179    fn build<T: SchemaBuilder>(&self, schema_builder: T) -> String {
180        let mut sql = String::with_capacity(256);
181        schema_builder.prepare_foreign_key_create_statement(self, &mut sql);
182        sql
183    }
184}
185
186impl ForeignKeyCreateStatement {
187    pub fn build<T: SchemaBuilder>(&self, schema_builder: T) -> String {
188        <Self as SchemaStatementBuilder>::build(self, schema_builder)
189    }
190
191    pub fn to_string<T: SchemaBuilder>(&self, schema_builder: T) -> String {
192        <Self as SchemaStatementBuilder>::to_string(self, schema_builder)
193    }
194}