gluesql_file_storage/
store.rs

1use {
2    crate::{FileRow, FileStorage, ResultExt},
3    async_trait::async_trait,
4    futures::stream::iter,
5    gluesql_core::{
6        data::{Key, Schema},
7        error::Result,
8        store::{DataRow, RowIter, Store},
9    },
10    std::{ffi::OsStr, fs},
11};
12
13#[async_trait(?Send)]
14impl Store for FileStorage {
15    async fn fetch_all_schemas(&self) -> Result<Vec<Schema>> {
16        let mut schemas = fs::read_dir(&self.path)
17            .map_storage_err()?
18            .map(|dir_entry| {
19                let dir_entry = dir_entry.map_storage_err()?;
20                let file_type = dir_entry.file_type().map_storage_err()?;
21                let path = dir_entry.path();
22                let extension = path.extension().and_then(OsStr::to_str);
23                if file_type.is_dir() || extension != Some("sql") {
24                    return Ok(None);
25                }
26
27                self.fetch_schema(path).map(Some)
28            })
29            .filter_map(Result::transpose)
30            .collect::<Result<Vec<Schema>>>()?;
31
32        schemas.sort_by(|a, b| a.table_name.cmp(&b.table_name));
33
34        Ok(schemas)
35    }
36
37    async fn fetch_schema(&self, table_name: &str) -> Result<Option<Schema>> {
38        let path = self.path(table_name).with_extension("sql");
39        if !path.exists() {
40            return Ok(None);
41        }
42
43        self.fetch_schema(path).map(Some)
44    }
45
46    async fn fetch_data(&self, table_name: &str, key: &Key) -> Result<Option<DataRow>> {
47        let path = self.data_path(table_name, key)?;
48        if !path.exists() {
49            return Ok(None);
50        }
51
52        fs::read_to_string(path)
53            .map_storage_err()
54            .and_then(|data| {
55                ron::from_str(&data)
56                    .map_storage_err()
57                    .map(|FileRow { row, .. }| row)
58            })
59            .map(Some)
60    }
61
62    async fn scan_data(&self, table_name: &str) -> Result<RowIter> {
63        let path = self.path(table_name);
64        let mut entries = fs::read_dir(path)
65            .map_storage_err()?
66            .map(|dir_entry| {
67                let dir_entry = dir_entry.map_storage_err()?;
68                let file_type = dir_entry.file_type().map_storage_err()?;
69                let path = dir_entry.path();
70                let extension = path.extension().and_then(OsStr::to_str);
71                if file_type.is_dir() || extension != Some("ron") {
72                    return Ok(None);
73                }
74
75                Ok(Some(path))
76            })
77            .filter_map(Result::transpose)
78            .collect::<Result<Vec<_>>>()?;
79
80        entries.sort();
81
82        let rows = entries.into_iter().map(|path| {
83            let data = fs::read_to_string(path).map_storage_err()?;
84
85            ron::from_str(&data)
86                .map_storage_err()
87                .map(|FileRow { key, row }| (key, row))
88        });
89
90        Ok(Box::pin(iter(rows)))
91    }
92}