Skip to main content

vespertide_query/sql/
types.rs

1/// Database backend for SQL generation
2#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3pub enum DatabaseBackend {
4    Postgres,
5    MySql,
6    Sqlite,
7}
8
9/// Represents a built query that can be converted to SQL for any database backend
10#[derive(Debug, Clone)]
11pub enum BuiltQuery {
12    CreateTable(Box<sea_query::TableCreateStatement>),
13    DropTable(Box<sea_query::TableDropStatement>),
14    AlterTable(Box<sea_query::TableAlterStatement>),
15    CreateIndex(Box<sea_query::IndexCreateStatement>),
16    DropIndex(Box<sea_query::IndexDropStatement>),
17    RenameTable(Box<sea_query::TableRenameStatement>),
18    CreateForeignKey(Box<sea_query::ForeignKeyCreateStatement>),
19    DropForeignKey(Box<sea_query::ForeignKeyDropStatement>),
20    Insert(Box<sea_query::InsertStatement>),
21    Update(Box<sea_query::UpdateStatement>),
22    Raw(RawSql),
23}
24
25/// Raw SQL that may have backend-specific variants
26#[derive(Debug, Clone)]
27pub struct RawSql {
28    pub postgres: String,
29    pub mysql: String,
30    pub sqlite: String,
31}
32
33impl RawSql {
34    /// Create a `RawSql` with the same SQL for all backends
35    pub fn uniform(sql: String) -> Self {
36        Self {
37            postgres: sql.clone(),
38            mysql: sql.clone(),
39            sqlite: sql,
40        }
41    }
42
43    /// Create a `RawSql` with different SQL for each backend
44    pub fn per_backend(postgres: String, mysql: String, sqlite: String) -> Self {
45        Self {
46            postgres,
47            mysql,
48            sqlite,
49        }
50    }
51
52    /// Create a `RawSql` carrying `PostgreSQL`-only SQL; `MySQL` and `SQLite`
53    /// get no output.
54    ///
55    /// Replaces the repeated 3-line construction
56    /// `RawSql::per_backend(pg, String::new(), String::new())` so the
57    /// PG-only intent is visible at the call site (and the two
58    /// zero-capacity `String::new()` allocations are written once, in
59    /// this constructor).
60    pub fn postgres_only(sql: String) -> Self {
61        Self {
62            postgres: sql,
63            mysql: String::new(),
64            sqlite: String::new(),
65        }
66    }
67}
68
69impl BuiltQuery {
70    /// Build SQL string for the specified database backend
71    pub fn build(&self, backend: DatabaseBackend) -> String {
72        match self {
73            BuiltQuery::CreateTable(stmt) => {
74                crate::sql::helpers::build_schema_statement(stmt.as_ref(), backend)
75            }
76            BuiltQuery::DropTable(stmt) => {
77                crate::sql::helpers::build_schema_statement(stmt.as_ref(), backend)
78            }
79            BuiltQuery::AlterTable(stmt) => {
80                crate::sql::helpers::build_schema_statement(stmt.as_ref(), backend)
81            }
82            BuiltQuery::CreateIndex(stmt) => {
83                crate::sql::helpers::build_schema_statement(stmt.as_ref(), backend)
84            }
85            BuiltQuery::DropIndex(stmt) => {
86                crate::sql::helpers::build_schema_statement(stmt.as_ref(), backend)
87            }
88            BuiltQuery::RenameTable(stmt) => {
89                crate::sql::helpers::build_schema_statement(stmt.as_ref(), backend)
90            }
91            BuiltQuery::CreateForeignKey(stmt) => {
92                crate::sql::helpers::build_schema_statement(stmt.as_ref(), backend)
93            }
94            BuiltQuery::DropForeignKey(stmt) => {
95                crate::sql::helpers::build_schema_statement(stmt.as_ref(), backend)
96            }
97            BuiltQuery::Insert(stmt) => {
98                crate::sql::helpers::build_query_statement(stmt.as_ref(), backend)
99            }
100            BuiltQuery::Update(stmt) => {
101                crate::sql::helpers::build_query_statement(stmt.as_ref(), backend)
102            }
103            BuiltQuery::Raw(raw) => match backend {
104                DatabaseBackend::Postgres => raw.postgres.clone(),
105                DatabaseBackend::MySql => raw.mysql.clone(),
106                DatabaseBackend::Sqlite => raw.sqlite.clone(),
107            },
108        }
109    }
110}