use crate::builder::QueryBuilder;
use crate::dialect::Dialect;
use crate::value::Value;
#[cfg(feature = "sqlx_mysql")]
use crate::dialect::MySql;
#[cfg(feature = "sqlx_postgres")]
use crate::dialect::Postgres;
#[cfg(feature = "sqlx_sqlite")]
use crate::dialect::Sqlite;
pub trait SqlxDialect: Dialect + private::Sealed {
type Database: sqlx::Database<Arguments: sqlx::IntoArguments<Self::Database>>;
fn bind_arguments(binds: &[Value]) -> <Self::Database as sqlx::Database>::Arguments;
}
mod private {
pub trait Sealed {}
#[cfg(feature = "sqlx_postgres")]
impl Sealed for crate::dialect::Postgres {}
#[cfg(feature = "sqlx_mysql")]
impl Sealed for crate::dialect::MySql {}
#[cfg(feature = "sqlx_sqlite")]
impl Sealed for crate::dialect::Sqlite {}
}
#[cfg(feature = "sqlx_postgres")]
impl SqlxDialect for Postgres {
type Database = sqlx::Postgres;
fn bind_arguments(binds: &[Value]) -> sqlx::postgres::PgArguments {
use sqlx::Arguments;
let mut arguments = sqlx::postgres::PgArguments::default();
for bind in binds {
match bind {
Value::Null => {
let _ = arguments.add(Option::<String>::None);
}
Value::Bool(b) => {
let _ = arguments.add(*b);
}
Value::I64(i) => {
let _ = arguments.add(*i);
}
Value::F64(f) => {
let _ = arguments.add(*f);
}
Value::Text(s) => {
let _ = arguments.add(s.clone());
}
Value::Bytes(b) => {
let _ = arguments.add(b.clone());
}
#[cfg(feature = "json")]
Value::Json(j) => {
let _ = arguments.add(serde_json::to_string(j).unwrap_or_default());
}
#[cfg(feature = "uuid")]
Value::Uuid(u) => {
let _ = arguments.add(*u);
}
#[cfg(feature = "chrono")]
Value::DateTimeUtc(dt) => {
let _ = arguments.add(*dt);
}
#[cfg(feature = "chrono")]
Value::NaiveDateTime(dt) => {
let _ = arguments.add(*dt);
}
#[cfg(feature = "chrono")]
Value::NaiveDate(d) => {
let _ = arguments.add(*d);
}
#[cfg(feature = "chrono")]
Value::NaiveTime(t) => {
let _ = arguments.add(*t);
}
#[cfg(feature = "decimal")]
Value::Decimal(d) => {
let _ = arguments.add(*d);
}
}
}
arguments
}
}
#[cfg(feature = "sqlx_mysql")]
impl SqlxDialect for MySql {
type Database = sqlx::MySql;
fn bind_arguments(binds: &[Value]) -> sqlx::mysql::MySqlArguments {
use sqlx::Arguments;
let mut arguments = sqlx::mysql::MySqlArguments::default();
for bind in binds {
match bind {
Value::Null => {
let _ = arguments.add(Option::<String>::None);
}
Value::Bool(b) => {
let _ = arguments.add(*b);
}
Value::I64(i) => {
let _ = arguments.add(*i);
}
Value::F64(f) => {
let _ = arguments.add(*f);
}
Value::Text(s) => {
let _ = arguments.add(s.clone());
}
Value::Bytes(b) => {
let _ = arguments.add(b.clone());
}
#[cfg(feature = "json")]
Value::Json(j) => {
let _ = arguments.add(serde_json::to_string(j).unwrap_or_default());
}
#[cfg(feature = "uuid")]
Value::Uuid(u) => {
let _ = arguments.add(*u);
}
#[cfg(feature = "chrono")]
Value::DateTimeUtc(dt) => {
let _ = arguments.add(*dt);
}
#[cfg(feature = "chrono")]
Value::NaiveDateTime(dt) => {
let _ = arguments.add(*dt);
}
#[cfg(feature = "chrono")]
Value::NaiveDate(d) => {
let _ = arguments.add(*d);
}
#[cfg(feature = "chrono")]
Value::NaiveTime(t) => {
let _ = arguments.add(*t);
}
#[cfg(feature = "decimal")]
Value::Decimal(d) => {
let _ = arguments.add(*d);
}
}
}
arguments
}
}
#[cfg(feature = "sqlx_sqlite")]
impl SqlxDialect for Sqlite {
type Database = sqlx::Sqlite;
fn bind_arguments(binds: &[Value]) -> sqlx::sqlite::SqliteArguments {
use sqlx::Arguments;
let mut arguments = sqlx::sqlite::SqliteArguments::default();
for bind in binds {
match bind {
Value::Null => {
let _ = arguments.add(Option::<String>::None);
}
Value::Bool(b) => {
let _ = arguments.add(*b);
}
Value::I64(i) => {
let _ = arguments.add(*i);
}
Value::F64(f) => {
let _ = arguments.add(*f);
}
Value::Text(s) => {
let _ = arguments.add(s.clone());
}
Value::Bytes(b) => {
let _ = arguments.add(b.clone());
}
#[cfg(feature = "json")]
Value::Json(j) => {
let _ = arguments.add(serde_json::to_string(j).unwrap_or_default());
}
#[cfg(feature = "uuid")]
Value::Uuid(u) => {
let _ = arguments.add(*u);
}
#[cfg(feature = "chrono")]
Value::DateTimeUtc(dt) => {
let _ = arguments.add(*dt);
}
#[cfg(feature = "chrono")]
Value::NaiveDateTime(dt) => {
let _ = arguments.add(*dt);
}
#[cfg(feature = "chrono")]
Value::NaiveDate(d) => {
let _ = arguments.add(*d);
}
#[cfg(feature = "chrono")]
Value::NaiveTime(t) => {
let _ = arguments.add(*t);
}
#[cfg(feature = "decimal")]
Value::Decimal(d) => {
let _ = arguments.add(d.to_string());
}
}
}
arguments
}
}
#[cfg(any(
feature = "sqlx_postgres",
feature = "sqlx_mysql",
feature = "sqlx_sqlite"
))]
impl<D: SqlxDialect> QueryBuilder<D> {
pub fn to_sqlx_query(
&self,
) -> sqlx::query::Query<'_, D::Database, <D::Database as sqlx::Database>::Arguments> {
let (sql, binds) = self.to_sql();
sqlx::query_with(sqlx::AssertSqlSafe(sql), D::bind_arguments(&binds))
}
pub fn to_sqlx_query_as<T>(
&self,
) -> sqlx::query::QueryAs<'_, D::Database, T, <D::Database as sqlx::Database>::Arguments>
where
T: for<'r> sqlx::FromRow<'r, <D::Database as sqlx::Database>::Row>,
{
let (sql, binds) = self.to_sql();
sqlx::query_as_with(sqlx::AssertSqlSafe(sql), D::bind_arguments(&binds))
}
}