1use crate::error::Error;
2
3pub trait CreateIndex<'until_build> {
7 fn unique(self) -> Self;
13
14 fn if_not_exists(self) -> Self;
18
19 fn add_column(self, column: &'until_build str) -> Self;
26
27 fn set_condition(self, condition: String) -> Self;
34
35 fn build(self) -> Result<String, Error>;
39}
40
41pub struct CreateIndexData<'until_build> {
45 pub(crate) name: &'until_build str,
46 pub(crate) table_name: &'until_build str,
47 pub(crate) unique: bool,
48 pub(crate) if_not_exists: bool,
49 pub(crate) columns: Vec<&'until_build str>,
50 pub(crate) condition: Option<String>,
51}
52
53pub enum CreateIndexImpl<'until_build> {
59 #[cfg(feature = "sqlite")]
63 Sqlite(CreateIndexData<'until_build>),
64 #[cfg(feature = "mysql")]
68 MySQL(CreateIndexData<'until_build>),
69 #[cfg(feature = "postgres")]
73 Postgres(CreateIndexData<'until_build>),
74}
75
76impl<'until_build> CreateIndex<'until_build> for CreateIndexImpl<'until_build> {
77 fn unique(mut self) -> Self {
78 match self {
79 #[cfg(feature = "sqlite")]
80 CreateIndexImpl::Sqlite(ref mut d) => d.unique = true,
81 #[cfg(feature = "mysql")]
82 CreateIndexImpl::MySQL(ref mut d) => d.unique = true,
83 #[cfg(feature = "postgres")]
84 CreateIndexImpl::Postgres(ref mut d) => d.unique = true,
85 };
86 self
87 }
88
89 fn if_not_exists(mut self) -> Self {
90 match self {
91 #[cfg(feature = "sqlite")]
92 CreateIndexImpl::Sqlite(ref mut d) => d.if_not_exists = true,
93 #[cfg(feature = "mysql")]
94 CreateIndexImpl::MySQL(ref mut d) => d.if_not_exists = true,
95 #[cfg(feature = "postgres")]
96 CreateIndexImpl::Postgres(ref mut d) => d.if_not_exists = true,
97 };
98 self
99 }
100
101 fn add_column(mut self, column: &'until_build str) -> Self {
102 match self {
103 #[cfg(feature = "sqlite")]
104 CreateIndexImpl::Sqlite(ref mut d) => d.columns.push(column),
105 #[cfg(feature = "mysql")]
106 CreateIndexImpl::MySQL(ref mut d) => d.columns.push(column),
107 #[cfg(feature = "postgres")]
108 CreateIndexImpl::Postgres(ref mut d) => d.columns.push(column),
109 }
110 self
111 }
112
113 fn set_condition(mut self, condition: String) -> Self {
114 match self {
115 #[cfg(feature = "sqlite")]
116 CreateIndexImpl::Sqlite(ref mut d) => d.condition = Some(condition),
117 #[cfg(feature = "mysql")]
118 CreateIndexImpl::MySQL(ref mut d) => d.condition = Some(condition),
119 #[cfg(feature = "postgres")]
120 CreateIndexImpl::Postgres(ref mut d) => d.condition = Some(condition),
121 }
122 self
123 }
124
125 fn build(self) -> Result<String, Error> {
126 match self {
127 #[cfg(feature = "sqlite")]
128 CreateIndexImpl::Sqlite(d) => {
129 if d.columns.is_empty() {
130 return Err(Error::SQLBuildError(format!(
131 "Couldn't create index on {}: Missing column(s) to create the index on",
132 d.table_name
133 )));
134 }
135
136 Ok(format!(
137 "CREATE {} INDEX{} {} ON {} ({}) {};",
138 if d.unique { "UNIQUE" } else { "" },
139 if d.if_not_exists {
140 " IF NOT EXISTS"
141 } else {
142 ""
143 },
144 d.name,
145 d.table_name,
146 d.columns.join(", "),
147 d.condition.as_ref().map_or("", |x| x.as_str()),
148 ))
149 }
150 #[cfg(feature = "mysql")]
151 CreateIndexImpl::MySQL(d) => {
152 if d.columns.is_empty() {
153 return Err(Error::SQLBuildError(format!(
154 "Couldn't create index on {}: Missing column(s) to create the index on",
155 d.table_name
156 )));
157 }
158
159 Ok(format!(
160 "CREATE {} INDEX{} {} ON {} ({});",
161 if d.unique { "UNIQUE" } else { "" },
162 if d.if_not_exists {
163 " IF NOT EXISTS"
164 } else {
165 ""
166 },
167 d.name,
168 d.table_name,
169 d.columns.join(", "),
170 ))
171 }
172 #[cfg(feature = "postgres")]
173 CreateIndexImpl::Postgres(d) => {
174 if d.columns.is_empty() {
175 return Err(Error::SQLBuildError(format!(
176 "Couldn't create index on {}: Missing column(s) to create the index on",
177 d.table_name
178 )));
179 }
180
181 Ok(format!(
182 "CREATE{} INDEX{} {} ON {} ({}){};",
183 if d.unique { " UNIQUE" } else { "" },
184 if d.if_not_exists {
185 " IF NOT EXISTS"
186 } else {
187 ""
188 },
189 d.name,
190 d.table_name,
191 d.columns.join(", "),
192 match d.condition {
193 None => String::from(""),
194 Some(cond) => format!(" WHERE {}", cond.as_str()),
195 }
196 ))
197 }
198 }
199 }
200}