1use std::fmt;
16use std::str::FromStr;
17
18use crate::ast::dialect::FeatureSet;
19use crate::dialect::Ansi;
20#[cfg(feature = "bigquery")]
21use crate::dialect::BigQuery;
22#[cfg(feature = "clickhouse")]
23use crate::dialect::ClickHouse;
24#[cfg(feature = "databricks")]
25use crate::dialect::Databricks;
26#[cfg(feature = "duckdb")]
27use crate::dialect::DuckDb;
28#[cfg(feature = "hive")]
29use crate::dialect::Hive;
30#[cfg(feature = "lenient")]
31use crate::dialect::Lenient;
32#[cfg(feature = "mssql")]
33use crate::dialect::Mssql;
34#[cfg(feature = "mysql")]
35use crate::dialect::MySql;
36#[cfg(feature = "postgres")]
37use crate::dialect::Postgres;
38#[cfg(feature = "redshift")]
39use crate::dialect::Redshift;
40#[cfg(feature = "snowflake")]
41use crate::dialect::Snowflake;
42#[cfg(feature = "sqlite")]
43use crate::dialect::Sqlite;
44use crate::error::ParseResult;
45use crate::parser::{
46 ParseOptions, Parsed, Recovered, parse_recovering_with_options, parse_with_options,
47};
48use crate::render::RenderDialect;
49use crate::tokenizer::{LexError, Token, TriviaIndex, tokenize_with, tokenize_with_trivia};
50
51#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
77#[non_exhaustive]
78pub enum BuiltinDialect {
79 Ansi,
81 #[cfg(feature = "postgres")]
83 Postgres,
84 #[cfg(feature = "mysql")]
86 MySql,
87 #[cfg(feature = "sqlite")]
89 Sqlite,
90 #[cfg(feature = "duckdb")]
92 DuckDb,
93 #[cfg(feature = "bigquery")]
95 BigQuery,
96 #[cfg(feature = "hive")]
98 Hive,
99 #[cfg(feature = "clickhouse")]
101 ClickHouse,
102 #[cfg(feature = "databricks")]
104 Databricks,
105 #[cfg(feature = "mssql")]
107 Mssql,
108 #[cfg(feature = "snowflake")]
110 Snowflake,
111 #[cfg(feature = "redshift")]
113 Redshift,
114 #[cfg(feature = "lenient")]
117 Lenient,
118}
119
120impl BuiltinDialect {
121 pub const ALL: &'static [BuiltinDialect] = &[
127 BuiltinDialect::Ansi,
128 #[cfg(feature = "postgres")]
129 BuiltinDialect::Postgres,
130 #[cfg(feature = "mysql")]
131 BuiltinDialect::MySql,
132 #[cfg(feature = "sqlite")]
133 BuiltinDialect::Sqlite,
134 #[cfg(feature = "duckdb")]
135 BuiltinDialect::DuckDb,
136 #[cfg(feature = "bigquery")]
137 BuiltinDialect::BigQuery,
138 #[cfg(feature = "hive")]
139 BuiltinDialect::Hive,
140 #[cfg(feature = "clickhouse")]
141 BuiltinDialect::ClickHouse,
142 #[cfg(feature = "databricks")]
143 BuiltinDialect::Databricks,
144 #[cfg(feature = "mssql")]
145 BuiltinDialect::Mssql,
146 #[cfg(feature = "snowflake")]
147 BuiltinDialect::Snowflake,
148 #[cfg(feature = "redshift")]
149 BuiltinDialect::Redshift,
150 #[cfg(feature = "lenient")]
151 BuiltinDialect::Lenient,
152 ];
153
154 pub fn from_name(name: &str) -> Option<Self> {
171 if name.eq_ignore_ascii_case("ansi") || name.eq_ignore_ascii_case("generic") {
172 return Some(Self::Ansi);
173 }
174 #[cfg(feature = "postgres")]
175 if name.eq_ignore_ascii_case("postgres")
176 || name.eq_ignore_ascii_case("postgresql")
177 || name.eq_ignore_ascii_case("pg")
178 {
179 return Some(Self::Postgres);
180 }
181 #[cfg(feature = "mysql")]
182 if name.eq_ignore_ascii_case("mysql") || name.eq_ignore_ascii_case("mariadb") {
183 return Some(Self::MySql);
184 }
185 #[cfg(feature = "sqlite")]
186 if name.eq_ignore_ascii_case("sqlite") || name.eq_ignore_ascii_case("sqlite3") {
187 return Some(Self::Sqlite);
188 }
189 #[cfg(feature = "duckdb")]
190 if name.eq_ignore_ascii_case("duckdb") || name.eq_ignore_ascii_case("duck") {
191 return Some(Self::DuckDb);
192 }
193 #[cfg(feature = "bigquery")]
194 if name.eq_ignore_ascii_case("bigquery")
195 || name.eq_ignore_ascii_case("bq")
196 || name.eq_ignore_ascii_case("zetasql")
197 {
198 return Some(Self::BigQuery);
199 }
200 #[cfg(feature = "hive")]
201 if name.eq_ignore_ascii_case("hive") || name.eq_ignore_ascii_case("hiveql") {
202 return Some(Self::Hive);
203 }
204 #[cfg(feature = "clickhouse")]
205 if name.eq_ignore_ascii_case("clickhouse") || name.eq_ignore_ascii_case("ch") {
206 return Some(Self::ClickHouse);
207 }
208 #[cfg(feature = "databricks")]
209 if name.eq_ignore_ascii_case("databricks") || name.eq_ignore_ascii_case("dbx") {
210 return Some(Self::Databricks);
211 }
212 #[cfg(feature = "mssql")]
213 if name.eq_ignore_ascii_case("mssql")
214 || name.eq_ignore_ascii_case("tsql")
215 || name.eq_ignore_ascii_case("sqlserver")
216 {
217 return Some(Self::Mssql);
218 }
219 #[cfg(feature = "snowflake")]
220 if name.eq_ignore_ascii_case("snowflake") || name.eq_ignore_ascii_case("sf") {
221 return Some(Self::Snowflake);
222 }
223 #[cfg(feature = "redshift")]
227 if name.eq_ignore_ascii_case("redshift") || name.eq_ignore_ascii_case("amazonredshift") {
228 return Some(Self::Redshift);
229 }
230 #[cfg(feature = "lenient")]
231 if name.eq_ignore_ascii_case("lenient") || name.eq_ignore_ascii_case("permissive") {
232 return Some(Self::Lenient);
233 }
234 None
235 }
236
237 pub const fn name(self) -> &'static str {
240 match self {
241 Self::Ansi => "ansi",
242 #[cfg(feature = "postgres")]
243 Self::Postgres => "postgres",
244 #[cfg(feature = "mysql")]
245 Self::MySql => "mysql",
246 #[cfg(feature = "sqlite")]
247 Self::Sqlite => "sqlite",
248 #[cfg(feature = "duckdb")]
249 Self::DuckDb => "duckdb",
250 #[cfg(feature = "bigquery")]
251 Self::BigQuery => "bigquery",
252 #[cfg(feature = "hive")]
253 Self::Hive => "hive",
254 #[cfg(feature = "clickhouse")]
255 Self::ClickHouse => "clickhouse",
256 #[cfg(feature = "databricks")]
257 Self::Databricks => "databricks",
258 #[cfg(feature = "mssql")]
259 Self::Mssql => "mssql",
260 #[cfg(feature = "snowflake")]
261 Self::Snowflake => "snowflake",
262 #[cfg(feature = "redshift")]
263 Self::Redshift => "redshift",
264 #[cfg(feature = "lenient")]
265 Self::Lenient => "lenient",
266 }
267 }
268
269 pub const fn aliases(self) -> &'static [&'static str] {
272 match self {
273 Self::Ansi => &["ansi", "generic"],
274 #[cfg(feature = "postgres")]
275 Self::Postgres => &["postgres", "postgresql", "pg"],
276 #[cfg(feature = "mysql")]
277 Self::MySql => &["mysql", "mariadb"],
278 #[cfg(feature = "sqlite")]
279 Self::Sqlite => &["sqlite", "sqlite3"],
280 #[cfg(feature = "duckdb")]
281 Self::DuckDb => &["duckdb", "duck"],
282 #[cfg(feature = "bigquery")]
283 Self::BigQuery => &["bigquery", "bq", "zetasql"],
284 #[cfg(feature = "hive")]
285 Self::Hive => &["hive", "hiveql"],
286 #[cfg(feature = "clickhouse")]
287 Self::ClickHouse => &["clickhouse", "ch"],
288 #[cfg(feature = "databricks")]
289 Self::Databricks => &["databricks", "dbx"],
290 #[cfg(feature = "mssql")]
291 Self::Mssql => &["mssql", "tsql", "sqlserver"],
292 #[cfg(feature = "snowflake")]
293 Self::Snowflake => &["snowflake", "sf"],
294 #[cfg(feature = "redshift")]
295 Self::Redshift => &["redshift", "amazonredshift"],
296 #[cfg(feature = "lenient")]
297 Self::Lenient => &["lenient", "permissive"],
298 }
299 }
300
301 pub fn features(self) -> &'static FeatureSet {
305 match self {
306 Self::Ansi => &FeatureSet::ANSI,
307 #[cfg(feature = "postgres")]
308 Self::Postgres => &FeatureSet::POSTGRES,
309 #[cfg(feature = "mysql")]
310 Self::MySql => &FeatureSet::MYSQL,
311 #[cfg(feature = "sqlite")]
312 Self::Sqlite => &FeatureSet::SQLITE,
313 #[cfg(feature = "duckdb")]
314 Self::DuckDb => &FeatureSet::DUCKDB,
315 #[cfg(feature = "bigquery")]
316 Self::BigQuery => &FeatureSet::BIGQUERY,
317 #[cfg(feature = "hive")]
318 Self::Hive => &FeatureSet::HIVE,
319 #[cfg(feature = "clickhouse")]
320 Self::ClickHouse => &FeatureSet::CLICKHOUSE,
321 #[cfg(feature = "databricks")]
322 Self::Databricks => &FeatureSet::DATABRICKS,
323 #[cfg(feature = "mssql")]
324 Self::Mssql => &FeatureSet::MSSQL,
325 #[cfg(feature = "snowflake")]
326 Self::Snowflake => &FeatureSet::SNOWFLAKE,
327 #[cfg(feature = "redshift")]
328 Self::Redshift => &FeatureSet::REDSHIFT,
329 #[cfg(feature = "lenient")]
330 Self::Lenient => &FeatureSet::LENIENT,
331 }
332 }
333}
334
335impl fmt::Display for BuiltinDialect {
342 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
345 f.write_str(self.name())
346 }
347}
348
349impl FromStr for BuiltinDialect {
350 type Err = ParseBuiltinDialectError;
351
352 fn from_str(s: &str) -> Result<Self, Self::Err> {
356 Self::from_name(s).ok_or_else(|| ParseBuiltinDialectError { name: s.into() })
357 }
358}
359
360impl Default for BuiltinDialect {
361 fn default() -> Self {
364 Self::Ansi
365 }
366}
367
368#[derive(Clone, Debug, PartialEq, Eq)]
375pub struct ParseBuiltinDialectError {
376 name: Box<str>,
377}
378
379impl ParseBuiltinDialectError {
380 pub fn name(&self) -> &str {
382 &self.name
383 }
384}
385
386impl fmt::Display for ParseBuiltinDialectError {
387 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
388 write!(
389 f,
390 "unknown built-in dialect {:?}: not a recognized name or alias, or its dialect \
391 is not compiled into this build",
392 self.name,
393 )
394 }
395}
396
397impl std::error::Error for ParseBuiltinDialectError {}
398
399pub fn parse_with_builtin(src: &str, dialect: BuiltinDialect) -> ParseResult<Parsed> {
423 parse_with_builtin_options(src, dialect, ParseOptions::default())
424}
425
426pub fn parse_with_builtin_options(
433 src: &str,
434 dialect: BuiltinDialect,
435 options: ParseOptions,
436) -> ParseResult<Parsed> {
437 match dialect {
438 BuiltinDialect::Ansi => parse_with_options(src, Ansi, options),
439 #[cfg(feature = "postgres")]
440 BuiltinDialect::Postgres => parse_with_options(src, Postgres, options),
441 #[cfg(feature = "mysql")]
442 BuiltinDialect::MySql => parse_with_options(src, MySql, options),
443 #[cfg(feature = "sqlite")]
444 BuiltinDialect::Sqlite => parse_with_options(src, Sqlite, options),
445 #[cfg(feature = "duckdb")]
446 BuiltinDialect::DuckDb => parse_with_options(src, DuckDb, options),
447 #[cfg(feature = "bigquery")]
448 BuiltinDialect::BigQuery => parse_with_options(src, BigQuery, options),
449 #[cfg(feature = "hive")]
450 BuiltinDialect::Hive => parse_with_options(src, Hive, options),
451 #[cfg(feature = "clickhouse")]
452 BuiltinDialect::ClickHouse => parse_with_options(src, ClickHouse, options),
453 #[cfg(feature = "databricks")]
454 BuiltinDialect::Databricks => parse_with_options(src, Databricks, options),
455 #[cfg(feature = "mssql")]
456 BuiltinDialect::Mssql => parse_with_options(src, Mssql, options),
457 #[cfg(feature = "snowflake")]
458 BuiltinDialect::Snowflake => parse_with_options(src, Snowflake, options),
459 #[cfg(feature = "redshift")]
460 BuiltinDialect::Redshift => parse_with_options(src, Redshift, options),
461 #[cfg(feature = "lenient")]
462 BuiltinDialect::Lenient => parse_with_options(src, Lenient, options),
463 }
464}
465
466pub fn parse_recovering_with_builtin(src: &str, dialect: BuiltinDialect) -> ParseResult<Recovered> {
469 parse_recovering_with_builtin_options(src, dialect, ParseOptions::default())
470}
471
472pub fn parse_recovering_with_builtin_options(
474 src: &str,
475 dialect: BuiltinDialect,
476 options: ParseOptions,
477) -> ParseResult<Recovered> {
478 match dialect {
479 BuiltinDialect::Ansi => parse_recovering_with_options(src, Ansi, options),
480 #[cfg(feature = "postgres")]
481 BuiltinDialect::Postgres => parse_recovering_with_options(src, Postgres, options),
482 #[cfg(feature = "mysql")]
483 BuiltinDialect::MySql => parse_recovering_with_options(src, MySql, options),
484 #[cfg(feature = "sqlite")]
485 BuiltinDialect::Sqlite => parse_recovering_with_options(src, Sqlite, options),
486 #[cfg(feature = "duckdb")]
487 BuiltinDialect::DuckDb => parse_recovering_with_options(src, DuckDb, options),
488 #[cfg(feature = "bigquery")]
489 BuiltinDialect::BigQuery => parse_recovering_with_options(src, BigQuery, options),
490 #[cfg(feature = "hive")]
491 BuiltinDialect::Hive => parse_recovering_with_options(src, Hive, options),
492 #[cfg(feature = "clickhouse")]
493 BuiltinDialect::ClickHouse => parse_recovering_with_options(src, ClickHouse, options),
494 #[cfg(feature = "databricks")]
495 BuiltinDialect::Databricks => parse_recovering_with_options(src, Databricks, options),
496 #[cfg(feature = "mssql")]
497 BuiltinDialect::Mssql => parse_recovering_with_options(src, Mssql, options),
498 #[cfg(feature = "snowflake")]
499 BuiltinDialect::Snowflake => parse_recovering_with_options(src, Snowflake, options),
500 #[cfg(feature = "redshift")]
501 BuiltinDialect::Redshift => parse_recovering_with_options(src, Redshift, options),
502 #[cfg(feature = "lenient")]
503 BuiltinDialect::Lenient => parse_recovering_with_options(src, Lenient, options),
504 }
505}
506
507pub fn tokenize_with_builtin(src: &str, dialect: BuiltinDialect) -> Result<Vec<Token>, LexError> {
509 tokenize_with(src, dialect.features())
510}
511
512pub fn tokenize_with_builtin_trivia(
514 src: &str,
515 dialect: BuiltinDialect,
516) -> Result<(Vec<Token>, TriviaIndex), LexError> {
517 tokenize_with_trivia(src, dialect.features())
518}
519
520impl RenderDialect for BuiltinDialect {
521 fn render_features(&self) -> FeatureSet {
522 self.features().clone()
523 }
524}
525
526#[cfg(test)]
527mod tests {
528 use super::*;
529
530 #[test]
531 fn ansi_is_always_built_in_and_round_trips_its_name() {
532 let ansi = BuiltinDialect::from_name("ansi").expect("ansi resolves");
533 assert_eq!(ansi, BuiltinDialect::Ansi);
534 assert_eq!(
536 BuiltinDialect::from_name("ANSI"),
537 Some(BuiltinDialect::Ansi)
538 );
539 assert_eq!(
540 BuiltinDialect::from_name("Generic"),
541 Some(BuiltinDialect::Ansi)
542 );
543 for dialect in BuiltinDialect::ALL {
545 assert_eq!(BuiltinDialect::from_name(dialect.name()), Some(*dialect));
546 }
547 assert_eq!(BuiltinDialect::Ansi.features(), &FeatureSet::ANSI);
548 }
549
550 #[test]
551 fn unknown_name_is_a_clean_none() {
552 for name in ["", "oracle", "postgre", "my sql"] {
560 assert_eq!(BuiltinDialect::from_name(name), None, "{name:?}");
561 }
562 }
563
564 #[test]
565 fn display_and_fromstr_round_trip_over_all_including_aliases_and_case() {
566 for &dialect in BuiltinDialect::ALL {
567 assert_eq!(dialect.to_string(), dialect.name());
570 assert_eq!(dialect.name().parse::<BuiltinDialect>(), Ok(dialect));
571 assert_eq!(dialect.to_string().parse::<BuiltinDialect>(), Ok(dialect));
572 for alias in dialect.aliases() {
574 assert_eq!(alias.parse::<BuiltinDialect>(), Ok(dialect), "{alias:?}");
575 assert_eq!(
576 alias.to_uppercase().parse::<BuiltinDialect>(),
577 Ok(dialect),
578 "{alias:?} upper",
579 );
580 }
581 }
582 assert_eq!(BuiltinDialect::default(), BuiltinDialect::Ansi);
583 }
584
585 #[test]
586 fn fromstr_error_carries_the_name_and_is_a_std_error() {
587 let err = "no-such-dialect".parse::<BuiltinDialect>().unwrap_err();
588 assert_eq!(err.name(), "no-such-dialect");
589 let as_error: &dyn std::error::Error = &err;
591 assert!(as_error.to_string().contains("no-such-dialect"));
592 }
593
594 #[test]
595 fn parse_with_builtin_parses_under_ansi() {
596 let parsed = parse_with_builtin("SELECT 1", BuiltinDialect::Ansi).expect("parses");
597 assert_eq!(parsed.statements().len(), 1);
598 }
599
600 #[cfg(feature = "postgres")]
601 #[test]
602 fn postgres_builtin_resolves_and_parses_its_surface() {
603 assert_eq!(
604 BuiltinDialect::from_name("postgresql"),
605 Some(BuiltinDialect::Postgres)
606 );
607 assert_eq!(
608 BuiltinDialect::from_name("PG"),
609 Some(BuiltinDialect::Postgres)
610 );
611 assert_eq!(BuiltinDialect::Postgres.features(), &FeatureSet::POSTGRES);
612 assert!(parse_with_builtin("SELECT $1", BuiltinDialect::Postgres).is_ok());
615 assert!(parse_with_builtin("SELECT $1", BuiltinDialect::Ansi).is_err());
616 }
617
618 #[cfg(feature = "mysql")]
619 #[test]
620 fn mysql_builtin_resolves_and_parses_its_surface() {
621 assert_eq!(
622 BuiltinDialect::from_name("MySQL"),
623 Some(BuiltinDialect::MySql)
624 );
625 assert_eq!(BuiltinDialect::MySql.features(), &FeatureSet::MYSQL);
626 assert!(parse_with_builtin("SELECT a FROM t LIMIT 5, 10", BuiltinDialect::MySql).is_ok());
629 assert!(parse_with_builtin("SELECT a FROM t LIMIT 5, 10", BuiltinDialect::Ansi).is_err());
630 }
631
632 #[cfg(feature = "sqlite")]
633 #[test]
634 fn sqlite_builtin_resolves_and_parses_its_surface() {
635 assert_eq!(
636 BuiltinDialect::from_name("SQLite"),
637 Some(BuiltinDialect::Sqlite)
638 );
639 assert_eq!(
640 BuiltinDialect::from_name("sqlite3"),
641 Some(BuiltinDialect::Sqlite)
642 );
643 assert_eq!(BuiltinDialect::Sqlite.features(), &FeatureSet::SQLITE);
644 assert!(parse_with_builtin("SELECT 1 == 1", BuiltinDialect::Sqlite).is_ok());
647 assert!(parse_with_builtin("SELECT 1 == 1", BuiltinDialect::Ansi).is_err());
648 assert!(parse_with_builtin("SELECT $value", BuiltinDialect::Sqlite).is_ok());
649 }
650
651 #[cfg(feature = "duckdb")]
652 #[test]
653 fn duckdb_builtin_resolves_and_parses_its_surface() {
654 assert_eq!(
655 BuiltinDialect::from_name("DuckDB"),
656 Some(BuiltinDialect::DuckDb)
657 );
658 assert_eq!(
659 BuiltinDialect::from_name("duck"),
660 Some(BuiltinDialect::DuckDb)
661 );
662 assert_eq!(BuiltinDialect::DuckDb.features(), &FeatureSet::DUCKDB);
663 assert!(parse_with_builtin("SELECT 0xFF + 1", BuiltinDialect::DuckDb).is_ok());
667 assert!(parse_with_builtin("SELECT 0xFF + 1", BuiltinDialect::Ansi).is_err());
668 assert!(parse_with_builtin("SELECT", BuiltinDialect::DuckDb).is_err());
671 }
672
673 #[cfg(feature = "bigquery")]
674 #[test]
675 fn bigquery_builtin_resolves_and_parses_its_surface() {
676 assert_eq!(
677 BuiltinDialect::from_name("BigQuery"),
678 Some(BuiltinDialect::BigQuery)
679 );
680 assert_eq!(
682 BuiltinDialect::from_name("bq"),
683 Some(BuiltinDialect::BigQuery)
684 );
685 assert_eq!(
686 BuiltinDialect::from_name("ZetaSQL"),
687 Some(BuiltinDialect::BigQuery)
688 );
689 assert_eq!(BuiltinDialect::BigQuery.features(), &FeatureSet::BIGQUERY);
690 assert!(
694 parse_with_builtin(
695 "SELECT * FROM UNNEST(arr) WITH OFFSET AS pos",
696 BuiltinDialect::BigQuery
697 )
698 .is_ok()
699 );
700 assert!(
701 parse_with_builtin(
702 "SELECT * FROM UNNEST(arr) WITH OFFSET AS pos",
703 BuiltinDialect::Ansi
704 )
705 .is_err()
706 );
707 }
708
709 #[cfg(feature = "hive")]
710 #[test]
711 fn hive_builtin_resolves_and_parses_its_surface() {
712 assert_eq!(
713 BuiltinDialect::from_name("Hive"),
714 Some(BuiltinDialect::Hive)
715 );
716 assert_eq!(
718 BuiltinDialect::from_name("HiveQL"),
719 Some(BuiltinDialect::Hive)
720 );
721 assert_eq!(BuiltinDialect::Hive.features(), &FeatureSet::HIVE);
722 assert!(
726 parse_with_builtin(
727 "SELECT * FROM a LEFT SEMI JOIN b ON a.x = b.x",
728 BuiltinDialect::Hive
729 )
730 .is_ok()
731 );
732 assert!(
733 parse_with_builtin(
734 "SELECT * FROM a LEFT SEMI JOIN b ON a.x = b.x",
735 BuiltinDialect::Ansi
736 )
737 .is_err()
738 );
739 }
740
741 #[cfg(feature = "clickhouse")]
742 #[test]
743 fn clickhouse_builtin_resolves_and_parses_its_surface() {
744 assert_eq!(
745 BuiltinDialect::from_name("ClickHouse"),
746 Some(BuiltinDialect::ClickHouse)
747 );
748 assert_eq!(
749 BuiltinDialect::from_name("ch"),
750 Some(BuiltinDialect::ClickHouse)
751 );
752 assert_eq!(
753 BuiltinDialect::ClickHouse.features(),
754 &FeatureSet::CLICKHOUSE
755 );
756 assert!(
760 parse_with_builtin(
761 "SELECT a FROM t SETTINGS max_threads = 8",
762 BuiltinDialect::ClickHouse
763 )
764 .is_ok()
765 );
766 assert!(
767 parse_with_builtin(
768 "SELECT a FROM t SETTINGS max_threads = 8",
769 BuiltinDialect::Ansi
770 )
771 .is_err()
772 );
773 }
774
775 #[cfg(feature = "snowflake")]
776 #[test]
777 fn snowflake_builtin_resolves_and_parses_its_surface() {
778 assert_eq!(
779 BuiltinDialect::from_name("Snowflake"),
780 Some(BuiltinDialect::Snowflake)
781 );
782 assert_eq!(
783 BuiltinDialect::from_name("sf"),
784 Some(BuiltinDialect::Snowflake)
785 );
786 assert_eq!(BuiltinDialect::Snowflake.features(), &FeatureSet::SNOWFLAKE);
787 assert!(
791 parse_with_builtin("SELECT src:customer[0].name", BuiltinDialect::Snowflake).is_ok()
792 );
793 assert!(parse_with_builtin("SELECT src:customer[0].name", BuiltinDialect::Ansi).is_err());
794 }
795
796 #[cfg(feature = "redshift")]
797 #[test]
798 fn redshift_builtin_resolves_and_defers_its_pg_heritage_surface() {
799 assert_eq!(
800 BuiltinDialect::from_name("Redshift"),
801 Some(BuiltinDialect::Redshift)
802 );
803 assert_eq!(
805 BuiltinDialect::from_name("AmazonRedshift"),
806 Some(BuiltinDialect::Redshift)
807 );
808 assert_eq!(BuiltinDialect::from_name("rs"), None);
810 assert_eq!(BuiltinDialect::Redshift.features(), &FeatureSet::REDSHIFT);
811 assert!(parse_with_builtin("SELECT \"Col\" FROM t", BuiltinDialect::Redshift).is_ok());
814 assert!(
818 parse_with_builtin(
819 "SELECT * FROM t WHERE name ILIKE 'a%'",
820 BuiltinDialect::Redshift
821 )
822 .is_err()
823 );
824 }
825
826 #[cfg(feature = "databricks")]
827 #[test]
828 fn databricks_builtin_resolves_and_parses_its_surface() {
829 assert_eq!(
830 BuiltinDialect::from_name("Databricks"),
831 Some(BuiltinDialect::Databricks)
832 );
833 assert_eq!(
834 BuiltinDialect::from_name("dbx"),
835 Some(BuiltinDialect::Databricks)
836 );
837 assert_eq!(
838 BuiltinDialect::Databricks.features(),
839 &FeatureSet::DATABRICKS
840 );
841 assert!(
845 parse_with_builtin(
846 "SELECT * FROM a LEFT SEMI JOIN b ON a.x = b.x",
847 BuiltinDialect::Databricks
848 )
849 .is_ok()
850 );
851 assert!(
852 parse_with_builtin(
853 "SELECT * FROM a LEFT SEMI JOIN b ON a.x = b.x",
854 BuiltinDialect::Ansi
855 )
856 .is_err()
857 );
858 }
859
860 #[cfg(feature = "mssql")]
861 #[test]
862 fn mssql_builtin_resolves_and_parses_its_surface() {
863 assert_eq!(
864 BuiltinDialect::from_name("MSSQL"),
865 Some(BuiltinDialect::Mssql)
866 );
867 assert_eq!(
869 BuiltinDialect::from_name("tsql"),
870 Some(BuiltinDialect::Mssql)
871 );
872 assert_eq!(
873 BuiltinDialect::from_name("SqlServer"),
874 Some(BuiltinDialect::Mssql)
875 );
876 assert_eq!(BuiltinDialect::Mssql.features(), &FeatureSet::MSSQL);
877 assert!(
881 parse_with_builtin(
882 "SELECT * FROM a CROSS APPLY (SELECT 1) AS t",
883 BuiltinDialect::Mssql
884 )
885 .is_ok()
886 );
887 assert!(
888 parse_with_builtin(
889 "SELECT * FROM a CROSS APPLY (SELECT 1) AS t",
890 BuiltinDialect::Ansi
891 )
892 .is_err()
893 );
894 }
895
896 #[cfg(feature = "lenient")]
897 #[test]
898 fn lenient_builtin_resolves_and_parses_its_union() {
899 assert_eq!(
900 BuiltinDialect::from_name("Lenient"),
901 Some(BuiltinDialect::Lenient)
902 );
903 assert_eq!(
904 BuiltinDialect::from_name("permissive"),
905 Some(BuiltinDialect::Lenient)
906 );
907 assert_eq!(BuiltinDialect::Lenient.features(), &FeatureSet::LENIENT);
908 assert!(
912 parse_with_builtin(r#"SELECT "a", `b`, [c] FROM t"#, BuiltinDialect::Lenient).is_ok()
913 );
914 assert!(parse_with_builtin("SELECT `b` FROM t", BuiltinDialect::Ansi).is_err());
915 }
916}