mod private {
pub trait Sealed {}
}
pub trait Dialect: 'static + Copy + Default + private::Sealed {
const IDENTIFIER_QUOTE: char;
const CAST_BIGINT: &'static str = "BIGINT";
const CAST_DOUBLE: &'static str = "DOUBLE PRECISION";
const PARENTHESIZED_SET_OP_BRANCHES: bool = true;
const INSERT_NO_COLUMNS: &'static str = " DEFAULT VALUES";
const OFFSET_WITHOUT_LIMIT: Option<&'static str> = None;
fn write_placeholder(n: usize, out: &mut String) {
let _ = n;
out.push('?');
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Postgres;
impl private::Sealed for Postgres {}
impl Dialect for Postgres {
const IDENTIFIER_QUOTE: char = '"';
fn write_placeholder(n: usize, out: &mut String) {
use std::fmt::Write as _;
let _ = write!(out, "${n}");
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct MySql;
impl private::Sealed for MySql {}
impl Dialect for MySql {
const CAST_BIGINT: &'static str = "SIGNED";
const CAST_DOUBLE: &'static str = "DOUBLE";
const OFFSET_WITHOUT_LIMIT: Option<&'static str> = Some("18446744073709551615");
const IDENTIFIER_QUOTE: char = '`';
const INSERT_NO_COLUMNS: &'static str = " () VALUES ()";
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Sqlite;
impl private::Sealed for Sqlite {}
impl Dialect for Sqlite {
const PARENTHESIZED_SET_OP_BRANCHES: bool = false;
const OFFSET_WITHOUT_LIMIT: Option<&'static str> = Some("-1");
const IDENTIFIER_QUOTE: char = '"';
}
#[diagnostic::on_unimplemented(
message = "`{Self}` has no `RETURNING`",
label = "Postgres and SQLite do; MySQL has no equivalent at any version",
note = "read the rows back with a second statement, or write the query for a dialect that has it"
)]
pub trait SupportsReturning: Dialect {}
impl SupportsReturning for Postgres {}
impl SupportsReturning for Sqlite {}
#[diagnostic::on_unimplemented(
message = "`{Self}` has no `ON CONFLICT`",
label = "Postgres and SQLite do; MySQL spells upsert as `ON DUPLICATE KEY UPDATE`",
note = "that is a different clause, not a spelling of this one, so it isn't rendered from `.on_conflict_*(..)`"
)]
pub trait SupportsOnConflict: Dialect {}
impl SupportsOnConflict for Postgres {}
impl SupportsOnConflict for Sqlite {}
#[diagnostic::on_unimplemented(
message = "`{Self}` has no `RIGHT JOIN`",
label = "swap the tables and use `.left_join(..)`, which every dialect has"
)]
pub trait SupportsRightJoin: Dialect {}
impl SupportsRightJoin for Postgres {}
impl SupportsRightJoin for MySql {}
impl SupportsRightJoin for Sqlite {}
#[diagnostic::on_unimplemented(
message = "`{Self}` has no `FULL JOIN`",
label = "Postgres and SQLite do; MySQL's idiom is a `UNION` of a `LEFT` and a `RIGHT` join",
note = "that rewrite is a different query shape, so `.full_join(..)` doesn't do it silently"
)]
pub trait SupportsFullOuterJoin: Dialect {}
impl SupportsFullOuterJoin for Postgres {}
impl SupportsFullOuterJoin for Sqlite {}