Skip to main content

rainier_orm/
dialect.rs

1//! Dialect selection and SQL rendering.
2//!
3//! One [`Entity`](crate::Entity) yields one `sea_query` statement; this module
4//! renders that statement for whichever backend the [`Executor`](crate::Executor)
5//! reports. That indirection is the whole "translation between SQLite / D1 /
6//! MySQL / Postgres" story — the query is built once, lowered per dialect here.
7//!
8//! D1 is SQLite-on-the-wire, so it shares [`Dialect::Sqlite`] rendering; what
9//! differs for D1 is *transport*, which is the executor's concern, not the
10//! SQL's.
11
12use sea_query::{
13    MysqlQueryBuilder, PostgresQueryBuilder, QueryStatementBuilder, SchemaStatementBuilder,
14    SqliteQueryBuilder, Values,
15};
16
17/// The SQL dialect a backend speaks. Cloudflare D1 maps to [`Sqlite`] (it is
18/// SQLite over HTTP); the executor handles the transport difference.
19///
20/// [`Sqlite`]: Dialect::Sqlite
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum Dialect {
23    MySql,
24    Postgres,
25    Sqlite,
26}
27
28impl Dialect {
29    /// Render a data statement (`SELECT`/`INSERT`/`UPDATE`/`DELETE`) to
30    /// parameterised SQL plus its ordered bind values.
31    pub fn build_query<S: QueryStatementBuilder>(&self, stmt: &S) -> (String, Values) {
32        match self {
33            Dialect::MySql => stmt.build_any(&MysqlQueryBuilder),
34            Dialect::Postgres => stmt.build_any(&PostgresQueryBuilder),
35            Dialect::Sqlite => stmt.build_any(&SqliteQueryBuilder),
36        }
37    }
38
39    /// Render a schema statement (e.g. `CREATE TABLE`) to SQL. Schema
40    /// statements carry no bind values.
41    pub fn build_schema<S: SchemaStatementBuilder>(&self, stmt: &S) -> String {
42        match self {
43            Dialect::MySql => stmt.build_any(&MysqlQueryBuilder),
44            Dialect::Postgres => stmt.build_any(&PostgresQueryBuilder),
45            Dialect::Sqlite => stmt.build_any(&SqliteQueryBuilder),
46        }
47    }
48}