systemprompt_database/services/
executor.rs1use super::database::Database;
11use super::provider::DatabaseProvider;
12use crate::error::{DatabaseResult, RepositoryError};
13use crate::models::QueryResult;
14
15#[derive(Debug, Copy, Clone)]
16pub struct SqlExecutor;
17
18impl SqlExecutor {
19 pub async fn execute_statements(db: &Database, sql: &str) -> DatabaseResult<()> {
20 db.execute_batch(sql).await
21 }
22
23 pub async fn execute_statements_parsed(
24 db: &dyn DatabaseProvider,
25 sql: &str,
26 ) -> DatabaseResult<()> {
27 for statement in Self::parse_sql_statements(sql)? {
28 db.execute_raw(&statement)
29 .await
30 .map_err(|source| RepositoryError::Statement {
31 statement: statement.clone(),
32 source: Box::new(source),
33 })?;
34 }
35 Ok(())
36 }
37
38 pub fn parse_sql_statements(sql: &str) -> DatabaseResult<Vec<String>> {
39 let statements =
40 pg_query::split_with_parser(sql).map_err(|e| RepositoryError::SqlParse(Box::new(e)))?;
41 Ok(statements
42 .into_iter()
43 .map(str::trim)
44 .filter(|s| !s.is_empty())
45 .map(str::to_owned)
46 .collect())
47 }
48
49 pub async fn execute_query(db: &Database, query: &str) -> DatabaseResult<QueryResult> {
50 db.query_raw(&query).await
51 }
52
53 pub async fn execute_file(db: &Database, file_path: &str) -> DatabaseResult<()> {
54 let sql = tokio::fs::read_to_string(file_path)
55 .await
56 .map_err(|source| RepositoryError::SqlFile {
57 path: file_path.to_owned(),
58 source,
59 })?;
60 Self::execute_statements(db, &sql).await
61 }
62}