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 = pg_query::split_with_parser(sql).map_err(RepositoryError::SqlSplit)?;
40 Ok(statements
41 .into_iter()
42 .map(str::trim)
43 .filter(|s| !s.is_empty())
44 .map(str::to_owned)
45 .collect())
46 }
47
48 pub async fn execute_query(db: &Database, query: &str) -> DatabaseResult<QueryResult> {
49 db.query_raw(&query)
50 .await
51 .map_err(|e| RepositoryError::QueryExecution(Box::new(e)))
52 }
53
54 pub async fn execute_file(db: &Database, file_path: &str) -> DatabaseResult<()> {
55 let sql = tokio::fs::read_to_string(file_path)
56 .await
57 .map_err(|source| RepositoryError::SqlFile {
58 path: file_path.to_owned(),
59 source,
60 })?;
61 Self::execute_statements(db, &sql).await
62 }
63}