sea_query/types/
qualification.rs

1//! Conversion traits/impls for "potentially qualified" names like `(schema?).(table?).column`.
2
3use super::*;
4
5// -------------------------- MaybeQualifiedOnce -------------------------------
6
7/// A name that can be unqualified (`foo`) or qualified once (`foo.bar`).
8///
9/// This is mostly a "private" helper trait to provide reusable conversions.
10pub trait MaybeQualifiedOnce {
11    /// Represent a maybe-qualified name as a `(foo?, bar)` tuple.
12    fn into_2_parts(self) -> (Option<DynIden>, DynIden);
13}
14
15/// Only the "base", no qualification (`foo`).
16impl<T> MaybeQualifiedOnce for T
17where
18    T: IntoIden,
19{
20    fn into_2_parts(self) -> (Option<DynIden>, DynIden) {
21        (None, self.into_iden())
22    }
23}
24
25/// With a qualification (`foo.bar`).
26impl<S, T> MaybeQualifiedOnce for (S, T)
27where
28    S: IntoIden,
29    T: IntoIden,
30{
31    fn into_2_parts(self) -> (Option<DynIden>, DynIden) {
32        let (qual, base) = self;
33        (Some(qual.into_iden()), base.into_iden())
34    }
35}
36
37// ------------------------- MaybeQualifiedTwice -------------------------------
38
39/// A name that can be unqualified (`foo`), qualified once (`foo.bar`), or twice (`foo.bar.baz`).
40///
41/// This is mostly a "private" helper trait to provide reusable conversions.
42pub trait MaybeQualifiedTwice {
43    /// Represent a maybe-qualified name as a `(foo?, bar?, baz)` tuple.
44    ///
45    /// To be precise, it's actually `((foo?, bar)?, baz)` to rule out invalid states like `(Some, None, Some)`.
46    fn into_3_parts(self) -> (Option<(Option<DynIden>, DynIden)>, DynIden);
47}
48
49/// From 1 or 2 parts (`foo` or `foo.bar`).
50impl<T> MaybeQualifiedTwice for T
51where
52    T: MaybeQualifiedOnce,
53{
54    fn into_3_parts(self) -> (Option<(Option<DynIden>, DynIden)>, DynIden) {
55        let (middle, base) = self.into_2_parts();
56        let qual = middle.map(|middle| (None, middle));
57        (qual, base)
58    }
59}
60
61/// Fully-qualified from 3 parts (`foo.bar.baz`).
62impl<S, T, U> MaybeQualifiedTwice for (S, T, U)
63where
64    S: IntoIden,
65    T: IntoIden,
66    U: IntoIden,
67{
68    fn into_3_parts(self) -> (Option<(Option<DynIden>, DynIden)>, DynIden) {
69        let (q2, q1, base) = self;
70        let (q2, q1, base) = (q2.into_iden(), q1.into_iden(), base.into_iden());
71        let q = (Some(q2), q1);
72        (Some(q), base)
73    }
74}
75
76// -------------------------------- impls --------------------------------------
77
78/// Construct a [`SchemaName`] from 1-2 parts (`(database?).schema`)
79impl<T> From<T> for SchemaName
80where
81    T: MaybeQualifiedOnce,
82{
83    fn from(value: T) -> Self {
84        let (db, schema) = value.into_2_parts();
85        let db_name = db.map(DatabaseName);
86        SchemaName(db_name, schema)
87    }
88}
89
90/// Construct a [`TypeRef`] from 1-3 parts (`(database?).(schema?).type`)
91impl<T> From<T> for TypeRef
92where
93    T: MaybeQualifiedTwice,
94{
95    fn from(value: T) -> Self {
96        let (schema_parts, r#type) = value.into_3_parts();
97        let schema_name = schema_parts.map(|schema_parts| match schema_parts {
98            (Some(db), schema) => SchemaName(Some(DatabaseName(db)), schema),
99            (None, schema) => SchemaName(None, schema),
100        });
101        TypeRef(schema_name, r#type)
102    }
103}
104
105/// Construct a [`TableName`] from 1-3 parts (`(database?).(schema?).table`)
106impl<T> From<T> for TableName
107where
108    T: MaybeQualifiedTwice,
109{
110    fn from(value: T) -> Self {
111        let (schema_parts, table) = value.into_3_parts();
112        let schema_name = schema_parts.map(|schema_parts| match schema_parts {
113            (Some(db), schema) => SchemaName(Some(DatabaseName(db)), schema),
114            (None, schema) => SchemaName(None, schema),
115        });
116        TableName(schema_name, table)
117    }
118}
119
120/// Construct a [`ColumnName`] from 1-3 parts (`(schema?).(table?).column`)
121impl<T> From<T> for ColumnName
122where
123    T: MaybeQualifiedTwice,
124{
125    fn from(value: T) -> Self {
126        let (table_parts, column) = value.into_3_parts();
127        let table_name = table_parts.map(|table_parts| match table_parts {
128            (Some(schema), table) => TableName(Some(schema.into()), table),
129            (None, table) => TableName(None, table),
130        });
131        ColumnName(table_name, column)
132    }
133}