easy_sqlx_core/sql/utils/
quote.rs1pub enum QuotePolicy {
2 QuotePolicyAlways,
3 QuotePolicyNone,
4 QuotePolicyReserved,
5}
6
7const COMMAN_QUOTE_MARK: u8 = b'`';
8
9pub fn always_no_reserve(_str: &String) -> bool {
10 false
11}
12
13pub fn always_reserve(_str: &String) -> bool {
14 true
15}
16
17#[derive(Clone)]
18pub struct Quoter {
19 prefix: u8,
20 suffix: u8,
21 is_reserved: fn(str: &String) -> bool,
22}
23
24impl Quoter {
25 pub fn new(prefix: u8, suffix: u8, is_reserved: fn(str: &String) -> bool) -> Self {
26 Self {
27 prefix,
28 suffix,
29 is_reserved,
30 }
31 }
32
33 pub fn common_quoter() -> Self {
34 Self {
35 prefix: COMMAN_QUOTE_MARK,
36 suffix: COMMAN_QUOTE_MARK,
37 is_reserved: always_reserve,
38 }
39 }
40
41 pub fn is_empty(&self) -> bool {
42 return self.prefix == 0 && self.suffix == 0;
43 }
44
45 pub fn quote<'a>(&self, s: &String) -> String {
46 let mut buf = String::new();
49 self.quote_to(&mut buf, s);
50 return buf;
51 }
53
54 pub fn join(&self, a: Vec<String>, sep: &String) -> String {
55 let mut buf = String::new();
56 self.join_write(&mut buf, a, sep);
57 return buf;
58 }
59
60 pub fn join_write(&self, b: &mut String, a: Vec<String>, sep: &String) {
61 if a.is_empty() {
62 return;
63 }
64
65 for (n, str) in a.iter().enumerate() {
66 if n > 0 {
67 b.push_str(sep.as_str());
68 }
69 self.quote_to(b, &str.trim().to_string());
70 }
71 }
72
73 pub fn trim(&self, s: String) -> String {
75 if s.len() < 2 {
76 return s;
77 }
78
79 let trim_start =
80 s.trim_start_matches(String::from_utf8(vec![self.prefix]).unwrap().as_str());
81 let trim_end =
82 trim_start.trim_end_matches(String::from_utf8(vec![self.suffix]).unwrap().as_str());
83 trim_end.to_string()
84 }
97
98 pub fn quote_to(&self, buf: &mut String, value: &String) {
111 let mut n = 0;
113 while n < value.len() {
114 let start = Quoter::find_start(value, n);
115 if start > n {
116 buf.push_str(&value.as_str()[n..start]);
117 }
121 if start == value.len() {
122 return;
123 }
124
125 let next_end = Quoter::find_word(value, start);
126 self.quote_word_to(buf, &value.as_str()[start..next_end].to_string());
127 n = next_end;
132 }
133 }
134
135 fn find_word(v: &String, start: usize) -> usize {
136 for (n, v) in v.char_indices() {
137 if n >= start && (v == '.' || v == ' ') {
138 return n;
139 }
140 }
141 v.len()
142 }
150
151 fn find_start(value: &String, start: usize) -> usize {
152 if let Some(ch) = value.chars().nth(start) {
155 if ch == '.' {
156 return start + 1;
157 }
158 if ch != ' ' {
162 return start;
163 }
164
165 let mut k: i32 = -1;
166 for (n, v) in value.char_indices() {
167 if n >= start && v != ' ' {
168 k = n as i32;
169 break;
170 }
171 }
172
173 if k == -1 {
174 return value.len();
175 }
176
177 let ch_k = value.chars().nth(k as usize).unwrap();
178 let ch_k_1 = value.chars().nth((k + 1) as usize).unwrap();
179
180 if (ch_k == 'A' || ch_k == 'a') && (ch_k_1 == 'S' || ch_k_1 == 's') {
181 k += 2;
182 }
183
184 for (n, v) in value.char_indices() {
185 if n >= (k as usize) && v != ' ' {
186 return n;
187 }
188 }
189 }
190 return value.len();
191 }
192
193 fn quote_word_to(&self, buf: &mut String, word: &String) {
194 let mut real_word = word.clone();
196 let word_bytes = word.as_bytes();
197 if (word_bytes[0] == COMMAN_QUOTE_MARK
198 && word_bytes[word_bytes.len() - 1] == COMMAN_QUOTE_MARK)
199 || (word_bytes[0] == self.prefix && word_bytes[word_bytes.len() - 1] == self.suffix)
200 {
201 real_word = word.as_str()[1..word.len() - 1].to_string();
202 }
203
204 if self.is_empty() {
205 buf.push_str(&real_word);
206 return;
207 }
208
209 let is_reserved = (self.is_reserved)(&real_word);
210 if is_reserved && real_word != "*" {
211 buf.push(self.prefix.into());
212 }
216 buf.push_str(&real_word);
217 if is_reserved && real_word != "*" {
221 buf.push(self.suffix.into());
222 }
223 }
224
225 pub fn replace(&self, sql: &String) -> String {
227 if self.is_empty() {
228 return sql.clone();
229 }
230
231 let mark: char = COMMAN_QUOTE_MARK.into();
234
235 let mut buf = String::new();
236
237 let mut begin_single_quote: bool = false;
238 let chars = &mut sql.chars();
239 let len = chars.count();
240 let mut n: usize = 0;
241 loop {
242 if n >= len {
243 break;
244 }
245 let ch = chars.nth(n).unwrap();
246
247 if !begin_single_quote && ch == mark {
248 let mut j = n + 1;
250 for (m, ch) in sql.char_indices() {
251 if m >= j && ch == mark {
252 break;
253 }
254 j += 1;
255 }
256 let word = sql.as_str()[n + 1..j].to_string();
262 let is_reserved = (self.is_reserved)(&word);
263
264 if is_reserved {
265 buf.push(self.prefix.into());
266 }
268 buf.push_str(&word);
269 if is_reserved {
271 buf.push(self.suffix.into());
273 }
274 n = j
275 } else {
276 if ch == '\'' {
277 begin_single_quote = !begin_single_quote
278 }
279 buf.push(ch);
280 }
282
283 n += 1;
284 }
285 return buf;
286 }
287}