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            sql.write_str("CONSTRAINT ").unwrap();
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_prefix(create, sql);
20
21        if create.nulls_not_distinct {
22            sql.write_str("NULLS NOT DISTINCT ").unwrap();
23        }
24
25        self.prepare_index_columns(&create.index.columns, sql);
26
27        if !create.include_columns.is_empty() {
28            sql.write_str(" ").unwrap();
29            self.prepare_include_columns(&create.include_columns, sql);
30        }
31    }
32
33    fn prepare_index_create_statement(
34        &self,
35        create: &IndexCreateStatement,
36        sql: &mut dyn SqlWriter,
37    ) {
38        sql.write_str("CREATE ").unwrap();
39        self.prepare_index_prefix(create, sql);
40        sql.write_str("INDEX ").unwrap();
41
42        if create.if_not_exists {
43            sql.write_str("IF NOT EXISTS ").unwrap();
44        }
45
46        if let Some(name) = &create.index.name {
47            sql.write_char(self.quote().left()).unwrap();
48            sql.write_str(name).unwrap();
49            sql.write_char(self.quote().right()).unwrap();
50        }
51
52        sql.write_str(" ON ").unwrap();
53        if let Some(table) = &create.table {
54            self.prepare_table_ref_index_stmt(table, sql);
55        }
56
57        self.prepare_index_type(&create.index_type, sql);
58        sql.write_str(" ").unwrap();
59        self.prepare_index_columns(&create.index.columns, sql);
60
61        if !create.include_columns.is_empty() {
62            sql.write_str(" ").unwrap();
63            self.prepare_include_columns(&create.include_columns, sql);
64        }
65
66        if create.nulls_not_distinct {
67            sql.write_str(" NULLS NOT DISTINCT").unwrap();
68        }
69        self.prepare_filter(&create.r#where, sql);
70    }
71
72    fn prepare_table_ref_index_stmt(&self, table_ref: &TableRef, sql: &mut dyn SqlWriter) {
73        // Support only `table` and `schema.table` forms.
74        // No `database.schema.table` or aliases.
75        let TableRef::Table(table_name, None) = table_ref else {
76            panic!("Not supported");
77        };
78        match table_name.as_iden_tuple() {
79            (Some(_db), _schema, _table) => panic!("Not supported"),
80            (None, _schema, _table) => self.prepare_table_ref_iden(table_ref, sql),
81        }
82    }
83
84    fn prepare_index_drop_statement(&self, drop: &IndexDropStatement, sql: &mut dyn SqlWriter) {
85        sql.write_str("DROP INDEX ").unwrap();
86
87        if drop.if_exists {
88            sql.write_str("IF EXISTS ").unwrap();
89        }
90
91        if let Some(table) = &drop.table {
92            // Support only `table` and `schema.table` forms.
93            // No `database.schema.table` or aliases.
94            let TableRef::Table(table_name, None) = table else {
95                panic!("Not supported");
96            };
97            match table_name.as_iden_tuple() {
98                (None, None, _table) => {}
99                (None, Some(schema), _table) => {
100                    self.prepare_iden(schema, sql);
101                    sql.write_str(".").unwrap();
102                }
103                (Some(_db), _schema, _table) => panic!("Not supported"),
104            }
105        }
106        if let Some(name) = &drop.index.name {
107            sql.write_char(self.quote().left()).unwrap();
108            sql.write_str(name).unwrap();
109            sql.write_char(self.quote().right()).unwrap();
110        }
111    }
112
113    fn prepare_index_type(&self, col_index_type: &Option<IndexType>, sql: &mut dyn SqlWriter) {
114        if let Some(index_type) = col_index_type {
115            sql.write_str(" USING ").unwrap();
116            match index_type {
117                IndexType::BTree => sql.write_str("BTREE"),
118                IndexType::FullText => sql.write_str("GIN"),
119                IndexType::Hash => sql.write_str("HASH"),
120                IndexType::Custom(custom) => sql.write_str(&custom.0),
121            }
122            .unwrap()
123        }
124    }
125
126    fn prepare_index_prefix(&self, create: &IndexCreateStatement, sql: &mut dyn SqlWriter) {
127        if create.primary {
128            sql.write_str("PRIMARY KEY ").unwrap();
129        }
130        if create.unique {
131            sql.write_str("UNIQUE ").unwrap();
132        }
133    }
134
135    fn prepare_index_columns(&self, columns: &[IndexColumn], sql: &mut dyn SqlWriter) {
136        sql.write_str("(").unwrap();
137
138        let mut cols = columns.iter();
139        join_io!(
140            cols,
141            col,
142            join {
143                sql.write_str(", ").unwrap();
144            },
145            do {
146                match col {
147                    IndexColumn::TableColumn(column) => {
148                        self.prepare_index_column_with_table_column(column, sql);
149                    }
150                    IndexColumn::Expr(column) => {
151                        sql.write_str("(").unwrap();
152                        self.prepare_simple_expr(&column.expr, sql);
153                        sql.write_str(")").unwrap();
154                        if let Some(order) = &column.order {
155                            match order {
156                                IndexOrder::Asc => sql.write_str(" ASC").unwrap(),
157                                IndexOrder::Desc => sql.write_str(" DESC").unwrap(),
158                            }
159                        }
160                    }
161                }
162            }
163        );
164
165        sql.write_str(")").unwrap();
166    }
167
168    fn prepare_filter(&self, condition: &ConditionHolder, sql: &mut dyn SqlWriter) {
169        self.prepare_condition(condition, "WHERE", sql);
170    }
171}
172
173impl PostgresQueryBuilder {
174    fn prepare_include_columns(&self, columns: &[DynIden], sql: &mut dyn SqlWriter) {
175        sql.write_str("INCLUDE (").unwrap();
176
177        let mut cols = columns.iter();
178        join_io!(
179            cols,
180            col,
181            join {
182                sql.write_str(", ").unwrap();
183            },
184            do {
185                self.prepare_iden(col, sql);
186            }
187        );
188
189        sql.write_str(")").unwrap();
190    }
191}