gluesql_core/executor/
fetch.rs1use {
2 super::{context::RowContext, filter::check_expr},
3 crate::{
4 data::{Key, Row, SCHEMALESS_DOC_COLUMN},
5 plan::ExprPlan,
6 result::Result,
7 store::GStore,
8 },
9 serde::Serialize,
10 std::{borrow::Cow, fmt::Debug, rc::Rc},
11 thiserror::Error as ThisError,
12};
13
14pub type KeyedRows<'a> = Box<dyn Iterator<Item = Result<(Key, Row)>> + 'a>;
15
16#[derive(ThisError, Serialize, Debug, PartialEq, Eq)]
17pub enum FetchError {
18 #[error("table not found: {0}")]
19 TableNotFound(String),
20}
21
22pub fn fetch<'a, T: GStore>(
23 storage: &'a T,
24 table_name: &'a str,
25 columns: Rc<[String]>,
26 where_clause: Option<&'a ExprPlan>,
27) -> Result<KeyedRows<'a>> {
28 let rows = storage.scan_data(table_name)?.filter_map(move |row| {
29 let (key, values) = match row {
30 Ok(row) => row,
31 Err(error) => return Some(Err(error)),
32 };
33 let row = Row {
34 columns: Rc::clone(&columns),
35 values,
36 };
37
38 match where_clause {
39 Some(expr) => {
40 let context = RowContext::new(table_name, Cow::Borrowed(&row), None);
41 let context = Rc::new(context);
42 match check_expr(storage, Some(&context), None, expr) {
43 Ok(true) => Some(Ok((key, row))),
44 Ok(false) => None,
45 Err(error) => Some(Err(error)),
46 }
47 }
48 None => Some(Ok((key, row))),
49 }
50 });
51
52 Ok(Box::new(rows))
53}
54
55pub fn fetch_columns<T: GStore>(storage: &T, table_name: &str) -> Result<Vec<String>> {
56 let columns = storage
57 .fetch_schema(table_name)?
58 .ok_or_else(|| FetchError::TableNotFound(table_name.to_owned()))?
59 .column_defs
60 .map_or_else(
61 || vec![SCHEMALESS_DOC_COLUMN.to_owned()],
62 |column_defs| {
63 column_defs
64 .into_iter()
65 .map(|column_def| column_def.name)
66 .collect()
67 },
68 );
69
70 Ok(columns)
71}