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