pub mod filter;
pub mod introspect;
pub mod ir;
pub mod overlay;
pub mod row;
pub mod select;
pub mod translate;
pub mod write;
pub use introspect::{introspect_to_schema_json, schema_def_from_rows};
pub use overlay::merge_schema;
pub use row::restore_rows_json;
pub use translate::translate;
use crate::schema::Schema;
pub(crate) fn scalar_column(schema: &Schema, field: &str) -> Option<String> {
if field.contains('.') {
let (head, _) = field.split_once('.')?;
let head_type = schema.fields.get(head).map(|f| f.field_type.as_str());
if matches!(head_type, Some("object") | Some("array")) {
return None;
}
return Some(field.to_string());
}
match schema.fields.get(field).map(|f| f.field_type.as_str()) {
Some("object") | Some("array") => None,
_ => Some(field.to_string()),
}
}
pub(crate) fn field_is_bool(schema: &Schema, field: &str) -> bool {
schema
.fields
.get(field)
.map(|f| {
f.field_type.eq_ignore_ascii_case("bool")
|| f.field_type.eq_ignore_ascii_case("boolean")
})
.unwrap_or(false)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Backend {
Mysql,
Postgres,
Sqlite,
}
impl Backend {
pub fn parse(s: &str) -> Result<Backend, String> {
match s.to_lowercase().as_str() {
"mysql" => Ok(Backend::Mysql),
"postgres" | "pg" | "postgresql" => Ok(Backend::Postgres),
"sqlite" => Ok(Backend::Sqlite),
_ => Err(format!("不支持的后端: {}", s)),
}
}
pub fn quote_ident(&self, ident: &str) -> String {
match self {
Backend::Mysql => format!("`{}`", ident.replace('`', "``")),
_ => format!("\"{}\"", ident.replace('"', "\"\"")),
}
}
pub fn double_type(&self) -> &'static str {
match self {
Backend::Mysql => "DOUBLE",
Backend::Postgres => "DOUBLE PRECISION",
Backend::Sqlite => "REAL",
}
}
pub fn qualified_table(&self, namespace: Option<&str>, table: &str) -> String {
match namespace.filter(|s| !s.is_empty()) {
Some(ns) => format!("{}.{}", self.quote_ident(ns), self.quote_ident(table)),
None => self.quote_ident(table),
}
}
pub fn placeholder(&self, _index: usize) -> String {
match self {
Backend::Postgres => format!("${}", _index + 1),
_ => "?".to_string(),
}
}
pub fn as_str(&self) -> &'static str {
match self {
Backend::Mysql => "mysql",
Backend::Postgres => "postgres",
Backend::Sqlite => "sqlite",
}
}
pub fn supports_returning(&self) -> bool {
!matches!(self, Backend::Mysql)
}
}