use crate::config::DatabaseBackend;
use prax_query::filter::FilterValue;
pub fn placeholder(backend: DatabaseBackend, index: usize) -> String {
match backend {
DatabaseBackend::Postgres => format!("${}", index),
DatabaseBackend::MySql | DatabaseBackend::Sqlite => "?".to_string(),
}
}
pub fn filter_value_to_string(value: &FilterValue) -> String {
match value {
FilterValue::String(s) => s.clone(),
FilterValue::Int(i) => i.to_string(),
FilterValue::Float(f) => f.to_string(),
FilterValue::Bool(b) => b.to_string(),
FilterValue::Null => "NULL".to_string(),
FilterValue::Json(j) => j.to_string(),
FilterValue::List(arr) => {
let items: Vec<String> = arr.iter().map(filter_value_to_string).collect();
format!("[{}]", items.join(", "))
}
}
}
pub fn placeholders(backend: DatabaseBackend, count: usize, start: usize) -> String {
(start..start + count)
.map(|i| placeholder(backend, i))
.collect::<Vec<_>>()
.join(", ")
}
pub fn quote_identifier(backend: DatabaseBackend, name: &str) -> String {
match backend {
DatabaseBackend::Postgres => format!("\"{}\"", name.replace('"', "\"\"")),
DatabaseBackend::MySql => format!("`{}`", name.replace('`', "``")),
DatabaseBackend::Sqlite => format!("\"{}\"", name.replace('"', "\"\"")),
}
}
pub fn rust_to_sql_type(backend: DatabaseBackend, rust_type: &str) -> &'static str {
match backend {
DatabaseBackend::Postgres => match rust_type {
"i32" => "INTEGER",
"i64" => "BIGINT",
"f32" => "REAL",
"f64" => "DOUBLE PRECISION",
"bool" => "BOOLEAN",
"String" | "&str" => "TEXT",
"Vec<u8>" | "&[u8]" => "BYTEA",
"Uuid" => "UUID",
"DateTime" | "chrono::DateTime" => "TIMESTAMPTZ",
"NaiveDate" => "DATE",
"NaiveTime" => "TIME",
"Decimal" => "DECIMAL",
"Json" | "serde_json::Value" => "JSONB",
_ => "TEXT",
},
DatabaseBackend::MySql => match rust_type {
"i32" => "INT",
"i64" => "BIGINT",
"f32" => "FLOAT",
"f64" => "DOUBLE",
"bool" => "BOOLEAN",
"String" | "&str" => "TEXT",
"Vec<u8>" | "&[u8]" => "BLOB",
"Uuid" => "CHAR(36)",
"DateTime" | "chrono::DateTime" => "DATETIME",
"NaiveDate" => "DATE",
"NaiveTime" => "TIME",
"Decimal" => "DECIMAL",
"Json" | "serde_json::Value" => "JSON",
_ => "TEXT",
},
DatabaseBackend::Sqlite => match rust_type {
"i32" | "i64" => "INTEGER",
"f32" | "f64" => "REAL",
"bool" => "INTEGER", "String" | "&str" => "TEXT",
"Vec<u8>" | "&[u8]" => "BLOB",
"Uuid" => "TEXT",
"DateTime" | "chrono::DateTime" => "TEXT", "NaiveDate" => "TEXT",
"NaiveTime" => "TEXT",
"Decimal" => "TEXT",
"Json" | "serde_json::Value" => "TEXT", _ => "TEXT",
},
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_placeholder() {
assert_eq!(placeholder(DatabaseBackend::Postgres, 1), "$1");
assert_eq!(placeholder(DatabaseBackend::Postgres, 5), "$5");
assert_eq!(placeholder(DatabaseBackend::MySql, 1), "?");
assert_eq!(placeholder(DatabaseBackend::Sqlite, 1), "?");
}
#[test]
fn test_placeholders() {
assert_eq!(placeholders(DatabaseBackend::Postgres, 3, 1), "$1, $2, $3");
assert_eq!(placeholders(DatabaseBackend::MySql, 3, 1), "?, ?, ?");
}
#[test]
fn test_quote_identifier() {
assert_eq!(
quote_identifier(DatabaseBackend::Postgres, "users"),
"\"users\""
);
assert_eq!(quote_identifier(DatabaseBackend::MySql, "users"), "`users`");
assert_eq!(
quote_identifier(DatabaseBackend::Sqlite, "users"),
"\"users\""
);
assert_eq!(
quote_identifier(DatabaseBackend::Postgres, "user\"name"),
"\"user\"\"name\""
);
}
#[test]
fn test_rust_to_sql_type() {
assert_eq!(
rust_to_sql_type(DatabaseBackend::Postgres, "i32"),
"INTEGER"
);
assert_eq!(rust_to_sql_type(DatabaseBackend::MySql, "i32"), "INT");
assert_eq!(rust_to_sql_type(DatabaseBackend::Sqlite, "i32"), "INTEGER");
assert_eq!(
rust_to_sql_type(DatabaseBackend::Postgres, "bool"),
"BOOLEAN"
);
assert_eq!(rust_to_sql_type(DatabaseBackend::Sqlite, "bool"), "INTEGER");
}
}