rust_store_core/dialect/
mod.rs1pub mod filter;
17pub mod introspect;
18pub mod ir;
19pub mod overlay;
20pub mod row;
21pub mod select;
22pub mod translate;
23pub mod write;
24
25pub use introspect::{introspect_to_schema_json, schema_def_from_rows};
27pub use overlay::merge_schema;
28pub use row::restore_rows_json;
29pub use translate::translate;
30
31use crate::schema::Schema;
32
33pub(crate) fn scalar_column(schema: &Schema, field: &str) -> Option<String> {
38 if field.contains('.') {
39 let (head, _) = field.split_once('.')?;
40 let head_type = schema.fields.get(head).map(|f| f.field_type.as_str());
42 if matches!(head_type, Some("object") | Some("array")) {
43 return None;
44 }
45 return Some(field.to_string());
46 }
47 match schema.fields.get(field).map(|f| f.field_type.as_str()) {
48 Some("object") | Some("array") => None,
49 _ => Some(field.to_string()),
50 }
51}
52
53pub(crate) fn field_is_bool(schema: &Schema, field: &str) -> bool {
62 schema
63 .fields
64 .get(field)
65 .map(|f| {
66 f.field_type.eq_ignore_ascii_case("bool")
67 || f.field_type.eq_ignore_ascii_case("boolean")
68 })
69 .unwrap_or(false)
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum Backend {
75 Mysql,
76 Postgres,
77 Sqlite,
78}
79
80impl Backend {
81 pub fn parse(s: &str) -> Result<Backend, String> {
83 match s.to_lowercase().as_str() {
84 "mysql" => Ok(Backend::Mysql),
85 "postgres" | "pg" | "postgresql" => Ok(Backend::Postgres),
86 "sqlite" => Ok(Backend::Sqlite),
87 _ => Err(format!("不支持的后端: {}", s)),
88 }
89 }
90
91 pub fn quote_ident(&self, ident: &str) -> String {
93 match self {
94 Backend::Mysql => format!("`{}`", ident.replace('`', "``")),
95 _ => format!("\"{}\"", ident.replace('"', "\"\"")),
96 }
97 }
98
99 pub fn double_type(&self) -> &'static str {
105 match self {
106 Backend::Mysql => "DOUBLE",
107 Backend::Postgres => "DOUBLE PRECISION",
108 Backend::Sqlite => "REAL",
109 }
110 }
111
112 pub fn qualified_table(&self, namespace: Option<&str>, table: &str) -> String {
117 match namespace.filter(|s| !s.is_empty()) {
118 Some(ns) => format!("{}.{}", self.quote_ident(ns), self.quote_ident(table)),
119 None => self.quote_ident(table),
120 }
121 }
122
123 pub fn placeholder(&self, _index: usize) -> String {
125 match self {
126 Backend::Postgres => format!("${}", _index + 1),
127 _ => "?".to_string(),
128 }
129 }
130
131 pub fn as_str(&self) -> &'static str {
133 match self {
134 Backend::Mysql => "mysql",
135 Backend::Postgres => "postgres",
136 Backend::Sqlite => "sqlite",
137 }
138 }
139
140 pub fn supports_returning(&self) -> bool {
142 !matches!(self, Backend::Mysql)
143 }
144}