Skip to main content

sqruff_lib_dialects/
mysql.rs

1use sqruff_lib_core::dialects::Dialect;
2use sqruff_lib_core::dialects::init::DialectKind;
3use sqruff_lib_core::dialects::syntax::SyntaxKind;
4use sqruff_lib_core::helpers::{Config, ToMatchable};
5use sqruff_lib_core::parser::grammar::Ref;
6use sqruff_lib_core::parser::grammar::anyof::{one_of, optionally_bracketed};
7use sqruff_lib_core::parser::lexer::Matcher;
8use sqruff_lib_core::parser::node_matcher::NodeMatcher;
9
10use super::ansi;
11use sqruff_lib_core::dialects::init::{DialectConfig, NullDialectConfig};
12use sqruff_lib_core::value::Value;
13
14/// Configuration for the MySQL dialect.
15pub type MySQLDialectConfig = NullDialectConfig;
16
17pub fn dialect(config: Option<&Value>) -> Dialect {
18    // Parse and validate dialect configuration, falling back to defaults on failure
19    let _dialect_config: MySQLDialectConfig = config
20        .map(MySQLDialectConfig::from_value)
21        .unwrap_or_default();
22
23    raw_dialect().config(|dialect| dialect.expand())
24}
25
26pub fn raw_dialect() -> Dialect {
27    let mut mysql = ansi::raw_dialect();
28    mysql.name = DialectKind::Mysql;
29
30    mysql.patch_lexer_matchers(vec![Matcher::regex(
31        "inline_comment",
32        r"(^--|-- |#)[^\n]*",
33        SyntaxKind::InlineComment,
34    )]);
35
36    // MySQL 8.0+ supports CTEs with DML statements (INSERT, UPDATE, DELETE)
37    // We add these to NonWithSelectableGrammar so WithCompoundStatementSegment can use them
38    mysql.add([(
39        "NonWithSelectableGrammar".into(),
40        one_of(vec![
41            Ref::new("SetExpressionSegment").to_matchable(),
42            optionally_bracketed(vec![Ref::new("SelectStatementSegment").to_matchable()])
43                .to_matchable(),
44            Ref::new("NonSetSelectableGrammar").to_matchable(),
45            Ref::new("UpdateStatementSegment").to_matchable(),
46            Ref::new("InsertStatementSegment").to_matchable(),
47            Ref::new("DeleteStatementSegment").to_matchable(),
48        ])
49        .to_matchable()
50        .into(),
51    )]);
52
53    mysql.add([
54        (
55            "DivBinaryOperatorSegment".into(),
56            NodeMatcher::new(SyntaxKind::BinaryOperator, |_| {
57                Ref::keyword("DIV").to_matchable()
58            })
59            .to_matchable()
60            .into(),
61        ),
62        (
63            "ArithmeticBinaryOperatorGrammar".into(),
64            one_of(vec![
65                Ref::new("PlusSegment").to_matchable(),
66                Ref::new("MinusSegment").to_matchable(),
67                Ref::new("DivideSegment").to_matchable(),
68                Ref::new("MultiplySegment").to_matchable(),
69                Ref::new("ModuloSegment").to_matchable(),
70                Ref::new("BitwiseAndSegment").to_matchable(),
71                Ref::new("BitwiseOrSegment").to_matchable(),
72                Ref::new("BitwiseXorSegment").to_matchable(),
73                Ref::new("BitwiseLShiftSegment").to_matchable(),
74                Ref::new("BitwiseRShiftSegment").to_matchable(),
75                Ref::new("DivBinaryOperatorSegment").to_matchable(),
76            ])
77            .to_matchable()
78            .into(),
79        ),
80    ]);
81
82    mysql
83}