1use crate::mysql::def::*;
2use crate::mysql::query::IndexQueryResult;
3use crate::Name;
4
5pub struct IndexQueryResultParser {
6 curr: Option<IndexInfo>,
7 results: Box<dyn Iterator<Item = IndexQueryResult>>,
8}
9
10pub fn parse_index_query_results(
12 results: Box<dyn Iterator<Item = IndexQueryResult>>,
13) -> impl Iterator<Item = IndexInfo> {
14 IndexQueryResultParser {
15 curr: None,
16 results,
17 }
18}
19
20impl Iterator for IndexQueryResultParser {
21 type Item = IndexInfo;
22
23 fn next(&mut self) -> Option<Self::Item> {
24 for result in self.results.by_ref() {
25 let mut index = parse_index_query_result(result);
26 if let Some(curr) = &mut self.curr {
27 if curr.name == index.name {
29 curr.parts.push(index.parts.pop().unwrap());
30 curr.functional |= index.functional;
31 } else {
32 let prev = self.curr.take();
33 self.curr = Some(index);
34 return prev;
35 }
36 } else {
37 self.curr = Some(index);
38 }
39 }
40 self.curr.take()
41 }
42}
43
44pub fn parse_index_query_result(mut result: IndexQueryResult) -> IndexInfo {
45 IndexInfo {
46 unique: match result.non_unique {
47 0 => true,
48 1 => false,
49 _ => unimplemented!(),
50 },
51 name: result.index_name,
52 parts: vec![IndexPart {
53 column: if result.column_name.is_some() {
54 result.column_name.take().unwrap()
55 } else if result.expression.is_some() {
56 result.expression.take().unwrap()
57 } else {
58 panic!("index column error")
59 },
60 order: match result.collation {
61 Some(collation) => match collation.as_str() {
62 "A" => IndexOrder::Ascending,
63 "D" => IndexOrder::Descending,
64 _ => unimplemented!(),
65 },
66 None => IndexOrder::Unordered,
67 },
68 sub_part: result.sub_part.map(|v| v as u32),
69 }],
70 nullable: matches!(result.nullable.as_str(), "YES"),
71 idx_type: IndexType::from_str(result.index_type.as_str()).unwrap(),
72 comment: result.index_comment,
73 functional: result.expression.is_some(),
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn test_1() {
83 assert_eq!(
84 parse_index_query_results(Box::new(
85 vec![IndexQueryResult {
86 non_unique: 0,
87 index_name: "PRIMARY".to_owned(),
88 column_name: Some("film_id".to_owned()),
89 collation: Some("A".to_owned()),
90 sub_part: None,
91 nullable: "".to_owned(),
92 index_type: "BTREE".to_owned(),
93 index_comment: "".to_owned(),
94 expression: None
95 }]
96 .into_iter()
97 ))
98 .collect::<Vec<IndexInfo>>(),
99 vec![IndexInfo {
100 unique: true,
101 name: "PRIMARY".to_owned(),
102 parts: vec![IndexPart {
103 column: "film_id".to_owned(),
104 order: IndexOrder::Ascending,
105 sub_part: None,
106 },],
107 nullable: false,
108 idx_type: IndexType::BTree,
109 comment: "".to_owned(),
110 functional: false,
111 }]
112 );
113 }
114
115 #[test]
116 fn test_2() {
117 assert_eq!(
118 parse_index_query_results(Box::new(
119 vec![IndexQueryResult {
120 non_unique: 1,
121 index_name: "idx_title".to_owned(),
122 column_name: Some("title".to_owned()),
123 collation: Some("A".to_owned()),
124 sub_part: None,
125 nullable: "".to_owned(),
126 index_type: "BTREE".to_owned(),
127 index_comment: "".to_owned(),
128 expression: None
129 }]
130 .into_iter()
131 ))
132 .collect::<Vec<IndexInfo>>(),
133 vec![IndexInfo {
134 unique: false,
135 name: "idx_title".to_owned(),
136 parts: vec![IndexPart {
137 column: "title".to_owned(),
138 order: IndexOrder::Ascending,
139 sub_part: None,
140 },],
141 nullable: false,
142 idx_type: IndexType::BTree,
143 comment: "".to_owned(),
144 functional: false,
145 }]
146 );
147 }
148
149 #[test]
150 fn test_3() {
151 assert_eq!(
152 parse_index_query_results(Box::new(
153 vec![
154 IndexQueryResult {
155 non_unique: 0,
156 index_name: "rental_date".to_owned(),
157 column_name: Some("rental_date".to_owned()),
158 collation: Some("A".to_owned()),
159 sub_part: None,
160 nullable: "".to_owned(),
161 index_type: "BTREE".to_owned(),
162 index_comment: "".to_owned(),
163 expression: None
164 },
165 IndexQueryResult {
166 non_unique: 0,
167 index_name: "rental_date".to_owned(),
168 column_name: Some("inventory_id".to_owned()),
169 collation: Some("D".to_owned()),
170 sub_part: None,
171 nullable: "".to_owned(),
172 index_type: "BTREE".to_owned(),
173 index_comment: "".to_owned(),
174 expression: None
175 },
176 IndexQueryResult {
177 non_unique: 0,
178 index_name: "rental_date".to_owned(),
179 column_name: Some("customer_id".to_owned()),
180 collation: Some("A".to_owned()),
181 sub_part: None,
182 nullable: "".to_owned(),
183 index_type: "BTREE".to_owned(),
184 index_comment: "".to_owned(),
185 expression: None
186 },
187 ]
188 .into_iter()
189 ))
190 .collect::<Vec<IndexInfo>>(),
191 vec![IndexInfo {
192 unique: true,
193 name: "rental_date".to_owned(),
194 parts: vec![
195 IndexPart {
196 column: "rental_date".to_owned(),
197 order: IndexOrder::Ascending,
198 sub_part: None,
199 },
200 IndexPart {
201 column: "inventory_id".to_owned(),
202 order: IndexOrder::Descending,
203 sub_part: None,
204 },
205 IndexPart {
206 column: "customer_id".to_owned(),
207 order: IndexOrder::Ascending,
208 sub_part: None,
209 },
210 ],
211 nullable: false,
212 idx_type: IndexType::BTree,
213 comment: "".to_owned(),
214 functional: false
215 }]
216 );
217 }
218
219 #[test]
220 fn test_4() {
221 assert_eq!(
222 parse_index_query_results(Box::new(
223 vec![IndexQueryResult {
224 non_unique: 1,
225 index_name: "idx_location".to_owned(),
226 column_name: Some("location".to_owned()),
227 collation: Some("A".to_owned()),
228 sub_part: Some(32),
229 nullable: "".to_owned(),
230 index_type: "SPATIAL".to_owned(),
231 index_comment: "".to_owned(),
232 expression: None
233 }]
234 .into_iter()
235 ))
236 .collect::<Vec<IndexInfo>>(),
237 vec![IndexInfo {
238 unique: false,
239 name: "idx_location".to_owned(),
240 parts: vec![IndexPart {
241 column: "location".to_owned(),
242 order: IndexOrder::Ascending,
243 sub_part: Some(32),
244 },],
245 nullable: false,
246 idx_type: IndexType::Spatial,
247 comment: "".to_owned(),
248 functional: false,
249 }]
250 );
251 }
252}