1use crate::ast::helpers::attached_token::AttachedToken;
19use crate::ast::{
20 BeginEndStatements, ConditionalStatementBlock, ConditionalStatements, CreateTrigger,
21 GranteesType, IfStatement, Statement,
22};
23use crate::dialect::Dialect;
24use crate::keywords::Keyword;
25use crate::parser::{Parser, ParserError};
26use crate::tokenizer::Token;
27#[cfg(not(feature = "std"))]
28use alloc::{vec, vec::Vec};
29
30#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
32#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
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 identifier_quote_style(&self, _identifier: &str) -> Option<char> {
55 Some('[')
56 }
57
58 fn convert_type_before_value(&self) -> bool {
61 true
62 }
63
64 fn supports_outer_join_operator(&self) -> bool {
65 true
66 }
67
68 fn supports_dollar_as_money_prefix(&self) -> bool {
71 true
72 }
73
74 fn supports_create_proc_syntax(&self) -> bool {
75 true
76 }
77
78 fn supports_connect_by(&self) -> bool {
79 true
80 }
81
82 fn supports_eq_alias_assignment(&self) -> bool {
83 true
84 }
85
86 fn supports_try_convert(&self) -> bool {
87 true
88 }
89
90 fn supports_boolean_literals(&self) -> bool {
92 false
93 }
94
95 fn supports_named_fn_args_with_colon_operator(&self) -> bool {
96 true
97 }
98
99 fn supports_named_fn_args_with_expr_name(&self) -> bool {
100 true
101 }
102
103 fn supports_named_fn_args_with_rarrow_operator(&self) -> bool {
104 false
105 }
106
107 fn supports_start_transaction_modifier(&self) -> bool {
108 true
109 }
110
111 fn supports_end_transaction_modifier(&self) -> bool {
112 true
113 }
114
115 fn supports_set_stmt_without_operator(&self) -> bool {
117 true
118 }
119
120 fn supports_table_versioning(&self) -> bool {
122 true
123 }
124
125 fn supports_nested_comments(&self) -> bool {
127 true
128 }
129
130 fn supports_object_name_double_dot_notation(&self) -> bool {
132 true
133 }
134
135 fn get_reserved_grantees_types(&self) -> &[GranteesType] {
137 &[GranteesType::Public]
138 }
139
140 fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
141 match kw {
142 Keyword::IF
149 | Keyword::ELSE
150 | Keyword::DECLARE
151 | Keyword::EXEC
152 | Keyword::EXECUTE
153 | Keyword::INSERT
154 | Keyword::UPDATE
155 | Keyword::DELETE
156 | Keyword::DROP
157 | Keyword::CREATE
158 | Keyword::ALTER
159 | Keyword::TRUNCATE
160 | Keyword::PRINT
161 | Keyword::WHILE
162 | Keyword::RETURN
163 | Keyword::THROW
164 | Keyword::RAISERROR
165 | Keyword::MERGE => false,
166 _ => explicit || self.is_column_alias(kw, parser),
167 }
168 }
169
170 fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
171 match kw {
172 Keyword::IF
183 | Keyword::ELSE
184 | Keyword::DECLARE
185 | Keyword::EXEC
186 | Keyword::EXECUTE
187 | Keyword::INSERT
188 | Keyword::UPDATE
189 | Keyword::DELETE
190 | Keyword::DROP
191 | Keyword::CREATE
192 | Keyword::ALTER
193 | Keyword::TRUNCATE
194 | Keyword::PRINT
195 | Keyword::WHILE
196 | Keyword::RETURN
197 | Keyword::THROW
198 | Keyword::RAISERROR
199 | Keyword::MERGE => false,
200 _ => explicit || self.is_table_alias(kw, parser),
201 }
202 }
203
204 fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
205 if parser.parse_keyword(Keyword::BEGIN) {
206 let is_block = parser
208 .maybe_parse(|p| {
209 if p.parse_transaction_modifier().is_some()
210 || p.parse_one_of_keywords(&[
211 Keyword::TRANSACTION,
212 Keyword::WORK,
213 Keyword::TRAN,
214 ])
215 .is_some()
216 || matches!(p.peek_token_ref().token, Token::SemiColon | Token::EOF)
217 {
218 p.expected_ref("statement", p.peek_token_ref())
219 } else {
220 Ok(())
221 }
222 })
223 .unwrap_or(None)
224 .is_some();
225 if is_block {
226 Some(parser.parse_begin_exception_end())
227 } else {
228 parser.prev_token();
229 None
230 }
231 } else if parser.peek_keyword(Keyword::IF) {
232 Some(self.parse_if_stmt(parser))
233 } else if parser.parse_keywords(&[Keyword::CREATE, Keyword::TRIGGER]) {
234 Some(self.parse_create_trigger(parser, false))
235 } else if parser.parse_keywords(&[
236 Keyword::CREATE,
237 Keyword::OR,
238 Keyword::ALTER,
239 Keyword::TRIGGER,
240 ]) {
241 Some(self.parse_create_trigger(parser, true))
242 } else {
243 None
244 }
245 }
246
247 fn get_next_precedence(&self, parser: &Parser) -> Option<Result<u8, ParserError>> {
248 let token = parser.peek_token_ref();
249 match &token.token {
250 Token::Colon => Some(Ok(self.prec_unknown())),
252 _ => None,
253 }
254 }
255}
256
257impl MsSqlDialect {
258 fn parse_if_stmt(&self, parser: &mut Parser) -> Result<Statement, ParserError> {
265 let if_token = parser.expect_keyword(Keyword::IF)?;
266
267 let condition = parser.parse_expr()?;
268
269 let if_block = if parser.peek_keyword(Keyword::BEGIN) {
270 let begin_token = parser.expect_keyword(Keyword::BEGIN)?;
271 let statements = self.parse_statement_list(parser, Some(Keyword::END))?;
272 let end_token = parser.expect_keyword(Keyword::END)?;
273 ConditionalStatementBlock {
274 start_token: AttachedToken(if_token),
275 condition: Some(condition),
276 then_token: None,
277 conditional_statements: ConditionalStatements::BeginEnd(BeginEndStatements {
278 begin_token: AttachedToken(begin_token),
279 statements,
280 end_token: AttachedToken(end_token),
281 }),
282 }
283 } else {
284 let stmt = parser.parse_statement()?;
285 ConditionalStatementBlock {
286 start_token: AttachedToken(if_token),
287 condition: Some(condition),
288 then_token: None,
289 conditional_statements: ConditionalStatements::Sequence {
290 statements: vec![stmt],
291 },
292 }
293 };
294
295 let mut prior_statement_ended_with_semi_colon = false;
296 while let Token::SemiColon = parser.peek_token_ref().token {
297 parser.advance_token();
298 prior_statement_ended_with_semi_colon = true;
299 }
300
301 let mut else_block = None;
302 if parser.peek_keyword(Keyword::ELSE) {
303 let else_token = parser.expect_keyword(Keyword::ELSE)?;
304 if parser.peek_keyword(Keyword::BEGIN) {
305 let begin_token = parser.expect_keyword(Keyword::BEGIN)?;
306 let statements = self.parse_statement_list(parser, Some(Keyword::END))?;
307 let end_token = parser.expect_keyword(Keyword::END)?;
308 else_block = Some(ConditionalStatementBlock {
309 start_token: AttachedToken(else_token),
310 condition: None,
311 then_token: None,
312 conditional_statements: ConditionalStatements::BeginEnd(BeginEndStatements {
313 begin_token: AttachedToken(begin_token),
314 statements,
315 end_token: AttachedToken(end_token),
316 }),
317 });
318 } else {
319 let stmt = parser.parse_statement()?;
320 else_block = Some(ConditionalStatementBlock {
321 start_token: AttachedToken(else_token),
322 condition: None,
323 then_token: None,
324 conditional_statements: ConditionalStatements::Sequence {
325 statements: vec![stmt],
326 },
327 });
328 }
329 } else if prior_statement_ended_with_semi_colon {
330 parser.prev_token();
331 }
332
333 Ok(IfStatement {
334 if_block,
335 else_block,
336 elseif_blocks: Vec::new(),
337 end_token: None,
338 }
339 .into())
340 }
341
342 fn parse_create_trigger(
346 &self,
347 parser: &mut Parser,
348 or_alter: bool,
349 ) -> Result<Statement, ParserError> {
350 let name = parser.parse_object_name(false)?;
351 parser.expect_keyword_is(Keyword::ON)?;
352 let table_name = parser.parse_object_name(false)?;
353 let period = parser.parse_trigger_period()?;
354 let events = parser.parse_comma_separated(Parser::parse_trigger_event)?;
355
356 parser.expect_keyword_is(Keyword::AS)?;
357 let statements = Some(parser.parse_conditional_statements(&[Keyword::END])?);
358
359 Ok(CreateTrigger {
360 or_alter,
361 temporary: false,
362 or_replace: false,
363 is_constraint: false,
364 name,
365 period: Some(period),
366 period_before_table: false,
367 events,
368 table_name,
369 referenced_table_name: None,
370 referencing: Vec::new(),
371 trigger_object: None,
372 condition: None,
373 exec_body: None,
374 statements_as: true,
375 statements,
376 characteristics: None,
377 }
378 .into())
379 }
380
381 fn parse_statement_list(
385 &self,
386 parser: &mut Parser,
387 terminal_keyword: Option<Keyword>,
388 ) -> Result<Vec<Statement>, ParserError> {
389 let mut stmts = Vec::new();
390 loop {
391 if let Token::EOF = parser.peek_token_ref().token {
392 break;
393 }
394 if let Some(term) = terminal_keyword {
395 if parser.peek_keyword(term) {
396 break;
397 }
398 }
399 stmts.push(parser.parse_statement()?);
400 while let Token::SemiColon = parser.peek_token_ref().token {
401 parser.advance_token();
402 }
403 }
404 Ok(stmts)
405 }
406}