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}