#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SqlDialect {
Sqlite,
Postgres,
}
impl SqlDialect {
pub fn placeholder(&self, n: usize) -> String {
match self {
SqlDialect::Sqlite => format!("?{n}"),
SqlDialect::Postgres => format!("${n}"),
}
}
pub fn scalar_max(&self) -> &'static str {
match self {
SqlDialect::Sqlite => "MAX",
SqlDialect::Postgres => "GREATEST",
}
}
pub fn text_collate(&self) -> &'static str {
match self {
SqlDialect::Sqlite => "",
SqlDialect::Postgres => " COLLATE \"C\"",
}
}
pub fn without_rowid(&self) -> &'static str {
match self {
SqlDialect::Sqlite => " WITHOUT ROWID",
SqlDialect::Postgres => "",
}
}
pub fn null_safe_eq(&self) -> &'static str {
match self {
SqlDialect::Sqlite => "IS",
SqlDialect::Postgres => "IS NOT DISTINCT FROM",
}
}
}
pub struct PlaceholderGen {
dialect: SqlDialect,
next_idx: usize,
}
impl PlaceholderGen {
pub fn new(dialect: SqlDialect) -> Self {
Self {
dialect,
next_idx: 1,
}
}
pub fn next_placeholder(&mut self) -> String {
let p = self.dialect.placeholder(self.next_idx);
self.next_idx += 1;
p
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn placeholder_syntax_per_dialect() {
assert_eq!(SqlDialect::Sqlite.placeholder(3), "?3");
assert_eq!(SqlDialect::Postgres.placeholder(3), "$3");
}
#[test]
fn scalar_max_per_dialect() {
assert_eq!(SqlDialect::Sqlite.scalar_max(), "MAX");
assert_eq!(SqlDialect::Postgres.scalar_max(), "GREATEST");
}
#[test]
fn text_collate_per_dialect() {
assert_eq!(SqlDialect::Sqlite.text_collate(), "");
assert_eq!(SqlDialect::Postgres.text_collate(), " COLLATE \"C\"");
}
#[test]
fn null_safe_eq_per_dialect() {
assert_eq!(SqlDialect::Sqlite.null_safe_eq(), "IS");
assert_eq!(SqlDialect::Postgres.null_safe_eq(), "IS NOT DISTINCT FROM");
}
}