use super::{SqlxDriver, SqlxValue};
use sqlx::QueryBuilder;
use std::fmt::Debug;
pub trait GatekeepSqlxBackend: Clone + Copy + Debug + Send + Sync + 'static {
type Database: sqlx::Database;
const DRIVER: SqlxDriver;
const NAME: &'static str;
fn push_placeholder(sql: &mut String, index: usize);
fn push_bind(builder: &mut QueryBuilder<Self::Database>, value: &SqlxValue);
const MIN_FUNCTION: &'static str;
const MAX_FUNCTION: &'static str;
const GRADE_FUNCTION_PROPAGATES_NULL: bool;
}
macro_rules! push_sqlx_bind {
($builder:expr, $value:expr) => {
match $value {
SqlxValue::Bool(value) => {
$builder.push_bind(*value);
}
SqlxValue::I16(value) => {
$builder.push_bind(*value);
}
SqlxValue::I32(value) => {
$builder.push_bind(*value);
}
SqlxValue::I64(value) => {
$builder.push_bind(*value);
}
SqlxValue::Text(value) => {
$builder.push_bind(value.clone());
}
SqlxValue::Bytes(value) => {
$builder.push_bind(value.clone());
}
SqlxValue::Uuid(value) => {
$builder.push_bind(*value);
}
SqlxValue::Date(value) => {
$builder.push_bind(*value);
}
SqlxValue::Time(value) => {
$builder.push_bind(*value);
}
SqlxValue::Timestamp(value) => {
$builder.push_bind(*value);
}
SqlxValue::TimestampTz(value) => {
$builder.push_bind(*value);
}
}
};
}
#[cfg(feature = "postgres")]
#[derive(Clone, Copy, Debug)]
pub struct PostgresBackend;
#[cfg(feature = "postgres")]
impl GatekeepSqlxBackend for PostgresBackend {
type Database = sqlx::Postgres;
const DRIVER: SqlxDriver = SqlxDriver::Postgres;
const NAME: &'static str = "postgres";
const MIN_FUNCTION: &'static str = "LEAST";
const MAX_FUNCTION: &'static str = "GREATEST";
const GRADE_FUNCTION_PROPAGATES_NULL: bool = false;
fn push_placeholder(sql: &mut String, index: usize) {
sql.push('$');
sql.push_str(&index.to_string());
}
fn push_bind(builder: &mut QueryBuilder<Self::Database>, value: &SqlxValue) {
push_sqlx_bind!(builder, value);
}
}
#[cfg(feature = "sqlite")]
#[derive(Clone, Copy, Debug)]
pub struct SqliteBackend;
#[cfg(feature = "sqlite")]
impl GatekeepSqlxBackend for SqliteBackend {
type Database = sqlx::Sqlite;
const DRIVER: SqlxDriver = SqlxDriver::Sqlite;
const NAME: &'static str = "sqlite";
const MIN_FUNCTION: &'static str = "min";
const MAX_FUNCTION: &'static str = "max";
const GRADE_FUNCTION_PROPAGATES_NULL: bool = true;
fn push_placeholder(sql: &mut String, _index: usize) {
sql.push('?');
}
fn push_bind(builder: &mut QueryBuilder<Self::Database>, value: &SqlxValue) {
push_sqlx_bind!(builder, value);
}
}
#[cfg(feature = "mysql")]
#[derive(Clone, Copy, Debug)]
pub struct MySqlBackend;
#[cfg(feature = "mysql")]
impl GatekeepSqlxBackend for MySqlBackend {
type Database = sqlx::MySql;
const DRIVER: SqlxDriver = SqlxDriver::MySql;
const NAME: &'static str = "mysql";
const MIN_FUNCTION: &'static str = "LEAST";
const MAX_FUNCTION: &'static str = "GREATEST";
const GRADE_FUNCTION_PROPAGATES_NULL: bool = true;
fn push_placeholder(sql: &mut String, _index: usize) {
sql.push('?');
}
fn push_bind(builder: &mut QueryBuilder<Self::Database>, value: &SqlxValue) {
push_sqlx_bind!(builder, value);
}
}