Skip to main content

sea_schema/mysql/query/
table.rs

1use super::{CharacterSetFields, InformationSchema, SchemaQueryBuilder};
2use crate::sqlx_types::SqlxRow;
3use sea_query::{Condition, DynIden, Expr, ExprTrait, Iden, Order, Query, SelectStatement};
4
5const MARIADB_FULL_COLLATION_NAME_SINCE: u32 = 101001;
6
7#[derive(Debug, Clone, Copy, sea_query::Iden)]
8/// Refs:
9/// - https://dev.mysql.com/doc/refman/8.0/en/information-schema-tables-table.html
10/// - https://mariadb.com/docs/server/reference/system-tables/information-schema/information-schema-tables
11pub enum TablesFields {
12    TableCatalog,
13    TableSchema,
14    TableName,
15    TableType,
16    Engine,
17    Version,
18    RowFormat,
19    TableRows,
20    AvgRowLength,
21    DataLength,
22    MaxDataLength,
23    IndexLength,
24    DataFree,
25    AutoIncrement,
26    CreateTime,
27    UpdateTime,
28    CheckTime,
29    TableCollation,
30    Checksum,
31    CreateOptions,
32    TableComment,
33}
34
35#[derive(Debug, sea_query::Iden)]
36pub enum TableType {
37    #[iden = "BASE TABLE"]
38    BaseTable,
39    #[iden = "VIEW"]
40    View,
41    #[iden = "SYSTEM VIEW"]
42    SystemView,
43    #[iden = "SYSTEM VERSIONED"]
44    SystemVersioned,
45}
46
47#[derive(Debug, Default)]
48pub struct TableQueryResult {
49    pub table_name: String,
50    pub engine: String,
51    pub auto_increment: Option<u64>,
52    pub table_char_set: Option<String>,
53    pub table_collation: Option<String>,
54    pub table_comment: String,
55    pub create_options: String,
56}
57
58impl SchemaQueryBuilder {
59    pub fn query_tables(&self, schema: DynIden) -> SelectStatement {
60        type Schema = InformationSchema;
61        let is_mariadb_and_ge_10_10_01 =
62            self.system.is_maria_db() && self.system.version >= MARIADB_FULL_COLLATION_NAME_SINCE;
63
64        Query::select()
65            .columns(vec![
66                TablesFields::TableName,
67                TablesFields::Engine,
68                TablesFields::AutoIncrement,
69                TablesFields::TableCollation,
70                TablesFields::TableComment,
71                TablesFields::CreateOptions,
72            ])
73            .column((
74                Schema::CollationCharacterSet,
75                CharacterSetFields::CharacterSetName,
76            ))
77            .from((Schema::Schema, Schema::Tables))
78            .left_join((Schema::Schema, Schema::CollationCharacterSet), {
79                let info_tables_collation = (Schema::Tables, TablesFields::TableCollation);
80                Condition::any()
81                    .add_option(is_mariadb_and_ge_10_10_01.then(|| {
82                        Expr::col((
83                            Schema::CollationCharacterSet,
84                            CharacterSetFields::FullCollationName,
85                        ))
86                        .equals(info_tables_collation)
87                    }))
88                    .add(
89                        Expr::col((
90                            Schema::CollationCharacterSet,
91                            CharacterSetFields::CollationName,
92                        ))
93                        .equals(info_tables_collation),
94                    )
95            })
96            .and_where(Expr::col(TablesFields::TableSchema).eq(schema.to_string()))
97            .and_where(Expr::col(TablesFields::TableType).is_in([
98                TableType::BaseTable.to_string(),
99                TableType::SystemVersioned.to_string(),
100            ]))
101            .order_by(TablesFields::TableName, Order::Asc)
102            .take()
103    }
104}
105
106#[cfg(feature = "sqlx-mysql")]
107impl From<SqlxRow> for TableQueryResult {
108    fn from(row: SqlxRow) -> Self {
109        use crate::mysql::discovery::GetMySqlValue;
110        use crate::sqlx_types::Row;
111        let row = row.mysql();
112        Self {
113            table_name: row.get_string(0),
114            engine: row.get_string(1),
115            auto_increment: row.get(2),
116            table_collation: row.get_string_opt(3),
117            table_comment: row.get_string(4),
118            create_options: row.get_string(5),
119            table_char_set: row.get_string_opt(6),
120        }
121    }
122}
123
124#[cfg(not(feature = "sqlx-mysql"))]
125impl From<SqlxRow> for TableQueryResult {
126    fn from(_: SqlxRow) -> Self {
127        Self::default()
128    }
129}