manifoldb_query/exec/
result.rs1use std::sync::Arc;
6
7use manifoldb_core::Value;
8
9use super::row::{Row, Schema};
10
11#[derive(Debug)]
13pub enum QueryResult {
14 Select(ResultSet),
16 Affected(u64),
18 Empty,
20}
21
22impl QueryResult {
23 #[must_use]
25 pub fn select(result_set: ResultSet) -> Self {
26 Self::Select(result_set)
27 }
28
29 #[must_use]
31 pub const fn affected(count: u64) -> Self {
32 Self::Affected(count)
33 }
34
35 #[must_use]
37 pub const fn empty() -> Self {
38 Self::Empty
39 }
40
41 #[must_use]
43 pub const fn is_select(&self) -> bool {
44 matches!(self, Self::Select(_))
45 }
46
47 #[must_use]
49 pub fn as_select(&self) -> Option<&ResultSet> {
50 match self {
51 Self::Select(rs) => Some(rs),
52 _ => None,
53 }
54 }
55
56 #[must_use]
58 pub fn into_select(self) -> Option<ResultSet> {
59 match self {
60 Self::Select(rs) => Some(rs),
61 _ => None,
62 }
63 }
64
65 #[must_use]
67 pub const fn affected_rows(&self) -> Option<u64> {
68 match self {
69 Self::Affected(n) => Some(*n),
70 _ => None,
71 }
72 }
73}
74
75#[derive(Debug, Clone)]
77pub struct ResultSet {
78 schema: Arc<Schema>,
80 rows: Vec<Row>,
82}
83
84impl ResultSet {
85 #[must_use]
87 pub fn new(schema: Arc<Schema>) -> Self {
88 Self { schema, rows: Vec::new() }
89 }
90
91 #[must_use]
93 pub fn with_rows(schema: Arc<Schema>, rows: Vec<Row>) -> Self {
94 Self { schema, rows }
95 }
96
97 #[must_use]
99 pub fn schema(&self) -> &Schema {
100 &self.schema
101 }
102
103 #[must_use]
105 pub fn schema_arc(&self) -> Arc<Schema> {
106 Arc::clone(&self.schema)
107 }
108
109 #[must_use]
111 pub fn columns(&self) -> Vec<&str> {
112 self.schema.columns()
113 }
114
115 #[must_use]
117 pub fn rows(&self) -> &[Row] {
118 &self.rows
119 }
120
121 #[must_use]
123 pub fn len(&self) -> usize {
124 self.rows.len()
125 }
126
127 #[must_use]
129 pub fn is_empty(&self) -> bool {
130 self.rows.is_empty()
131 }
132
133 pub fn push(&mut self, row: Row) {
135 self.rows.push(row);
136 }
137
138 #[must_use]
140 pub fn get(&self, index: usize) -> Option<&Row> {
141 self.rows.get(index)
142 }
143
144 #[must_use]
146 pub fn into_rows(self) -> Vec<Row> {
147 self.rows
148 }
149
150 pub fn iter(&self) -> impl Iterator<Item = &Row> {
152 self.rows.iter()
153 }
154
155 #[must_use]
157 pub fn to_values(&self) -> Vec<Vec<Value>> {
158 self.rows.iter().map(|r| r.values().to_vec()).collect()
159 }
160}
161
162impl IntoIterator for ResultSet {
163 type Item = Row;
164 type IntoIter = std::vec::IntoIter<Row>;
165
166 fn into_iter(self) -> Self::IntoIter {
167 self.rows.into_iter()
168 }
169}
170
171impl<'a> IntoIterator for &'a ResultSet {
172 type Item = &'a Row;
173 type IntoIter = std::slice::Iter<'a, Row>;
174
175 fn into_iter(self) -> Self::IntoIter {
176 self.rows.iter()
177 }
178}
179
180pub struct ResultSetBuilder {
184 schema: Arc<Schema>,
185 rows: Vec<Row>,
186}
187
188impl ResultSetBuilder {
189 #[must_use]
191 pub fn new(schema: Arc<Schema>) -> Self {
192 Self { schema, rows: Vec::new() }
193 }
194
195 #[must_use]
197 pub fn with_capacity(schema: Arc<Schema>, capacity: usize) -> Self {
198 Self { schema, rows: Vec::with_capacity(capacity) }
199 }
200
201 pub fn push(&mut self, row: Row) {
203 self.rows.push(row);
204 }
205
206 pub fn push_values(&mut self, values: Vec<Value>) {
208 let row = Row::new(Arc::clone(&self.schema), values);
209 self.rows.push(row);
210 }
211
212 #[must_use]
214 pub fn len(&self) -> usize {
215 self.rows.len()
216 }
217
218 #[must_use]
220 pub fn is_empty(&self) -> bool {
221 self.rows.is_empty()
222 }
223
224 #[must_use]
226 pub fn build(self) -> ResultSet {
227 ResultSet::with_rows(self.schema, self.rows)
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234
235 #[test]
236 fn query_result_types() {
237 let result = QueryResult::affected(5);
238 assert!(!result.is_select());
239 assert_eq!(result.affected_rows(), Some(5));
240
241 let schema = Arc::new(Schema::new(vec!["id".to_string()]));
242 let result = QueryResult::select(ResultSet::new(schema));
243 assert!(result.is_select());
244 assert_eq!(result.affected_rows(), None);
245 }
246
247 #[test]
248 fn result_set_basic() {
249 let schema = Arc::new(Schema::new(vec!["id".to_string(), "name".to_string()]));
250 let mut rs = ResultSet::new(Arc::clone(&schema));
251
252 rs.push(Row::new(Arc::clone(&schema), vec![Value::Int(1), Value::from("Alice")]));
253 rs.push(Row::new(Arc::clone(&schema), vec![Value::Int(2), Value::from("Bob")]));
254
255 assert_eq!(rs.len(), 2);
256 assert_eq!(rs.columns(), &["id", "name"]);
257 assert_eq!(rs.get(0).and_then(|r| r.get(0)), Some(&Value::Int(1)));
258 }
259
260 #[test]
261 fn result_set_builder() {
262 let schema = Arc::new(Schema::new(vec!["x".to_string()]));
263 let mut builder = ResultSetBuilder::new(Arc::clone(&schema));
264
265 builder.push_values(vec![Value::Int(1)]);
266 builder.push_values(vec![Value::Int(2)]);
267
268 let rs = builder.build();
269 assert_eq!(rs.len(), 2);
270 }
271
272 #[test]
273 fn result_set_iterator() {
274 let schema = Arc::new(Schema::new(vec!["n".to_string()]));
275 let rs = ResultSet::with_rows(
276 Arc::clone(&schema),
277 vec![
278 Row::new(Arc::clone(&schema), vec![Value::Int(1)]),
279 Row::new(Arc::clone(&schema), vec![Value::Int(2)]),
280 ],
281 );
282
283 let sum: i64 = rs
284 .iter()
285 .filter_map(|r| match r.get(0) {
286 Some(Value::Int(n)) => Some(*n),
287 _ => None,
288 })
289 .sum();
290
291 assert_eq!(sum, 3);
292 }
293}