atomr_persistence_sql/
schema.rs1use atomr_persistence::JournalError;
7use sqlx::AnyPool;
8
9use crate::config::{SqlConfig, SqlDialect};
10
11pub(crate) fn init_drivers() {
13 sqlx::any::install_default_drivers();
14}
15
16pub async fn ensure_schema(pool: &AnyPool, cfg: &SqlConfig) -> Result<(), JournalError> {
19 if !cfg.auto_migrate {
20 return Ok(());
21 }
22 let ddl = crate::dialect::migration_for(cfg.dialect);
23 for stmt in split_statements(ddl) {
24 sqlx::query(&stmt).execute(pool).await.map_err(JournalError::backend)?;
25 }
26 let worm_ddl = crate::dialect::worm_migration_for(cfg.dialect);
31 for stmt in split_statements(worm_ddl) {
32 if let Err(e) = sqlx::query(&stmt).execute(pool).await {
33 let msg = e.to_string().to_ascii_lowercase();
34 let already_applied = msg.contains("duplicate column")
35 || msg.contains("already exists")
36 || msg.contains("duplicate")
37 || msg.contains("exists");
38 if !already_applied {
39 return Err(JournalError::backend(e));
40 }
41 }
42 }
43 Ok(())
44}
45
46pub(crate) async fn install_worm_triggers(pool: &AnyPool, cfg: &SqlConfig) -> Result<(), JournalError> {
51 let ddl = crate::dialect::worm_deny_trigger_for(cfg.dialect);
52 for stmt in ddl.split("@@").map(str::trim).filter(|s| !s.is_empty()) {
54 sqlx::query(stmt).execute(pool).await.map_err(JournalError::backend)?;
55 }
56 Ok(())
57}
58
59fn split_statements(ddl: &str) -> Vec<String> {
60 let stripped: String =
61 ddl.lines().map(|l| l.split("--").next().unwrap_or("")).collect::<Vec<_>>().join("\n");
62 stripped.split(';').map(str::trim).filter(|s| !s.is_empty()).map(|s| s.to_string()).collect()
63}
64
65#[allow(dead_code)]
68pub async fn truncate(pool: &AnyPool, _dialect: SqlDialect) -> Result<(), JournalError> {
69 for table in ["event_tags", "event_journal", "snapshot_store"] {
70 sqlx::query(&format!("DELETE FROM {table}")).execute(pool).await.map_err(JournalError::backend)?;
71 }
72 Ok(())
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn splitter_skips_blank_and_comments() {
81 let sql = "-- hello\nCREATE TABLE a (id INT);\n\nCREATE TABLE b (id INT);";
82 let out = split_statements(sql);
83 assert_eq!(out.len(), 2);
84 assert!(out[0].starts_with("CREATE TABLE a"));
85 }
86}