multisql/glue/
select.rs

1use {
2	super::Glue,
3	crate::{Cast, ExecuteError, Payload, Result},
4	serde_json::value::Value as JSONValue,
5};
6
7/// ## Select (`SELECT`)
8impl Glue {
9	/// Only for `SELECT` queries.
10	///
11	/// Output is one big [serde_json::Value], wrapped in a [Result].
12	///
13	/// Generally useful for webby interactions.
14	pub fn select_json(&mut self, query: &str) -> Result<JSONValue> {
15		// TODO: Make this more efficient and not affect database if not select by converting earlier
16		if let Payload::Select { labels, rows } = self.execute(query)? {
17			let rows = JSONValue::Array(
18				rows.into_iter()
19					.map(|row| {
20						JSONValue::Object(
21							row.0
22								.into_iter()
23								.enumerate()
24								.map(|(index, cell)| (labels[index].clone(), cell.into()))
25								.collect::<serde_json::map::Map<String, JSONValue>>(),
26						)
27					})
28					.collect(),
29			);
30			Ok(rows)
31		} else {
32			Err(ExecuteError::QueryNotSupported.into())
33		}
34	}
35
36	/// Only for `SELECT` queries.
37	pub fn select_as_string(&mut self, query: &str) -> Result<Vec<Vec<String>>> {
38		// TODO: Make this more efficient and not affect database
39		if let Payload::Select { labels, rows } = self.execute(query)? {
40			Ok(vec![labels]
41				.into_iter()
42				.chain(
43					rows.into_iter()
44						.map(|row| {
45							row.0
46								.into_iter()
47								.map(|value| value.cast())
48								.collect::<Result<Vec<String>>>()
49						})
50						.collect::<Result<Vec<Vec<String>>>>()?,
51				)
52				.collect())
53		} else {
54			Err(ExecuteError::QueryNotSupported.into())
55		}
56	}
57
58	/// Only for `SELECT` queries.
59	pub fn select_as_csv(&mut self, query: &str) -> Result<String> {
60		// TODO: Don't use `unwrap()`
61		if let Payload::Select { labels, rows } = self.execute(query)? {
62			{
63				let mut writer = csv::Writer::from_writer(vec![]);
64				writer.write_record(labels).unwrap();
65				for row in rows.into_iter() {
66					for field in row.0.into_iter() {
67						let string: String = field.cast()?;
68						writer.write_field(string).unwrap();
69					}
70					writer.write_record(None::<&[u8]>).unwrap();
71				}
72				let bytes = writer.into_inner().unwrap();
73				let string = String::from_utf8(bytes).unwrap();
74				Some(string)
75			}
76			.map(Ok)
77			.unwrap()
78		} else {
79			Err(ExecuteError::QueryNotSupported.into())
80		}
81	}
82}