sea_query/backend/postgres/
index.rs

1use super::*;
2
3impl IndexBuilder for PostgresQueryBuilder {
4    // Overriden due to different "NULLS NOT UNIQUE" position in table index expression
5    // (as opposed to the regular index expression)
6    fn prepare_table_index_expression(
7        &self,
8        create: &IndexCreateStatement,
9        sql: &mut dyn SqlWriter,
10    ) {
11        if let Some(name) = &create.index.name {
12            write!(
13                sql,
14                "CONSTRAINT {}{}{} ",
15                self.quote().left(),
16                name,
17                self.quote().right()
18            )
19            .unwrap();
20        }
21
22        self.prepare_index_prefix(create, sql);
23
24        if create.nulls_not_distinct {
25            write!(sql, "NULLS NOT DISTINCT ").unwrap();
26        }
27
28        self.prepare_index_columns(&create.index.columns, sql);
29
30        if !create.include_columns.is_empty() {
31            write!(sql, " ").unwrap();
32            self.prepare_include_columns(&create.include_columns, sql);
33        }
34    }
35
36    fn prepare_index_create_statement(
37        &self,
38        create: &IndexCreateStatement,
39        sql: &mut dyn SqlWriter,
40    ) {
41        write!(sql, "CREATE ").unwrap();
42        self.prepare_index_prefix(create, sql);
43        write!(sql, "INDEX ").unwrap();
44
45        if create.if_not_exists {
46            write!(sql, "IF NOT EXISTS ").unwrap();
47        }
48
49        if let Some(name) = &create.index.name {
50            write!(
51                sql,
52                "{}{}{}",
53                self.quote().left(),
54                name,
55                self.quote().right()
56            )
57            .unwrap();
58        }
59
60        write!(sql, " ON ").unwrap();
61        if let Some(table) = &create.table {
62            self.prepare_table_ref_index_stmt(table, sql);
63        }
64
65        self.prepare_index_type(&create.index_type, sql);
66        write!(sql, " ").unwrap();
67        self.prepare_index_columns(&create.index.columns, sql);
68
69        if !create.include_columns.is_empty() {
70            write!(sql, " ").unwrap();
71            self.prepare_include_columns(&create.include_columns, sql);
72        }
73
74        if create.nulls_not_distinct {
75            write!(sql, " NULLS NOT DISTINCT").unwrap();
76        }
77        self.prepare_filter(&create.r#where, sql);
78    }
79
80    fn prepare_table_ref_index_stmt(&self, table_ref: &TableRef, sql: &mut dyn SqlWriter) {
81        match table_ref {
82            TableRef::Table(_) | TableRef::SchemaTable(_, _) => {
83                self.prepare_table_ref_iden(table_ref, sql)
84            }
85            _ => panic!("Not supported"),
86        }
87    }
88
89    fn prepare_index_drop_statement(&self, drop: &IndexDropStatement, sql: &mut dyn SqlWriter) {
90        write!(sql, "DROP INDEX ").unwrap();
91
92        if drop.if_exists {
93            write!(sql, "IF EXISTS ").unwrap();
94        }
95
96        if let Some(table) = &drop.table {
97            match table {
98                TableRef::Table(_) => {}
99                TableRef::SchemaTable(schema, _) => {
100                    schema.prepare(sql.as_writer(), self.quote());
101                    write!(sql, ".").unwrap();
102                }
103                _ => panic!("Not supported"),
104            }
105        }
106        if let Some(name) = &drop.index.name {
107            write!(
108                sql,
109                "{}{}{}",
110                self.quote().left(),
111                name,
112                self.quote().right()
113            )
114            .unwrap();
115        }
116    }
117
118    fn prepare_index_type(&self, col_index_type: &Option<IndexType>, sql: &mut dyn SqlWriter) {
119        if let Some(index_type) = col_index_type {
120            write!(
121                sql,
122                " USING {}",
123                match index_type {
124                    IndexType::BTree => "BTREE".to_owned(),
125                    IndexType::FullText => "GIN".to_owned(),
126                    IndexType::Hash => "HASH".to_owned(),
127                    IndexType::Custom(custom) => custom.to_string(),
128                }
129            )
130            .unwrap();
131        }
132    }
133
134    fn prepare_index_prefix(&self, create: &IndexCreateStatement, sql: &mut dyn SqlWriter) {
135        if create.primary {
136            write!(sql, "PRIMARY KEY ").unwrap();
137        }
138        if create.unique {
139            write!(sql, "UNIQUE ").unwrap();
140        }
141    }
142
143    fn prepare_index_columns(&self, columns: &[IndexColumn], sql: &mut dyn SqlWriter) {
144        write!(sql, "(").unwrap();
145        columns.iter().fold(true, |first, col| {
146            if !first {
147                write!(sql, ", ").unwrap();
148            }
149            match col {
150                IndexColumn::TableColumn(column) => {
151                    self.prepare_index_column_with_table_column(column, sql);
152                }
153                IndexColumn::Expr(column) => {
154                    write!(sql, "(").unwrap();
155                    self.prepare_simple_expr(&column.expr, sql);
156                    write!(sql, ")").unwrap();
157                    if let Some(order) = &column.order {
158                        match order {
159                            IndexOrder::Asc => write!(sql, " ASC").unwrap(),
160                            IndexOrder::Desc => write!(sql, " DESC").unwrap(),
161                        }
162                    }
163                }
164            }
165            false
166        });
167        write!(sql, ")").unwrap();
168    }
169
170    fn prepare_filter(&self, condition: &ConditionHolder, sql: &mut dyn SqlWriter) {
171        self.prepare_condition(condition, "WHERE", sql);
172    }
173}
174
175impl PostgresQueryBuilder {
176    fn prepare_include_columns(&self, columns: &[SeaRc<dyn Iden>], sql: &mut dyn SqlWriter) {
177        write!(sql, "INCLUDE (").unwrap();
178        columns.iter().fold(true, |first, col| {
179            if !first {
180                write!(sql, ", ").unwrap();
181            }
182            col.prepare(sql.as_writer(), self.quote());
183            false
184        });
185        write!(sql, ")").unwrap();
186    }
187}