sqlparser/dialect/
mssql.rs1use crate::ast::helpers::attached_token::AttachedToken;
19use crate::ast::{
20 BeginEndStatements, ConditionalStatementBlock, ConditionalStatements, IfStatement, Statement,
21};
22use crate::dialect::Dialect;
23use crate::keywords::{self, Keyword};
24use crate::parser::{Parser, ParserError};
25use crate::tokenizer::Token;
26#[cfg(not(feature = "std"))]
27use alloc::{vec, vec::Vec};
28
29const RESERVED_FOR_COLUMN_ALIAS: &[Keyword] = &[Keyword::IF, Keyword::ELSE];
30
31#[derive(Debug)]
33pub struct MsSqlDialect {}
34
35impl Dialect for MsSqlDialect {
36 fn is_delimited_identifier_start(&self, ch: char) -> bool {
37 ch == '"' || ch == '['
38 }
39
40 fn is_identifier_start(&self, ch: char) -> bool {
41 ch.is_alphabetic() || ch == '_' || ch == '#' || ch == '@'
43 }
44
45 fn is_identifier_part(&self, ch: char) -> bool {
46 ch.is_alphabetic()
47 || ch.is_ascii_digit()
48 || ch == '@'
49 || ch == '$'
50 || ch == '#'
51 || ch == '_'
52 }
53
54 fn convert_type_before_value(&self) -> bool {
57 true
58 }
59
60 fn supports_outer_join_operator(&self) -> bool {
61 true
62 }
63
64 fn supports_connect_by(&self) -> bool {
65 true
66 }
67
68 fn supports_eq_alias_assignment(&self) -> bool {
69 true
70 }
71
72 fn supports_try_convert(&self) -> bool {
73 true
74 }
75
76 fn supports_boolean_literals(&self) -> bool {
78 false
79 }
80
81 fn supports_named_fn_args_with_colon_operator(&self) -> bool {
82 true
83 }
84
85 fn supports_named_fn_args_with_expr_name(&self) -> bool {
86 true
87 }
88
89 fn supports_named_fn_args_with_rarrow_operator(&self) -> bool {
90 false
91 }
92
93 fn supports_start_transaction_modifier(&self) -> bool {
94 true
95 }
96
97 fn supports_end_transaction_modifier(&self) -> bool {
98 true
99 }
100
101 fn supports_set_stmt_without_operator(&self) -> bool {
103 true
104 }
105
106 fn supports_timestamp_versioning(&self) -> bool {
108 true
109 }
110
111 fn supports_nested_comments(&self) -> bool {
113 true
114 }
115
116 fn supports_object_name_double_dot_notation(&self) -> bool {
118 true
119 }
120
121 fn is_column_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
122 !keywords::RESERVED_FOR_COLUMN_ALIAS.contains(kw) && !RESERVED_FOR_COLUMN_ALIAS.contains(kw)
123 }
124
125 fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
126 if parser.peek_keyword(Keyword::IF) {
127 Some(self.parse_if_stmt(parser))
128 } else {
129 None
130 }
131 }
132}
133
134impl MsSqlDialect {
135 fn parse_if_stmt(&self, parser: &mut Parser) -> Result<Statement, ParserError> {
142 let if_token = parser.expect_keyword(Keyword::IF)?;
143
144 let condition = parser.parse_expr()?;
145
146 let if_block = if parser.peek_keyword(Keyword::BEGIN) {
147 let begin_token = parser.expect_keyword(Keyword::BEGIN)?;
148 let statements = self.parse_statement_list(parser, Some(Keyword::END))?;
149 let end_token = parser.expect_keyword(Keyword::END)?;
150 ConditionalStatementBlock {
151 start_token: AttachedToken(if_token),
152 condition: Some(condition),
153 then_token: None,
154 conditional_statements: ConditionalStatements::BeginEnd(BeginEndStatements {
155 begin_token: AttachedToken(begin_token),
156 statements,
157 end_token: AttachedToken(end_token),
158 }),
159 }
160 } else {
161 let stmt = parser.parse_statement()?;
162 ConditionalStatementBlock {
163 start_token: AttachedToken(if_token),
164 condition: Some(condition),
165 then_token: None,
166 conditional_statements: ConditionalStatements::Sequence {
167 statements: vec![stmt],
168 },
169 }
170 };
171
172 let mut prior_statement_ended_with_semi_colon = false;
173 while let Token::SemiColon = parser.peek_token_ref().token {
174 parser.advance_token();
175 prior_statement_ended_with_semi_colon = true;
176 }
177
178 let mut else_block = None;
179 if parser.peek_keyword(Keyword::ELSE) {
180 let else_token = parser.expect_keyword(Keyword::ELSE)?;
181 if parser.peek_keyword(Keyword::BEGIN) {
182 let begin_token = parser.expect_keyword(Keyword::BEGIN)?;
183 let statements = self.parse_statement_list(parser, Some(Keyword::END))?;
184 let end_token = parser.expect_keyword(Keyword::END)?;
185 else_block = Some(ConditionalStatementBlock {
186 start_token: AttachedToken(else_token),
187 condition: None,
188 then_token: None,
189 conditional_statements: ConditionalStatements::BeginEnd(BeginEndStatements {
190 begin_token: AttachedToken(begin_token),
191 statements,
192 end_token: AttachedToken(end_token),
193 }),
194 });
195 } else {
196 let stmt = parser.parse_statement()?;
197 else_block = Some(ConditionalStatementBlock {
198 start_token: AttachedToken(else_token),
199 condition: None,
200 then_token: None,
201 conditional_statements: ConditionalStatements::Sequence {
202 statements: vec![stmt],
203 },
204 });
205 }
206 } else if prior_statement_ended_with_semi_colon {
207 parser.prev_token();
208 }
209
210 Ok(Statement::If(IfStatement {
211 if_block,
212 else_block,
213 elseif_blocks: Vec::new(),
214 end_token: None,
215 }))
216 }
217
218 fn parse_statement_list(
222 &self,
223 parser: &mut Parser,
224 terminal_keyword: Option<Keyword>,
225 ) -> Result<Vec<Statement>, ParserError> {
226 let mut stmts = Vec::new();
227 loop {
228 if let Token::EOF = parser.peek_token_ref().token {
229 break;
230 }
231 if let Some(term) = terminal_keyword {
232 if parser.peek_keyword(term) {
233 break;
234 }
235 }
236 stmts.push(parser.parse_statement()?);
237 while let Token::SemiColon = parser.peek_token_ref().token {
238 parser.advance_token();
239 }
240 }
241 Ok(stmts)
242 }
243}