Skip to content

Commit 7ff24be

Browse files
committed
Doris: Add dialect skeleton
1 parent 5e7b007 commit 7ff24be

5 files changed

Lines changed: 115 additions & 0 deletions

File tree

examples/cli.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ $ cargo run --example cli - [--dialectname]
5252
"--postgres" => Box::new(PostgreSqlDialect {}),
5353
"--ms" => Box::new(MsSqlDialect {}),
5454
"--mysql" => Box::new(MySqlDialect {}),
55+
"--doris" => Box::new(DorisDialect {}),
5556
"--snowflake" => Box::new(SnowflakeDialect {}),
5657
"--hive" => Box::new(HiveDialect {}),
5758
"--redshift" => Box::new(RedshiftSqlDialect {}),

src/dialect/doris.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
use crate::dialect::Dialect;
19+
20+
/// A [`Dialect`] for [Apache Doris](https://doris.apache.org/).
21+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
22+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23+
pub struct DorisDialect {}
24+
25+
impl Dialect for DorisDialect {
26+
fn is_delimited_identifier_start(&self, ch: char) -> bool {
27+
ch == '`'
28+
}
29+
30+
fn identifier_quote_style(&self, _identifier: &str) -> Option<char> {
31+
Some('`')
32+
}
33+
34+
fn is_identifier_start(&self, ch: char) -> bool {
35+
ch.is_ascii_alphabetic() || ch == '_' || !ch.is_ascii()
36+
}
37+
38+
fn is_identifier_part(&self, ch: char) -> bool {
39+
self.is_identifier_start(ch) || ch.is_ascii_digit()
40+
}
41+
42+
fn supports_string_literal_backslash_escape(&self) -> bool {
43+
true
44+
}
45+
46+
fn ignores_wildcard_escapes(&self) -> bool {
47+
true
48+
}
49+
50+
fn supports_numeric_prefix(&self) -> bool {
51+
true
52+
}
53+
}

src/dialect/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mod ansi;
1919
mod bigquery;
2020
mod clickhouse;
2121
mod databricks;
22+
mod doris;
2223
mod duckdb;
2324
mod generic;
2425
mod hive;
@@ -43,6 +44,7 @@ pub use self::ansi::AnsiDialect;
4344
pub use self::bigquery::BigQueryDialect;
4445
pub use self::clickhouse::ClickHouseDialect;
4546
pub use self::databricks::DatabricksDialect;
47+
pub use self::doris::DorisDialect;
4648
pub use self::duckdb::DuckDbDialect;
4749
pub use self::generic::GenericDialect;
4850
pub use self::hive::HiveDialect;
@@ -1908,6 +1910,7 @@ pub fn dialect_from_str(dialect_name: impl AsRef<str>) -> Option<Box<dyn Dialect
19081910
"bigquery" => Some(Box::new(BigQueryDialect)),
19091911
"ansi" => Some(Box::new(AnsiDialect {})),
19101912
"duckdb" => Some(Box::new(DuckDbDialect {})),
1913+
"doris" => Some(Box::new(DorisDialect {})),
19111914
"databricks" => Some(Box::new(DatabricksDialect {})),
19121915
"spark" | "sparksql" => Some(Box::new(SparkSqlDialect {})),
19131916
"oracle" => Some(Box::new(OracleDialect {})),
@@ -1963,6 +1966,8 @@ mod tests {
19631966
assert!(parse_dialect("ANSI").is::<AnsiDialect>());
19641967
assert!(parse_dialect("duckdb").is::<DuckDbDialect>());
19651968
assert!(parse_dialect("DuckDb").is::<DuckDbDialect>());
1969+
assert!(parse_dialect("doris").is::<DorisDialect>());
1970+
assert!(parse_dialect("Doris").is::<DorisDialect>());
19661971
assert!(parse_dialect("DataBricks").is::<DatabricksDialect>());
19671972
assert!(parse_dialect("databricks").is::<DatabricksDialect>());
19681973
assert!(parse_dialect("teradata").is::<TeradataDialect>());

src/test_utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ pub fn all_dialects() -> TestedDialects {
286286
Box::new(HiveDialect {}),
287287
Box::new(RedshiftSqlDialect {}),
288288
Box::new(MySqlDialect {}),
289+
Box::new(DorisDialect {}),
289290
Box::new(BigQueryDialect {}),
290291
Box::new(SQLiteDialect {}),
291292
Box::new(DuckDbDialect {}),

tests/sqlparser_doris.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#![warn(clippy::all)]
19+
//! Test SQL syntax specific to Apache Doris.
20+
21+
#[macro_use]
22+
mod test_utils;
23+
24+
use sqlparser::dialect::{Dialect, DorisDialect, GenericDialect};
25+
use test_utils::*;
26+
27+
fn doris() -> TestedDialects {
28+
TestedDialects::new(vec![Box::new(DorisDialect {})])
29+
}
30+
31+
fn doris_and_generic() -> TestedDialects {
32+
TestedDialects::new(vec![Box::new(DorisDialect {}), Box::new(GenericDialect {})])
33+
}
34+
35+
#[test]
36+
fn doris_identifier_and_string_literal_gates() {
37+
let dialect = DorisDialect {};
38+
assert_eq!(dialect.identifier_quote_style("identifier"), Some('`'));
39+
assert!(dialect.is_delimited_identifier_start('`'));
40+
assert!(dialect.supports_string_literal_backslash_escape());
41+
assert!(dialect.ignores_wildcard_escapes());
42+
assert!(dialect.supports_numeric_prefix());
43+
}
44+
45+
#[test]
46+
fn parse_doris_strings_and_identifiers() {
47+
doris().verified_stmt(
48+
r#"SELECT "double quoted string", 'single quoted string', `select` FROM `db`.`table`"#,
49+
);
50+
}
51+
52+
#[test]
53+
fn doris_and_generic_parse_common_sql_identically() {
54+
doris_and_generic().verified_stmt("SELECT 1 AS properties FROM t");
55+
}

0 commit comments

Comments
 (0)