use std::borrow::Cow;
pub const MYSQL_KEYWORDS: &[&str] = &[
"ACCESSIBLE",
"ADD",
"ALL",
"ALTER",
"ANALYZE",
"AND",
"AS",
"ASC",
"ASENSITIVE",
"BEFORE",
"BETWEEN",
"BIGINT",
"BINARY",
"BLOB",
"BOTH",
"BY",
"CALL",
"CASCADE",
"CASE",
"CHANGE",
"CHAR",
"CHARACTER",
"CHECK",
"COLLATE",
"COLUMN",
"CONDITION",
"CONSTRAINT",
"CONTINUE",
"CONVERT",
"CREATE",
"CROSS",
"CURRENT_DATE",
"CURRENT_TIME",
"CURRENT_TIMESTAMP",
"CURRENT_USER",
"CURSOR",
"DATABASE",
"DATABASES",
"DAY_HOUR",
"DAY_MICROSECOND",
"DAY_MINUTE",
"DAY_SECOND",
"DEC",
"DECIMAL",
"DECLARE",
"DEFAULT",
"DELAYED",
"DELETE",
"DESC",
"DESCRIBE",
"DETERMINISTIC",
"DISTINCT",
"DISTINCTROW",
"DIV",
"DOUBLE",
"DROP",
"DUAL",
"EACH",
"ELSE",
"ELSEIF",
"ENCLOSED",
"ESCAPED",
"EXISTS",
"EXIT",
"EXPLAIN",
"FALSE",
"FETCH",
"FLOAT",
"FLOAT4",
"FLOAT8",
"FOR",
"FORCE",
"FOREIGN",
"FROM",
"FULLTEXT",
"GENERATED",
"GET",
"GRANT",
"GROUP",
"HAVING",
"HIGH_PRIORITY",
"HOUR_MICROSECOND",
"HOUR_MINUTE",
"HOUR_SECOND",
"IF",
"IGNORE",
"IN",
"INDEX",
"INFILE",
"INNER",
"INOUT",
"INSENSITIVE",
"INSERT",
"INT",
"INT1",
"INT2",
"INT3",
"INT4",
"INT8",
"INTEGER",
"INTERVAL",
"INTO",
"IO_AFTER_GTIDS",
"IO_BEFORE_GTIDS",
"IS",
"ITERATE",
"JOIN",
"KEY",
"KEYS",
"KILL",
"LEADING",
"LEAVE",
"LEFT",
"LIKE",
"LIMIT",
"LINEAR",
"LINES",
"LOAD",
"LOCALTIME",
"LOCALTIMESTAMP",
"LOCK",
"LONG",
"LONGBLOB",
"LONGTEXT",
"LOOP",
"LOW_PRIORITY",
"MASTER_BIND",
"MASTER_SSL_VERIFY_SERVER_CERT",
"MATCH",
"MAXVALUE",
"MEDIUMBLOB",
"MEDIUMINT",
"MEDIUMTEXT",
"MIDDLEINT",
"MINUTE_MICROSECOND",
"MINUTE_SECOND",
"MOD",
"MODIFIES",
"NATURAL",
"NOT",
"NO_WRITE_TO_BINLOG",
"NULL",
"NUMERIC",
"ON",
"OPTIMIZE",
"OPTION",
"OPTIONALLY",
"OR",
"ORDER",
"OUT",
"OUTER",
"OUTFILE",
"PARTITION",
"PRECISION",
"PRIMARY",
"PROCEDURE",
"PURGE",
"RANGE",
"READ",
"READS",
"READ_WRITE",
"REAL",
"REFERENCES",
"REGEXP",
"RELEASE",
"RENAME",
"REPEAT",
"REPLACE",
"REQUIRE",
"RESIGNAL",
"RESTRICT",
"RETURN",
"REVOKE",
"RIGHT",
"RLIKE",
"SCHEMA",
"SCHEMAS",
"SECOND_MICROSECOND",
"SELECT",
"SENSITIVE",
"SEPARATOR",
"SET",
"SHOW",
"SIGNAL",
"SMALLINT",
"SPATIAL",
"SPECIFIC",
"SQL",
"SQLEXCEPTION",
"SQLSTATE",
"SQLWARNING",
"SQL_BIG_RESULT",
"SQL_CALC_FOUND_ROWS",
"SQL_SMALL_RESULT",
"SSL",
"STARTING",
"STORED",
"STRAIGHT_JOIN",
"TABLE",
"TERMINATED",
"THEN",
"TINYBLOB",
"TINYINT",
"TINYTEXT",
"TO",
"TRAILING",
"TRIGGER",
"TRUE",
"UNDO",
"UNION",
"UNIQUE",
"UNLOCK",
"UNSIGNED",
"UPDATE",
"USAGE",
"USE",
"USING",
"UTC_DATE",
"UTC_TIME",
"UTC_TIMESTAMP",
"VALUES",
"VARBINARY",
"VARCHAR",
"VARCHARACTER",
"VARYING",
"VIRTUAL",
"WHEN",
"WHERE",
"WHILE",
"WITH",
"WRITE",
"XOR",
"YEAR_MONTH",
"ZEROFILL",
];
pub const POSTGRES_KEYWORDS: &[&str] = &[
"ALL",
"ANALYSE",
"ANALYZE",
"AND",
"ANY",
"ARRAY",
"AS",
"ASC",
"ASYMMETRIC",
"AUTHORIZATION",
"BINARY",
"BOTH",
"CASE",
"CAST",
"CHECK",
"COLLATE",
"COLLATION",
"COLUMN",
"CONCURRENTLY",
"CONSTRAINT",
"CREATE",
"CROSS",
"CURRENT_CATALOG",
"CURRENT_DATE",
"CURRENT_ROLE",
"CURRENT_SCHEMA",
"CURRENT_TIME",
"CURRENT_TIMESTAMP",
"CURRENT_USER",
"DEFAULT",
"DEFERRABLE",
"DEFERRED",
"DELETE",
"DESC",
"DISTINCT",
"DO",
"ELSE",
"END",
"EXCEPT",
"FALSE",
"FETCH",
"FOR",
"FOREIGN",
"FREEZE",
"FROM",
"FULL",
"GRANT",
"GROUP",
"HAVING",
"ILIKE",
"IN",
"INITIALLY",
"INNER",
"INSERT",
"INTERSECT",
"INTO",
"IS",
"ISNULL",
"JOIN",
"LATERAL",
"LEADING",
"LEFT",
"LIKE",
"LIMIT",
"LOCALTIME",
"LOCALTIMESTAMP",
"NATURAL",
"NOT",
"NOTNULL",
"NULL",
"OFFSET",
"ON",
"ONLY",
"OR",
"ORDER",
"OUTER",
"OVERLAPS",
"PLACING",
"PRIMARY",
"REFERENCES",
"RETURNING",
"RIGHT",
"SELECT",
"SESSION_USER",
"SIMILAR",
"SOME",
"SYMMETRIC",
"TABLE",
"TABLESAMPLE",
"THEN",
"TO",
"TRAILING",
"TRUE",
"UNION",
"UNIQUE",
"UPDATE",
"USER",
"USING",
"VARIADIC",
"VERBOSE",
"WHEN",
"WHERE",
"WINDOW",
"WITH",
];
pub const SQLITE_KEYWORDS: &[&str] = &[
"ABORT",
"ACTION",
"ADD",
"AFTER",
"ALL",
"ALTER",
"ANALYZE",
"AND",
"AS",
"ASC",
"ATTACH",
"AUTOINCREMENT",
"BEFORE",
"BEGIN",
"BETWEEN",
"BY",
"CASCADE",
"CASE",
"CAST",
"CHECK",
"COLLATE",
"COLUMN",
"COMMIT",
"CONFLICT",
"CONSTRAINT",
"CREATE",
"CROSS",
"CURRENT_DATE",
"CURRENT_TIME",
"CURRENT_TIMESTAMP",
"DATABASE",
"DEFAULT",
"DEFERRABLE",
"DEFERRED",
"DELETE",
"DESC",
"DETACH",
"DISTINCT",
"DROP",
"EACH",
"ELSE",
"END",
"ESCAPE",
"EXCEPT",
"EXCLUSIVE",
"EXISTS",
"EXPLAIN",
"FAIL",
"FOR",
"FOREIGN",
"FROM",
"FULL",
"GLOB",
"GROUP",
"HAVING",
"IF",
"IGNORE",
"IMMEDIATE",
"IN",
"INDEX",
"INDEXED",
"INITIALLY",
"INNER",
"INSERT",
"INSTEAD",
"INTERSECT",
"INTO",
"IS",
"ISNULL",
"JOIN",
"KEY",
"LEFT",
"LIKE",
"LIMIT",
"MATCH",
"NATURAL",
"NO",
"NOT",
"NOTNULL",
"NULL",
"OF",
"OFFSET",
"ON",
"OR",
"ORDER",
"OUTER",
"PLAN",
"PRAGMA",
"PRIMARY",
"QUERY",
"RAISE",
"RECURSIVE",
"REFERENCES",
"REGEXP",
"REINDEX",
"RELEASE",
"RENAME",
"REPLACE",
"RESTRICT",
"RIGHT",
"ROLLBACK",
"ROW",
"SAVEPOINT",
"SELECT",
"SET",
"TABLE",
"TEMP",
"TEMPORARY",
"THEN",
"TO",
"TRANSACTION",
"TRIGGER",
"UNION",
"UNIQUE",
"UPDATE",
"USING",
"VACUUM",
"VALUES",
"VIEW",
"VIRTUAL",
"WHEN",
"WHERE",
"WITH",
"WITHOUT",
];
pub const COMMON_KEYWORDS: &[&str] = &[
"ALL",
"AND",
"AS",
"ASC",
"BETWEEN",
"BY",
"CASE",
"CHECK",
"COLLATE",
"COLUMN",
"CREATE",
"CROSS",
"DEFAULT",
"DELETE",
"DESC",
"DISTINCT",
"DROP",
"ELSE",
"END",
"EXISTS",
"FOREIGN",
"FROM",
"FULL",
"GROUP",
"HAVING",
"IN",
"INDEX",
"INNER",
"INSERT",
"INTO",
"IS",
"JOIN",
"LEFT",
"LIKE",
"LIMIT",
"NOT",
"NULL",
"ON",
"OR",
"ORDER",
"OUTER",
"PRIMARY",
"REFERENCES",
"SELECT",
"SET",
"TABLE",
"THEN",
"TO",
"UNION",
"UNIQUE",
"UPDATE",
"USING",
"VALUES",
"WHEN",
"WHERE",
"WITH",
];
fn contains_ignore_case<T: AsRef<str>>(haystack: &[T], needle: &str) -> bool {
let needle_lower = needle.to_lowercase();
haystack
.iter()
.any(|item| item.as_ref().to_lowercase() == needle_lower)
}
pub trait KeywordsEscaper {
fn gen_upsert_name(&self, word: &str) -> String;
fn is_keyword(&self, word: &str) -> bool;
fn escape_word(&self, word: &str) -> String;
fn escape<'a>(&self, word: &'a str) -> Cow<'a, str> {
let trimmed = word.trim();
if self.is_keyword(trimmed) {
Cow::Owned(self.escape_word(trimmed))
} else {
Cow::Borrowed(trimmed)
}
}
}
#[derive(Default, Debug, Clone)]
pub struct MySqlKeywordEscaper;
impl KeywordsEscaper for MySqlKeywordEscaper {
fn gen_upsert_name(&self, word: &str) -> String {
format!("VALUES({})", word)
}
fn is_keyword(&self, word: &str) -> bool {
contains_ignore_case(MYSQL_KEYWORDS, word)
}
fn escape_word(&self, word: &str) -> String {
format!("`{}`", word)
}
}
#[derive(Default, Debug, Clone)]
pub struct PostgresKeywordEscaper;
impl KeywordsEscaper for PostgresKeywordEscaper {
fn gen_upsert_name(&self, word: &str) -> String {
format!("EXCLUDED.{}", word)
}
fn is_keyword(&self, word: &str) -> bool {
contains_ignore_case(POSTGRES_KEYWORDS, word)
}
fn escape_word(&self, word: &str) -> String {
format!("\"{}\"", word)
}
}
#[derive(Default, Debug, Clone)]
pub struct SqliteKeywordEscaper;
impl KeywordsEscaper for SqliteKeywordEscaper {
fn gen_upsert_name(&self, word: &str) -> String {
format!("EXCLUDED.{}", word)
}
fn is_keyword(&self, word: &str) -> bool {
contains_ignore_case(SQLITE_KEYWORDS, word)
}
fn escape_word(&self, word: &str) -> String {
format!("\"{}\"", word)
}
}