atomr_persistence_sql/
dialect.rs1use crate::config::SqlDialect;
4
5pub fn detect_dialect(url: &str) -> Option<SqlDialect> {
6 let lower = url.to_ascii_lowercase();
7 if lower.starts_with("sqlite:") {
8 Some(SqlDialect::Sqlite)
9 } else if lower.starts_with("postgres:") || lower.starts_with("postgresql:") {
10 Some(SqlDialect::Postgres)
11 } else if lower.starts_with("mysql:") || lower.starts_with("mariadb:") {
12 Some(SqlDialect::MySql)
13 } else if lower.starts_with("mssql:") || lower.starts_with("sqlserver:") {
14 Some(SqlDialect::MsSql)
15 } else {
16 None
17 }
18}
19
20pub(crate) fn sqlite_migration() -> &'static str {
21 include_str!("../migrations/sqlite/001_init.sql")
22}
23
24pub(crate) fn postgres_migration() -> &'static str {
25 include_str!("../migrations/postgres/001_init.sql")
26}
27
28pub(crate) fn mysql_migration() -> &'static str {
29 include_str!("../migrations/mysql/001_init.sql")
30}
31
32pub(crate) fn mssql_migration() -> &'static str {
33 include_str!("../migrations/mssql/001_init.sql")
34}
35
36pub(crate) fn migration_for(dialect: SqlDialect) -> &'static str {
37 match dialect {
38 SqlDialect::Sqlite => sqlite_migration(),
39 SqlDialect::Postgres => postgres_migration(),
40 SqlDialect::MySql => mysql_migration(),
41 SqlDialect::MsSql => mssql_migration(),
42 }
43}
44
45pub(crate) fn worm_migration_for(dialect: SqlDialect) -> &'static str {
49 match dialect {
50 SqlDialect::Sqlite => include_str!("../migrations/sqlite/002_worm.sql"),
51 SqlDialect::Postgres => include_str!("../migrations/postgres/002_worm.sql"),
52 SqlDialect::MySql => include_str!("../migrations/mysql/002_worm.sql"),
53 SqlDialect::MsSql => include_str!("../migrations/mssql/002_worm.sql"),
54 }
55}
56
57pub(crate) fn worm_deny_trigger_for(dialect: SqlDialect) -> &'static str {
65 match dialect {
66 SqlDialect::Sqlite => concat!(
70 "CREATE TRIGGER IF NOT EXISTS event_journal_worm_no_update ",
71 "BEFORE UPDATE ON event_journal BEGIN SELECT RAISE(ABORT, 'WORM: event_journal is append-only'); END",
72 "@@",
73 "CREATE TRIGGER IF NOT EXISTS event_journal_worm_no_delete ",
74 "BEFORE DELETE ON event_journal BEGIN SELECT RAISE(ABORT, 'WORM: event_journal is append-only'); END",
75 ),
76 SqlDialect::Postgres | SqlDialect::MySql | SqlDialect::MsSql => "",
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn detects_all_schemes() {
87 assert_eq!(detect_dialect("sqlite::memory:"), Some(SqlDialect::Sqlite));
88 assert_eq!(detect_dialect("postgres://a"), Some(SqlDialect::Postgres));
89 assert_eq!(detect_dialect("postgresql://a"), Some(SqlDialect::Postgres));
90 assert_eq!(detect_dialect("mysql://a"), Some(SqlDialect::MySql));
91 assert_eq!(detect_dialect("mssql://a"), Some(SqlDialect::MsSql));
92 assert_eq!(detect_dialect("https://x"), None);
93 }
94
95 #[test]
96 fn migrations_embedded() {
97 assert!(migration_for(SqlDialect::Sqlite).contains("event_journal"));
98 assert!(migration_for(SqlDialect::Postgres).contains("event_journal"));
99 assert!(migration_for(SqlDialect::MySql).contains("event_journal"));
100 }
101}