Skip to main content

clorinde/
load_schema.rs

1use std::path::Path;
2
3use miette::NamedSource;
4use tokio_postgres::Client;
5
6use crate::utils::db_err;
7
8use self::error::Error;
9
10#[allow(clippy::result_large_err)]
11/// Loads PostgreSQL schemas into a database.
12///
13/// Takes a list of file paths as parameter and loads them in their given order.
14pub fn load_schema<P: AsRef<Path>>(client: &Client, paths: &[P]) -> Result<(), Error> {
15    for path in paths {
16        let path = path.as_ref();
17        let sql = std::fs::read_to_string(path).map_err(|err| Error::Io {
18            path: path.to_string_lossy().to_string(),
19            err,
20        })?;
21        futures::executor::block_on(client.batch_execute(&sql)).map_err(|err| {
22            let msg = format!("{err:#}");
23            let src = NamedSource::new(path.to_string_lossy(), sql);
24            if let Some((position, msg, help)) = db_err(&err) {
25                Error::Postgres {
26                    msg,
27                    help,
28                    src,
29                    err_span: Some((position as usize..position as usize).into()),
30                }
31            } else {
32                Error::Postgres {
33                    msg,
34                    help: None,
35                    src,
36                    err_span: None,
37                }
38            }
39        })?;
40    }
41    Ok(())
42}
43
44pub(crate) mod error {
45    use miette::{Diagnostic, NamedSource, SourceSpan};
46    use thiserror::Error as ThisError;
47
48    #[derive(Debug, ThisError, Diagnostic)]
49    pub enum Error {
50        #[error("Could not read schema `{path}`: ({err})")]
51        Io { path: String, err: std::io::Error },
52        #[error("Could not execute schema: {msg}")]
53        Postgres {
54            msg: String,
55            #[source_code]
56            src: NamedSource<String>,
57            #[help]
58            help: Option<String>,
59            #[label("error occurs near this location")]
60            err_span: Option<SourceSpan>,
61        },
62    }
63}