sea_schema/mysql/query/
foreign_key.rs

1use super::{InformationSchema, SchemaQueryBuilder};
2use crate::sqlx_types::mysql::MySqlRow;
3use sea_query::{Expr, Iden, Order, Query, SeaRc, SelectStatement};
4
5#[derive(Debug, sea_query::Iden)]
6/// Ref: https://dev.mysql.com/doc/refman/8.0/en/information-schema-key-column-usage-table.html
7pub enum KeyColumnUsageFields {
8    ConstraintSchema,
9    ConstraintName,
10    TableSchema,
11    TableName,
12    ColumnName,
13    OrdinalPosition,
14    PositionInUniqueConstraint,
15    ReferencedTableSchema,
16    ReferencedTableName,
17    ReferencedColumnName,
18}
19
20#[derive(Debug, sea_query::Iden)]
21/// Ref: https://dev.mysql.com/doc/refman/8.0/en/information-schema-referential-constraints-table.html
22pub enum ReferentialConstraintsFields {
23    ConstraintSchema,
24    ConstraintName,
25    UniqueConstraintSchema,
26    UniqueConstraintName,
27    UpdateRule,
28    DeleteRule,
29    TableName,
30    ReferencedTableName,
31}
32
33#[derive(Debug, Default)]
34pub struct ForeignKeyQueryResult {
35    pub constraint_name: String,
36    pub column_name: String,
37    pub referenced_table_name: String,
38    pub referenced_column_name: String,
39    pub update_rule: String,
40    pub delete_rule: String,
41}
42
43impl SchemaQueryBuilder {
44    pub fn query_foreign_key(
45        &self,
46        schema: SeaRc<dyn Iden>,
47        table: SeaRc<dyn Iden>,
48    ) -> SelectStatement {
49        type Schema = InformationSchema;
50        type Key = KeyColumnUsageFields;
51        type Ref = ReferentialConstraintsFields;
52        Query::select()
53            .columns(vec![
54                (Schema::KeyColumnUsage, Key::ConstraintName),
55                (Schema::KeyColumnUsage, Key::ColumnName),
56                (Schema::KeyColumnUsage, Key::ReferencedTableName),
57                (Schema::KeyColumnUsage, Key::ReferencedColumnName),
58            ])
59            .columns(vec![
60                (Schema::ReferentialConstraints, Ref::UpdateRule),
61                (Schema::ReferentialConstraints, Ref::DeleteRule),
62            ])
63            .from((Schema::Schema, Schema::KeyColumnUsage))
64            .inner_join(
65                (Schema::Schema, Schema::ReferentialConstraints),
66                Expr::col((Schema::KeyColumnUsage, Key::ConstraintSchema))
67                    .equals((Schema::ReferentialConstraints, Ref::ConstraintSchema))
68                    .and(
69                        Expr::col((Schema::KeyColumnUsage, Key::ConstraintName))
70                            .equals((Schema::ReferentialConstraints, Ref::ConstraintName)),
71                    ),
72            )
73            .and_where(
74                Expr::col((Schema::KeyColumnUsage, Key::ConstraintSchema)).eq(schema.to_string()),
75            )
76            .and_where(Expr::col((Schema::KeyColumnUsage, Key::TableName)).eq(table.to_string()))
77            .and_where(Expr::col((Schema::KeyColumnUsage, Key::ReferencedTableName)).is_not_null())
78            .and_where(Expr::col((Schema::KeyColumnUsage, Key::ReferencedColumnName)).is_not_null())
79            .order_by(Key::ConstraintName, Order::Asc)
80            .order_by(Key::OrdinalPosition, Order::Asc)
81            .take()
82    }
83}
84
85#[cfg(feature = "sqlx-mysql")]
86impl From<&MySqlRow> for ForeignKeyQueryResult {
87    fn from(row: &MySqlRow) -> Self {
88        use crate::mysql::discovery::GetMySqlValue;
89        Self {
90            constraint_name: row.get_string(0),
91            column_name: row.get_string(1),
92            referenced_table_name: row.get_string(2),
93            referenced_column_name: row.get_string(3),
94            update_rule: row.get_string(4),
95            delete_rule: row.get_string(5),
96        }
97    }
98}
99
100#[cfg(not(feature = "sqlx-mysql"))]
101impl From<&MySqlRow> for ForeignKeyQueryResult {
102    fn from(_: &MySqlRow) -> Self {
103        Self::default()
104    }
105}