wing_sqlparser/dialect/
mod.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13mod ansi;
14mod clickhouse;
15mod generic;
16mod hive;
17mod mssql;
18mod mysql;
19mod postgresql;
20mod snowflake;
21mod sqlite;
22
23use core::any::{Any, TypeId};
24use core::fmt::Debug;
25
26pub use self::ansi::AnsiDialect;
27pub use self::clickhouse::ClickHouseDialect;
28pub use self::generic::GenericDialect;
29pub use self::hive::HiveDialect;
30pub use self::mssql::MsSqlDialect;
31pub use self::mysql::MySqlDialect;
32pub use self::postgresql::PostgreSqlDialect;
33pub use self::snowflake::SnowflakeDialect;
34pub use self::sqlite::SQLiteDialect;
35pub use crate::keywords;
36
37/// `dialect_of!(parser is SQLiteDialect |  GenericDialect)` evaluates
38/// to `true` if `parser.dialect` is one of the `Dialect`s specified.
39macro_rules! dialect_of {
40    ( $parsed_dialect: ident is $($dialect_type: ty)|+ ) => {
41        ($($parsed_dialect.dialect.is::<$dialect_type>())||+)
42    };
43}
44
45pub trait Dialect: Debug + Any {
46    /// Determine if a character starts a quoted identifier. The default
47    /// implementation, accepting "double quoted" ids is both ANSI-compliant
48    /// and appropriate for most dialects (with the notable exception of
49    /// MySQL, MS SQL, and sqlite). You can accept one of characters listed
50    /// in `Word::matching_end_quote` here
51    fn is_delimited_identifier_start(&self, ch: char) -> bool {
52        ch == '"'
53    }
54    /// Determine if a character is a valid start character for an unquoted identifier
55    fn is_identifier_start(&self, ch: char) -> bool;
56    /// Determine if a character is a valid unquoted identifier character
57    fn is_identifier_part(&self, ch: char) -> bool;
58}
59
60impl dyn Dialect {
61    #[inline]
62    pub fn is<T: Dialect>(&self) -> bool {
63        // borrowed from `Any` implementation
64        TypeId::of::<T>() == self.type_id()
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::ansi::AnsiDialect;
71    use super::generic::GenericDialect;
72    use super::*;
73
74    struct DialectHolder<'a> {
75        dialect: &'a dyn Dialect,
76    }
77
78    #[test]
79    fn test_is_dialect() {
80        let generic_dialect: &dyn Dialect = &GenericDialect {};
81        let ansi_dialect: &dyn Dialect = &AnsiDialect {};
82
83        let generic_holder = DialectHolder {
84            dialect: generic_dialect,
85        };
86        let ansi_holder = DialectHolder {
87            dialect: ansi_dialect,
88        };
89
90        assert!(dialect_of!(generic_holder is GenericDialect |  AnsiDialect),);
91        assert!(!dialect_of!(generic_holder is  AnsiDialect));
92        assert!(dialect_of!(ansi_holder is AnsiDialect));
93        assert!(dialect_of!(ansi_holder is GenericDialect | AnsiDialect));
94        assert!(!dialect_of!(ansi_holder is GenericDialect | MsSqlDialect));
95    }
96}