sqruff_lib_core/dialects/
init.rs1use strum::IntoEnumIterator;
2use strum_macros::AsRefStr;
3
4use crate::value::Value;
5
6pub trait DialectConfig: Default + Clone + std::fmt::Debug {
9 fn from_value(value: &Value) -> Self {
12 let _ = value;
13 Self::default()
14 }
15}
16
17#[macro_export]
32macro_rules! dialect_config {
33 ($name:ident { $(
35 $(#[doc = $doc:expr])*
36 $field:ident : $desc:expr
37 ),* $(,)? }) => {
38 #[derive(Debug, Clone)]
39 pub struct $name {
40 $($(#[doc = $doc])* pub $field: bool,)*
41 }
42
43 impl Default for $name {
44 fn default() -> Self {
45 Self { $($field: false,)* }
46 }
47 }
48
49 impl $crate::dialects::init::DialectConfig for $name {
50 fn from_value(value: &$crate::value::Value) -> Self {
51 Self {
52 $($field: value[stringify!($field)].to_bool(),)*
53 }
54 }
55 }
56
57 impl $name {
58 pub fn config_options() -> Vec<(&'static str, &'static str, &'static str)> {
59 vec![
60 $((stringify!($field), $desc, "false"),)*
61 ]
62 }
63 }
64 };
65 ($name:ident {}) => {
67 #[derive(Debug, Clone, Default)]
68 pub struct $name;
69
70 impl $crate::dialects::init::DialectConfig for $name {}
71
72 impl $name {
73 pub fn config_options() -> Vec<(&'static str, &'static str, &'static str)> {
74 vec![]
75 }
76 }
77 };
78}
79
80#[derive(
81 strum_macros::EnumString,
82 strum_macros::EnumIter,
83 AsRefStr,
84 Debug,
85 Clone,
86 Copy,
87 Default,
88 Ord,
89 PartialOrd,
90 Eq,
91 PartialEq,
92 Hash,
93)]
94#[strum(serialize_all = "snake_case")]
95pub enum DialectKind {
96 #[default]
97 Ansi,
98 Athena,
99 Bigquery,
100 Clickhouse,
101 Databricks,
102 Db2,
103 Duckdb,
104 Greenplum,
105 Mysql,
106 Oracle,
107 Postgres,
108 Redshift,
109 Snowflake,
110 Sparksql,
111 Sqlite,
112 Trino,
113 Tsql,
114}
115
116impl DialectKind {
117 pub fn name(&self) -> &'static str {
119 match self {
120 DialectKind::Ansi => "ansi",
121 DialectKind::Athena => "athena",
122 DialectKind::Bigquery => "bigquery",
123 DialectKind::Clickhouse => "clickhouse",
124 DialectKind::Databricks => "databricks",
125 DialectKind::Db2 => "db2",
126 DialectKind::Duckdb => "duckdb",
127 DialectKind::Greenplum => "greenplum",
128 DialectKind::Mysql => "mysql",
129 DialectKind::Oracle => "oracle",
130 DialectKind::Postgres => "postgres",
131 DialectKind::Redshift => "redshift",
132 DialectKind::Snowflake => "snowflake",
133 DialectKind::Sparksql => "sparksql",
134 DialectKind::Sqlite => "sqlite",
135 DialectKind::Trino => "trino",
136 DialectKind::Tsql => "tsql",
137 }
138 }
139
140 pub fn description(&self) -> &'static str {
142 match self {
143 DialectKind::Ansi => {
144 "Standard SQL syntax. The default dialect and base for all others."
145 }
146 DialectKind::Athena => "Amazon Athena SQL dialect for querying data in S3.",
147 DialectKind::Bigquery => {
148 "Google BigQuery SQL dialect for analytics and data warehousing."
149 }
150 DialectKind::Clickhouse => "ClickHouse SQL dialect for real-time analytics.",
151 DialectKind::Databricks => "Databricks SQL dialect for lakehouse analytics.",
152 DialectKind::Db2 => "IBM Db2 SQL dialect.",
153 DialectKind::Duckdb => "DuckDB SQL dialect for in-process analytical database.",
154 DialectKind::Greenplum => "Greenplum SQL dialect, a massively parallel Postgres.",
155 DialectKind::Mysql => "MySQL SQL dialect for the popular open-source database.",
156 DialectKind::Oracle => "Oracle SQL dialect for Oracle Database.",
157 DialectKind::Postgres => {
158 "PostgreSQL SQL dialect for the advanced open-source database."
159 }
160 DialectKind::Redshift => "Amazon Redshift SQL dialect for cloud data warehousing.",
161 DialectKind::Snowflake => "Snowflake SQL dialect for cloud data platform.",
162 DialectKind::Sparksql => "Apache Spark SQL dialect for big data processing.",
163 DialectKind::Sqlite => "SQLite SQL dialect for embedded database.",
164 DialectKind::Trino => "Trino (formerly PrestoSQL) dialect for distributed SQL queries.",
165 DialectKind::Tsql => "T-SQL dialect for Microsoft SQL Server and Azure SQL.",
166 }
167 }
168
169 pub fn config_section(&self) -> String {
172 format!("[sqruff:dialect:{}]", self.name())
173 }
174
175 pub fn doc_url(&self) -> Option<&'static str> {
177 match self {
178 DialectKind::Ansi => None,
179 DialectKind::Athena => {
180 Some("https://docs.aws.amazon.com/athena/latest/ug/ddl-sql-reference.html")
181 }
182 DialectKind::Bigquery => {
183 Some("https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax")
184 }
185 DialectKind::Clickhouse => Some("https://clickhouse.com/docs/en/sql-reference/"),
186 DialectKind::Databricks => {
187 Some("https://docs.databricks.com/en/sql/language-manual/index.html")
188 }
189 DialectKind::Db2 => Some("https://www.ibm.com/docs/en/i/7.4?topic=overview-db2-i"),
190 DialectKind::Duckdb => Some("https://duckdb.org/docs/sql/introduction"),
191 DialectKind::Greenplum => {
192 Some("https://docs.vmware.com/en/VMware-Greenplum/index.html")
193 }
194 DialectKind::Mysql => Some("https://dev.mysql.com/doc/"),
195 DialectKind::Oracle => {
196 Some("https://www.oracle.com/database/technologies/appdev/sql.html")
197 }
198 DialectKind::Postgres => Some("https://www.postgresql.org/docs/current/sql.html"),
199 DialectKind::Redshift => {
200 Some("https://docs.aws.amazon.com/redshift/latest/dg/cm_chap_SQLCommandRef.html")
201 }
202 DialectKind::Snowflake => Some("https://docs.snowflake.com/en/sql-reference.html"),
203 DialectKind::Sparksql => Some("https://spark.apache.org/sql/"),
204 DialectKind::Sqlite => Some("https://www.sqlite.org/lang.html"),
205 DialectKind::Trino => Some("https://trino.io/docs/current/sql.html"),
206 DialectKind::Tsql => {
207 Some("https://learn.microsoft.com/en-us/sql/t-sql/language-reference")
208 }
209 }
210 }
211}
212
213pub fn dialect_readout() -> Vec<String> {
215 DialectKind::iter()
216 .map(|x| x.as_ref().to_string())
217 .collect()
218}
219
220#[cfg(test)]
221mod tests {
222 use super::DialectKind;
223
224 #[test]
225 fn dialect_readout_is_alphabetically_sorted() {
226 let readout = super::dialect_readout();
227
228 let mut sorted = readout.clone();
229 sorted.sort();
230
231 assert_eq!(readout, sorted);
232 }
233
234 #[test]
235 fn config_section_format() {
236 assert_eq!(
237 DialectKind::Snowflake.config_section(),
238 "[sqruff:dialect:snowflake]"
239 );
240 assert_eq!(
241 DialectKind::Bigquery.config_section(),
242 "[sqruff:dialect:bigquery]"
243 );
244 assert_eq!(DialectKind::Ansi.config_section(), "[sqruff:dialect:ansi]");
245 }
246}