1use crate::*;
4
5#[cfg(feature = "backend-mysql")]
6#[cfg_attr(docsrs, doc(cfg(feature = "backend-mysql")))]
7mod mysql;
8#[cfg(feature = "backend-postgres")]
9#[cfg_attr(docsrs, doc(cfg(feature = "backend-postgres")))]
10mod postgres;
11#[cfg(feature = "backend-sqlite")]
12#[cfg_attr(docsrs, doc(cfg(feature = "backend-sqlite")))]
13mod sqlite;
14
15#[cfg(feature = "backend-mysql")]
16pub use mysql::*;
17#[cfg(feature = "backend-postgres")]
18pub use postgres::*;
19#[cfg(feature = "backend-sqlite")]
20pub use sqlite::*;
21
22mod foreign_key_builder;
23mod index_builder;
24mod query_builder;
25mod table_builder;
26mod table_ref_builder;
27
28pub use self::foreign_key_builder::*;
29pub use self::index_builder::*;
30pub use self::query_builder::*;
31pub use self::table_builder::*;
32pub use self::table_ref_builder::*;
33
34pub trait GenericBuilder: QueryBuilder + SchemaBuilder {}
35
36pub trait SchemaBuilder: TableBuilder + IndexBuilder + ForeignKeyBuilder {}
37
38pub trait QuotedBuilder {
39 fn quote(&self) -> Quote;
41}
42
43pub trait EscapeBuilder {
44 fn escape_string(&self, string: &str) -> String {
46 string
47 .replace('\\', "\\\\")
48 .replace('"', "\\\"")
49 .replace('\'', "\\'")
50 .replace('\0', "\\0")
51 .replace('\x08', "\\b")
52 .replace('\x09', "\\t")
53 .replace('\x1a', "\\z")
54 .replace('\n', "\\n")
55 .replace('\r', "\\r")
56 }
57
58 fn unescape_string(&self, string: &str) -> String {
60 let mut escape = false;
61 let mut output = String::new();
62 for c in string.chars() {
63 if !escape && c == '\\' {
64 escape = true;
65 } else if escape {
66 write!(
67 output,
68 "{}",
69 match c {
70 '0' => '\0',
71 'b' => '\x08',
72 't' => '\x09',
73 'z' => '\x1a',
74 'n' => '\n',
75 'r' => '\r',
76 c => c,
77 }
78 )
79 .unwrap();
80 escape = false;
81 } else {
82 write!(output, "{c}").unwrap();
83 }
84 }
85 output
86 }
87}
88
89pub trait PrecedenceDecider {
90 fn inner_expr_well_known_greater_precedence(
94 &self,
95 inner: &SimpleExpr,
96 outer_oper: &Oper,
97 ) -> bool;
98}
99
100pub trait OperLeftAssocDecider {
101 fn well_known_left_associative(&self, op: &BinOper) -> bool;
105}
106
107#[derive(Debug, PartialEq)]
108pub enum Oper {
109 UnOper(UnOper),
110 BinOper(BinOper),
111}
112
113impl From<UnOper> for Oper {
114 fn from(value: UnOper) -> Self {
115 Oper::UnOper(value)
116 }
117}
118
119impl From<BinOper> for Oper {
120 fn from(value: BinOper) -> Self {
121 Oper::BinOper(value)
122 }
123}
124
125impl Oper {
126 pub(crate) fn is_logical(&self) -> bool {
127 matches!(
128 self,
129 Oper::UnOper(UnOper::Not) | Oper::BinOper(BinOper::And) | Oper::BinOper(BinOper::Or)
130 )
131 }
132
133 pub(crate) fn is_between(&self) -> bool {
134 matches!(
135 self,
136 Oper::BinOper(BinOper::Between) | Oper::BinOper(BinOper::NotBetween)
137 )
138 }
139
140 pub(crate) fn is_like(&self) -> bool {
141 matches!(
142 self,
143 Oper::BinOper(BinOper::Like) | Oper::BinOper(BinOper::NotLike)
144 )
145 }
146
147 pub(crate) fn is_in(&self) -> bool {
148 matches!(
149 self,
150 Oper::BinOper(BinOper::In) | Oper::BinOper(BinOper::NotIn)
151 )
152 }
153
154 pub(crate) fn is_is(&self) -> bool {
155 matches!(
156 self,
157 Oper::BinOper(BinOper::Is) | Oper::BinOper(BinOper::IsNot)
158 )
159 }
160
161 pub(crate) fn is_shift(&self) -> bool {
162 matches!(
163 self,
164 Oper::BinOper(BinOper::LShift) | Oper::BinOper(BinOper::RShift)
165 )
166 }
167
168 pub(crate) fn is_arithmetic(&self) -> bool {
169 match self {
170 Oper::BinOper(b) => {
171 matches!(
172 b,
173 BinOper::Mul | BinOper::Div | BinOper::Mod | BinOper::Add | BinOper::Sub
174 )
175 }
176 _ => false,
177 }
178 }
179
180 pub(crate) fn is_comparison(&self) -> bool {
181 match self {
182 Oper::BinOper(b) => {
183 matches!(
184 b,
185 BinOper::SmallerThan
186 | BinOper::SmallerThanOrEqual
187 | BinOper::Equal
188 | BinOper::GreaterThanOrEqual
189 | BinOper::GreaterThan
190 | BinOper::NotEqual
191 )
192 }
193 _ => false,
194 }
195 }
196}