1use std::borrow::Cow;
2
3pub const MYSQL_KEYWORDS: &[&str] = &[
4 "ACCESSIBLE",
5 "ADD",
6 "ALL",
7 "ALTER",
8 "ANALYZE",
9 "AND",
10 "AS",
11 "ASC",
12 "ASENSITIVE",
13 "BEFORE",
14 "BETWEEN",
15 "BIGINT",
16 "BINARY",
17 "BLOB",
18 "BOTH",
19 "BY",
20 "CALL",
21 "CASCADE",
22 "CASE",
23 "CHANGE",
24 "CHAR",
25 "CHARACTER",
26 "CHECK",
27 "COLLATE",
28 "COLUMN",
29 "CONDITION",
30 "CONSTRAINT",
31 "CONTINUE",
32 "CONVERT",
33 "CREATE",
34 "CROSS",
35 "CURRENT_DATE",
36 "CURRENT_TIME",
37 "CURRENT_TIMESTAMP",
38 "CURRENT_USER",
39 "CURSOR",
40 "DATABASE",
41 "DATABASES",
42 "DAY_HOUR",
43 "DAY_MICROSECOND",
44 "DAY_MINUTE",
45 "DAY_SECOND",
46 "DEC",
47 "DECIMAL",
48 "DECLARE",
49 "DEFAULT",
50 "DELAYED",
51 "DELETE",
52 "DESC",
53 "DESCRIBE",
54 "DETERMINISTIC",
55 "DISTINCT",
56 "DISTINCTROW",
57 "DIV",
58 "DOUBLE",
59 "DROP",
60 "DUAL",
61 "EACH",
62 "ELSE",
63 "ELSEIF",
64 "ENCLOSED",
65 "ESCAPED",
66 "EXISTS",
67 "EXIT",
68 "EXPLAIN",
69 "FALSE",
70 "FETCH",
71 "FLOAT",
72 "FLOAT4",
73 "FLOAT8",
74 "FOR",
75 "FORCE",
76 "FOREIGN",
77 "FROM",
78 "FULLTEXT",
79 "GENERATED",
80 "GET",
81 "GRANT",
82 "GROUP",
83 "HAVING",
84 "HIGH_PRIORITY",
85 "HOUR_MICROSECOND",
86 "HOUR_MINUTE",
87 "HOUR_SECOND",
88 "IF",
89 "IGNORE",
90 "IN",
91 "INDEX",
92 "INFILE",
93 "INNER",
94 "INOUT",
95 "INSENSITIVE",
96 "INSERT",
97 "INT",
98 "INT1",
99 "INT2",
100 "INT3",
101 "INT4",
102 "INT8",
103 "INTEGER",
104 "INTERVAL",
105 "INTO",
106 "IO_AFTER_GTIDS",
107 "IO_BEFORE_GTIDS",
108 "IS",
109 "ITERATE",
110 "JOIN",
111 "KEY",
112 "KEYS",
113 "KILL",
114 "LEADING",
115 "LEAVE",
116 "LEFT",
117 "LIKE",
118 "LIMIT",
119 "LINEAR",
120 "LINES",
121 "LOAD",
122 "LOCALTIME",
123 "LOCALTIMESTAMP",
124 "LOCK",
125 "LONG",
126 "LONGBLOB",
127 "LONGTEXT",
128 "LOOP",
129 "LOW_PRIORITY",
130 "MASTER_BIND",
131 "MASTER_SSL_VERIFY_SERVER_CERT",
132 "MATCH",
133 "MAXVALUE",
134 "MEDIUMBLOB",
135 "MEDIUMINT",
136 "MEDIUMTEXT",
137 "MIDDLEINT",
138 "MINUTE_MICROSECOND",
139 "MINUTE_SECOND",
140 "MOD",
141 "MODIFIES",
142 "NATURAL",
143 "NOT",
144 "NO_WRITE_TO_BINLOG",
145 "NULL",
146 "NUMERIC",
147 "ON",
148 "OPTIMIZE",
149 "OPTION",
150 "OPTIONALLY",
151 "OR",
152 "ORDER",
153 "OUT",
154 "OUTER",
155 "OUTFILE",
156 "PARTITION",
157 "PRECISION",
158 "PRIMARY",
159 "PROCEDURE",
160 "PURGE",
161 "RANGE",
162 "READ",
163 "READS",
164 "READ_WRITE",
165 "REAL",
166 "REFERENCES",
167 "REGEXP",
168 "RELEASE",
169 "RENAME",
170 "REPEAT",
171 "REPLACE",
172 "REQUIRE",
173 "RESIGNAL",
174 "RESTRICT",
175 "RETURN",
176 "REVOKE",
177 "RIGHT",
178 "RLIKE",
179 "SCHEMA",
180 "SCHEMAS",
181 "SECOND_MICROSECOND",
182 "SELECT",
183 "SENSITIVE",
184 "SEPARATOR",
185 "SET",
186 "SHOW",
187 "SIGNAL",
188 "SMALLINT",
189 "SPATIAL",
190 "SPECIFIC",
191 "SQL",
192 "SQLEXCEPTION",
193 "SQLSTATE",
194 "SQLWARNING",
195 "SQL_BIG_RESULT",
196 "SQL_CALC_FOUND_ROWS",
197 "SQL_SMALL_RESULT",
198 "SSL",
199 "STARTING",
200 "STORED",
201 "STRAIGHT_JOIN",
202 "TABLE",
203 "TERMINATED",
204 "THEN",
205 "TINYBLOB",
206 "TINYINT",
207 "TINYTEXT",
208 "TO",
209 "TRAILING",
210 "TRIGGER",
211 "TRUE",
212 "UNDO",
213 "UNION",
214 "UNIQUE",
215 "UNLOCK",
216 "UNSIGNED",
217 "UPDATE",
218 "USAGE",
219 "USE",
220 "USING",
221 "UTC_DATE",
222 "UTC_TIME",
223 "UTC_TIMESTAMP",
224 "VALUES",
225 "VARBINARY",
226 "VARCHAR",
227 "VARCHARACTER",
228 "VARYING",
229 "VIRTUAL",
230 "WHEN",
231 "WHERE",
232 "WHILE",
233 "WITH",
234 "WRITE",
235 "XOR",
236 "YEAR_MONTH",
237 "ZEROFILL",
238];
239
240pub const POSTGRES_KEYWORDS: &[&str] = &[
241 "ALL",
242 "ANALYSE",
243 "ANALYZE",
244 "AND",
245 "ANY",
246 "ARRAY",
247 "AS",
248 "ASC",
249 "ASYMMETRIC",
250 "AUTHORIZATION",
251 "BINARY",
252 "BOTH",
253 "CASE",
254 "CAST",
255 "CHECK",
256 "COLLATE",
257 "COLLATION",
258 "COLUMN",
259 "CONCURRENTLY",
260 "CONSTRAINT",
261 "CREATE",
262 "CROSS",
263 "CURRENT_CATALOG",
264 "CURRENT_DATE",
265 "CURRENT_ROLE",
266 "CURRENT_SCHEMA",
267 "CURRENT_TIME",
268 "CURRENT_TIMESTAMP",
269 "CURRENT_USER",
270 "DEFAULT",
271 "DEFERRABLE",
272 "DEFERRED",
273 "DELETE",
274 "DESC",
275 "DISTINCT",
276 "DO",
277 "ELSE",
278 "END",
279 "EXCEPT",
280 "FALSE",
281 "FETCH",
282 "FOR",
283 "FOREIGN",
284 "FREEZE",
285 "FROM",
286 "FULL",
287 "GRANT",
288 "GROUP",
289 "HAVING",
290 "ILIKE",
291 "IN",
292 "INITIALLY",
293 "INNER",
294 "INSERT",
295 "INTERSECT",
296 "INTO",
297 "IS",
298 "ISNULL",
299 "JOIN",
300 "LATERAL",
301 "LEADING",
302 "LEFT",
303 "LIKE",
304 "LIMIT",
305 "LOCALTIME",
306 "LOCALTIMESTAMP",
307 "NATURAL",
308 "NOT",
309 "NOTNULL",
310 "NULL",
311 "OFFSET",
312 "ON",
313 "ONLY",
314 "OR",
315 "ORDER",
316 "OUTER",
317 "OVERLAPS",
318 "PLACING",
319 "PRIMARY",
320 "REFERENCES",
321 "RETURNING",
322 "RIGHT",
323 "SELECT",
324 "SESSION_USER",
325 "SIMILAR",
326 "SOME",
327 "SYMMETRIC",
328 "TABLE",
329 "TABLESAMPLE",
330 "THEN",
331 "TO",
332 "TRAILING",
333 "TRUE",
334 "UNION",
335 "UNIQUE",
336 "UPDATE",
337 "USER",
338 "USING",
339 "VARIADIC",
340 "VERBOSE",
341 "WHEN",
342 "WHERE",
343 "WINDOW",
344 "WITH",
345];
346
347pub const SQLITE_KEYWORDS: &[&str] = &[
348 "ABORT",
349 "ACTION",
350 "ADD",
351 "AFTER",
352 "ALL",
353 "ALTER",
354 "ANALYZE",
355 "AND",
356 "AS",
357 "ASC",
358 "ATTACH",
359 "AUTOINCREMENT",
360 "BEFORE",
361 "BEGIN",
362 "BETWEEN",
363 "BY",
364 "CASCADE",
365 "CASE",
366 "CAST",
367 "CHECK",
368 "COLLATE",
369 "COLUMN",
370 "COMMIT",
371 "CONFLICT",
372 "CONSTRAINT",
373 "CREATE",
374 "CROSS",
375 "CURRENT_DATE",
376 "CURRENT_TIME",
377 "CURRENT_TIMESTAMP",
378 "DATABASE",
379 "DEFAULT",
380 "DEFERRABLE",
381 "DEFERRED",
382 "DELETE",
383 "DESC",
384 "DETACH",
385 "DISTINCT",
386 "DROP",
387 "EACH",
388 "ELSE",
389 "END",
390 "ESCAPE",
391 "EXCEPT",
392 "EXCLUSIVE",
393 "EXISTS",
394 "EXPLAIN",
395 "FAIL",
396 "FOR",
397 "FOREIGN",
398 "FROM",
399 "FULL",
400 "GLOB",
401 "GROUP",
402 "HAVING",
403 "IF",
404 "IGNORE",
405 "IMMEDIATE",
406 "IN",
407 "INDEX",
408 "INDEXED",
409 "INITIALLY",
410 "INNER",
411 "INSERT",
412 "INSTEAD",
413 "INTERSECT",
414 "INTO",
415 "IS",
416 "ISNULL",
417 "JOIN",
418 "KEY",
419 "LEFT",
420 "LIKE",
421 "LIMIT",
422 "MATCH",
423 "NATURAL",
424 "NO",
425 "NOT",
426 "NOTNULL",
427 "NULL",
428 "OF",
429 "OFFSET",
430 "ON",
431 "OR",
432 "ORDER",
433 "OUTER",
434 "PLAN",
435 "PRAGMA",
436 "PRIMARY",
437 "QUERY",
438 "RAISE",
439 "RECURSIVE",
440 "REFERENCES",
441 "REGEXP",
442 "REINDEX",
443 "RELEASE",
444 "RENAME",
445 "REPLACE",
446 "RESTRICT",
447 "RIGHT",
448 "ROLLBACK",
449 "ROW",
450 "SAVEPOINT",
451 "SELECT",
452 "SET",
453 "TABLE",
454 "TEMP",
455 "TEMPORARY",
456 "THEN",
457 "TO",
458 "TRANSACTION",
459 "TRIGGER",
460 "UNION",
461 "UNIQUE",
462 "UPDATE",
463 "USING",
464 "VACUUM",
465 "VALUES",
466 "VIEW",
467 "VIRTUAL",
468 "WHEN",
469 "WHERE",
470 "WITH",
471 "WITHOUT",
472];
473
474pub const COMMON_KEYWORDS: &[&str] = &[
475 "ALL",
476 "AND",
477 "AS",
478 "ASC",
479 "BETWEEN",
480 "BY",
481 "CASE",
482 "CHECK",
483 "COLLATE",
484 "COLUMN",
485 "CREATE",
486 "CROSS",
487 "DEFAULT",
488 "DELETE",
489 "DESC",
490 "DISTINCT",
491 "DROP",
492 "ELSE",
493 "END",
494 "EXISTS",
495 "FOREIGN",
496 "FROM",
497 "FULL",
498 "GROUP",
499 "HAVING",
500 "IN",
501 "INDEX",
502 "INNER",
503 "INSERT",
504 "INTO",
505 "IS",
506 "JOIN",
507 "LEFT",
508 "LIKE",
509 "LIMIT",
510 "NOT",
511 "NULL",
512 "ON",
513 "OR",
514 "ORDER",
515 "OUTER",
516 "PRIMARY",
517 "REFERENCES",
518 "SELECT",
519 "SET",
520 "TABLE",
521 "THEN",
522 "TO",
523 "UNION",
524 "UNIQUE",
525 "UPDATE",
526 "USING",
527 "VALUES",
528 "WHEN",
529 "WHERE",
530 "WITH",
531];
532
533fn contains_ignore_case<T: AsRef<str>>(haystack: &[T], needle: &str) -> bool {
534 let needle_lower = needle.to_lowercase();
535 haystack
536 .iter()
537 .any(|item| item.as_ref().to_lowercase() == needle_lower)
538}
539
540pub trait KeywordsEscaper {
541 fn gen_upsert_name(&self, word: &str) -> String;
542 fn is_keyword(&self, word: &str) -> bool;
543 fn escape_word(&self, word: &str) -> String;
544 fn escape<'a>(&self, word: &'a str) -> Cow<'a, str> {
545 let trimmed = word.trim();
546 if self.is_keyword(trimmed) {
547 Cow::Owned(self.escape_word(trimmed))
548 } else {
549 Cow::Borrowed(trimmed)
550 }
551 }
552}
553
554#[derive(Default, Debug, Clone)]
555pub struct MySqlKeywordEscaper;
556impl KeywordsEscaper for MySqlKeywordEscaper {
557 fn gen_upsert_name(&self, word: &str) -> String {
558 format!("VALUES({})", word)
559 }
560
561 fn is_keyword(&self, word: &str) -> bool {
562 contains_ignore_case(MYSQL_KEYWORDS, word)
563 }
564 fn escape_word(&self, word: &str) -> String {
565 format!("`{}`", word)
566 }
567}
568
569#[derive(Default, Debug, Clone)]
570pub struct PostgresKeywordEscaper;
571impl KeywordsEscaper for PostgresKeywordEscaper {
572 fn gen_upsert_name(&self, word: &str) -> String {
573 format!("EXCLUDED.{}", word)
574 }
575 fn is_keyword(&self, word: &str) -> bool {
576 contains_ignore_case(POSTGRES_KEYWORDS, word)
577 }
578 fn escape_word(&self, word: &str) -> String {
579 format!("\"{}\"", word)
580 }
581}
582
583#[derive(Default, Debug, Clone)]
584pub struct SqliteKeywordEscaper;
585impl KeywordsEscaper for SqliteKeywordEscaper {
586 fn gen_upsert_name(&self, word: &str) -> String {
587 format!("EXCLUDED.{}", word)
588 }
589 fn is_keyword(&self, word: &str) -> bool {
590 contains_ignore_case(SQLITE_KEYWORDS, word)
591 }
592 fn escape_word(&self, word: &str) -> String {
593 format!("\"{}\"", word)
594 }
595}