Skip to main content

sea_query/backend/mysql/
index.rs

1use super::*;
2
3impl IndexBuilder for MysqlQueryBuilder {
4    fn prepare_table_index_expression(
5        &self,
6        create: &IndexCreateStatement,
7        sql: &mut impl SqlWriter,
8    ) {
9        self.prepare_index_prefix(create, sql);
10        sql.write_str("KEY ").unwrap();
11
12        if let Some(name) = &create.index.name {
13            sql.write_char(self.quote().left()).unwrap();
14            sql.write_str(name).unwrap();
15            sql.write_char(self.quote().right()).unwrap();
16            sql.write_str(" ").unwrap();
17        }
18
19        self.prepare_index_type(&create.index_type, sql);
20        if matches!(create.index_type, Some(IndexType::FullText)) {
21            sql.write_str(" ").unwrap();
22        }
23
24        self.prepare_index_columns(&create.index.columns, sql);
25        self.prepare_filter(&create.r#where, sql);
26    }
27
28    fn prepare_index_create_statement(
29        &self,
30        create: &IndexCreateStatement,
31        sql: &mut impl SqlWriter,
32    ) {
33        sql.write_str("CREATE ").unwrap();
34        self.prepare_index_prefix(create, sql);
35        sql.write_str("INDEX ").unwrap();
36
37        if let Some(name) = &create.index.name {
38            sql.write_char(self.quote().left()).unwrap();
39            sql.write_str(name).unwrap();
40            sql.write_char(self.quote().right()).unwrap();
41        }
42
43        sql.write_str(" ON ").unwrap();
44        if let Some(table) = &create.table {
45            self.prepare_table_ref_index_stmt(table, sql);
46        }
47        sql.write_str(" ").unwrap();
48        self.prepare_index_columns(&create.index.columns, sql);
49
50        self.prepare_index_type(&create.index_type, sql);
51        self.prepare_filter(&create.r#where, sql);
52    }
53
54    fn prepare_table_ref_index_stmt(&self, table_ref: &TableRef, sql: &mut impl SqlWriter) {
55        match table_ref {
56            // Support only "naked" table names with no schema or alias.
57            TableRef::Table(TableName(None, _), None) => {
58                self.prepare_table_ref_iden(table_ref, sql)
59            }
60            _ => panic!("Not supported"),
61        }
62    }
63    fn prepare_index_drop_statement(&self, drop: &IndexDropStatement, sql: &mut impl SqlWriter) {
64        sql.write_str("DROP INDEX ").unwrap();
65
66        if drop.if_exists {
67            panic!("Mysql does not support IF EXISTS for DROP INDEX")
68        }
69
70        if let Some(name) = &drop.index.name {
71            sql.write_char(self.quote().left()).unwrap();
72            sql.write_str(name).unwrap();
73            sql.write_char(self.quote().right()).unwrap();
74        }
75
76        sql.write_str(" ON ").unwrap();
77        if let Some(table) = &drop.table {
78            self.prepare_table_ref_index_stmt(table, sql);
79        }
80    }
81
82    fn prepare_index_type(&self, col_index_type: &Option<IndexType>, sql: &mut impl SqlWriter) {
83        if let Some(index_type) = col_index_type {
84            if !matches!(index_type, IndexType::FullText) {
85                sql.write_str(" USING ").unwrap();
86                sql.write_str(match index_type {
87                    IndexType::BTree => "BTREE",
88                    IndexType::FullText => unreachable!(),
89                    IndexType::Hash => "HASH",
90                    IndexType::Custom(custom) => &custom.0,
91                })
92                .unwrap();
93            }
94        }
95    }
96
97    fn prepare_index_prefix(&self, create: &IndexCreateStatement, sql: &mut impl SqlWriter) {
98        if create.primary {
99            sql.write_str("PRIMARY ").unwrap();
100        }
101        if create.unique {
102            sql.write_str("UNIQUE ").unwrap();
103        }
104        if matches!(create.index_type, Some(IndexType::FullText)) {
105            sql.write_str("FULLTEXT ").unwrap();
106        }
107    }
108
109    fn prepare_index_columns(&self, columns: &[IndexColumn], sql: &mut impl SqlWriter) {
110        macro_rules! prepare {
111            ($i:ident) => {
112                match $i {
113                    IndexColumn::TableColumn(column) => {
114                        self.prepare_index_column_with_table_column(column, sql);
115                    }
116                    IndexColumn::Expr(column) => {
117                        sql.write_str("(").unwrap();
118                        self.prepare_expr(&column.expr, sql);
119                        sql.write_str(")").unwrap();
120                        if let Some(order) = &column.order {
121                            match order {
122                                IndexOrder::Asc => sql.write_str(" ASC").unwrap(),
123                                IndexOrder::Desc => sql.write_str(" DESC").unwrap(),
124                            }
125                        }
126                    }
127                }
128            };
129        }
130
131        sql.write_str("(").unwrap();
132
133        let mut cols = columns.iter();
134
135        if let Some(col) = cols.next() {
136            prepare!(col)
137        }
138
139        for col in cols {
140            sql.write_str(", ").unwrap();
141            prepare!(col)
142        }
143
144        sql.write_str(")").unwrap();
145    }
146
147    fn prepare_filter(&self, condition: &ConditionHolder, sql: &mut impl SqlWriter) {
148        self.prepare_condition(condition, "WHERE", sql);
149    }
150}