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