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 = "postgres")]
68 Postgres(CreateIndexData<'until_build>),
69}
70
71impl<'until_build> CreateIndex<'until_build> for CreateIndexImpl<'until_build> {
72 fn unique(mut self) -> Self {
73 match self {
74 #[cfg(feature = "sqlite")]
75 CreateIndexImpl::Sqlite(ref mut d) => d.unique = true,
76 #[cfg(feature = "postgres")]
77 CreateIndexImpl::Postgres(ref mut d) => d.unique = true,
78 };
79 self
80 }
81
82 fn if_not_exists(mut self) -> Self {
83 match self {
84 #[cfg(feature = "sqlite")]
85 CreateIndexImpl::Sqlite(ref mut d) => d.if_not_exists = true,
86 #[cfg(feature = "postgres")]
87 CreateIndexImpl::Postgres(ref mut d) => d.if_not_exists = true,
88 };
89 self
90 }
91
92 fn add_column(mut self, column: &'until_build str) -> Self {
93 match self {
94 #[cfg(feature = "sqlite")]
95 CreateIndexImpl::Sqlite(ref mut d) => d.columns.push(column),
96 #[cfg(feature = "postgres")]
97 CreateIndexImpl::Postgres(ref mut d) => d.columns.push(column),
98 }
99 self
100 }
101
102 fn set_condition(mut self, condition: String) -> Self {
103 match self {
104 #[cfg(feature = "sqlite")]
105 CreateIndexImpl::Sqlite(ref mut d) => d.condition = Some(condition),
106 #[cfg(feature = "postgres")]
107 CreateIndexImpl::Postgres(ref mut d) => d.condition = Some(condition),
108 }
109 self
110 }
111
112 fn build(self) -> Result<String, Error> {
113 match self {
114 #[cfg(feature = "sqlite")]
115 CreateIndexImpl::Sqlite(d) => {
116 if d.columns.is_empty() {
117 return Err(Error::SQLBuildError(format!(
118 "Couldn't create index on {}: Missing column(s) to create the index on",
119 d.table_name
120 )));
121 }
122
123 Ok(format!(
124 "CREATE {} INDEX{} {} ON {} ({}) {};",
125 if d.unique { "UNIQUE" } else { "" },
126 if d.if_not_exists {
127 " IF NOT EXISTS"
128 } else {
129 ""
130 },
131 d.name,
132 d.table_name,
133 d.columns.join(", "),
134 d.condition.as_ref().map_or("", |x| x.as_str()),
135 ))
136 }
137 #[cfg(feature = "postgres")]
138 CreateIndexImpl::Postgres(d) => {
139 if d.columns.is_empty() {
140 return Err(Error::SQLBuildError(format!(
141 "Couldn't create index on {}: Missing column(s) to create the index on",
142 d.table_name
143 )));
144 }
145
146 Ok(format!(
147 "CREATE{} INDEX{} {} ON {} ({}){};",
148 if d.unique { " UNIQUE" } else { "" },
149 if d.if_not_exists {
150 " IF NOT EXISTS"
151 } else {
152 ""
153 },
154 d.name,
155 d.table_name,
156 d.columns.join(", "),
157 match d.condition {
158 None => String::from(""),
159 Some(cond) => format!(" WHERE {}", cond.as_str()),
160 }
161 ))
162 }
163 }
164 }
165}