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_connect_by(&self) -> bool {
75 true
76 }
77
78 fn supports_eq_alias_assignment(&self) -> bool {
79 true
80 }
81
82 fn supports_try_convert(&self) -> bool {
83 true
84 }
85
86 fn supports_boolean_literals(&self) -> bool {
88 false
89 }
90
91 fn supports_named_fn_args_with_colon_operator(&self) -> bool {
92 true
93 }
94
95 fn supports_named_fn_args_with_expr_name(&self) -> bool {
96 true
97 }
98
99 fn supports_named_fn_args_with_rarrow_operator(&self) -> bool {
100 false
101 }
102
103 fn supports_start_transaction_modifier(&self) -> bool {
104 true
105 }
106
107 fn supports_end_transaction_modifier(&self) -> bool {
108 true
109 }
110
111 fn supports_set_stmt_without_operator(&self) -> bool {
113 true
114 }
115
116 fn supports_table_versioning(&self) -> bool {
118 true
119 }
120
121 fn supports_nested_comments(&self) -> bool {
123 true
124 }
125
126 fn supports_object_name_double_dot_notation(&self) -> bool {
128 true
129 }
130
131 fn get_reserved_grantees_types(&self) -> &[GranteesType] {
133 &[GranteesType::Public]
134 }
135
136 fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
137 match kw {
138 Keyword::IF
145 | Keyword::ELSE
146 | Keyword::DECLARE
147 | Keyword::EXEC
148 | Keyword::EXECUTE
149 | Keyword::INSERT
150 | Keyword::UPDATE
151 | Keyword::DELETE
152 | Keyword::DROP
153 | Keyword::CREATE
154 | Keyword::ALTER
155 | Keyword::TRUNCATE
156 | Keyword::PRINT
157 | Keyword::WHILE
158 | Keyword::RETURN
159 | Keyword::THROW
160 | Keyword::RAISERROR
161 | Keyword::MERGE => false,
162 _ => explicit || self.is_column_alias(kw, parser),
163 }
164 }
165
166 fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
167 match kw {
168 Keyword::IF
179 | Keyword::ELSE
180 | Keyword::DECLARE
181 | Keyword::EXEC
182 | Keyword::EXECUTE
183 | Keyword::INSERT
184 | Keyword::UPDATE
185 | Keyword::DELETE
186 | Keyword::DROP
187 | Keyword::CREATE
188 | Keyword::ALTER
189 | Keyword::TRUNCATE
190 | Keyword::PRINT
191 | Keyword::WHILE
192 | Keyword::RETURN
193 | Keyword::THROW
194 | Keyword::RAISERROR
195 | Keyword::MERGE => false,
196 _ => explicit || self.is_table_alias(kw, parser),
197 }
198 }
199
200 fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
201 if parser.parse_keyword(Keyword::BEGIN) {
202 let is_block = parser
204 .maybe_parse(|p| {
205 if p.parse_transaction_modifier().is_some()
206 || p.parse_one_of_keywords(&[
207 Keyword::TRANSACTION,
208 Keyword::WORK,
209 Keyword::TRAN,
210 ])
211 .is_some()
212 || matches!(p.peek_token_ref().token, Token::SemiColon | Token::EOF)
213 {
214 p.expected_ref("statement", p.peek_token_ref())
215 } else {
216 Ok(())
217 }
218 })
219 .unwrap_or(None)
220 .is_some();
221 if is_block {
222 Some(parser.parse_begin_exception_end())
223 } else {
224 parser.prev_token();
225 None
226 }
227 } else if parser.peek_keyword(Keyword::IF) {
228 Some(self.parse_if_stmt(parser))
229 } else if parser.parse_keywords(&[Keyword::CREATE, Keyword::TRIGGER]) {
230 Some(self.parse_create_trigger(parser, false))
231 } else if parser.parse_keywords(&[
232 Keyword::CREATE,
233 Keyword::OR,
234 Keyword::ALTER,
235 Keyword::TRIGGER,
236 ]) {
237 Some(self.parse_create_trigger(parser, true))
238 } else {
239 None
240 }
241 }
242
243 fn get_next_precedence(&self, parser: &Parser) -> Option<Result<u8, ParserError>> {
244 let token = parser.peek_token_ref();
245 match &token.token {
246 Token::Colon => Some(Ok(self.prec_unknown())),
248 _ => None,
249 }
250 }
251}
252
253impl MsSqlDialect {
254 fn parse_if_stmt(&self, parser: &mut Parser) -> Result<Statement, ParserError> {
261 let if_token = parser.expect_keyword(Keyword::IF)?;
262
263 let condition = parser.parse_expr()?;
264
265 let if_block = if parser.peek_keyword(Keyword::BEGIN) {
266 let begin_token = parser.expect_keyword(Keyword::BEGIN)?;
267 let statements = self.parse_statement_list(parser, Some(Keyword::END))?;
268 let end_token = parser.expect_keyword(Keyword::END)?;
269 ConditionalStatementBlock {
270 start_token: AttachedToken(if_token),
271 condition: Some(condition),
272 then_token: None,
273 conditional_statements: ConditionalStatements::BeginEnd(BeginEndStatements {
274 begin_token: AttachedToken(begin_token),
275 statements,
276 end_token: AttachedToken(end_token),
277 }),
278 }
279 } else {
280 let stmt = parser.parse_statement()?;
281 ConditionalStatementBlock {
282 start_token: AttachedToken(if_token),
283 condition: Some(condition),
284 then_token: None,
285 conditional_statements: ConditionalStatements::Sequence {
286 statements: vec![stmt],
287 },
288 }
289 };
290
291 let mut prior_statement_ended_with_semi_colon = false;
292 while let Token::SemiColon = parser.peek_token_ref().token {
293 parser.advance_token();
294 prior_statement_ended_with_semi_colon = true;
295 }
296
297 let mut else_block = None;
298 if parser.peek_keyword(Keyword::ELSE) {
299 let else_token = parser.expect_keyword(Keyword::ELSE)?;
300 if parser.peek_keyword(Keyword::BEGIN) {
301 let begin_token = parser.expect_keyword(Keyword::BEGIN)?;
302 let statements = self.parse_statement_list(parser, Some(Keyword::END))?;
303 let end_token = parser.expect_keyword(Keyword::END)?;
304 else_block = Some(ConditionalStatementBlock {
305 start_token: AttachedToken(else_token),
306 condition: None,
307 then_token: None,
308 conditional_statements: ConditionalStatements::BeginEnd(BeginEndStatements {
309 begin_token: AttachedToken(begin_token),
310 statements,
311 end_token: AttachedToken(end_token),
312 }),
313 });
314 } else {
315 let stmt = parser.parse_statement()?;
316 else_block = Some(ConditionalStatementBlock {
317 start_token: AttachedToken(else_token),
318 condition: None,
319 then_token: None,
320 conditional_statements: ConditionalStatements::Sequence {
321 statements: vec![stmt],
322 },
323 });
324 }
325 } else if prior_statement_ended_with_semi_colon {
326 parser.prev_token();
327 }
328
329 Ok(IfStatement {
330 if_block,
331 else_block,
332 elseif_blocks: Vec::new(),
333 end_token: None,
334 }
335 .into())
336 }
337
338 fn parse_create_trigger(
342 &self,
343 parser: &mut Parser,
344 or_alter: bool,
345 ) -> Result<Statement, ParserError> {
346 let name = parser.parse_object_name(false)?;
347 parser.expect_keyword_is(Keyword::ON)?;
348 let table_name = parser.parse_object_name(false)?;
349 let period = parser.parse_trigger_period()?;
350 let events = parser.parse_comma_separated(Parser::parse_trigger_event)?;
351
352 parser.expect_keyword_is(Keyword::AS)?;
353 let statements = Some(parser.parse_conditional_statements(&[Keyword::END])?);
354
355 Ok(CreateTrigger {
356 or_alter,
357 temporary: false,
358 or_replace: false,
359 is_constraint: false,
360 name,
361 period: Some(period),
362 period_before_table: false,
363 events,
364 table_name,
365 referenced_table_name: None,
366 referencing: Vec::new(),
367 trigger_object: None,
368 condition: None,
369 exec_body: None,
370 statements_as: true,
371 statements,
372 characteristics: None,
373 }
374 .into())
375 }
376
377 fn parse_statement_list(
381 &self,
382 parser: &mut Parser,
383 terminal_keyword: Option<Keyword>,
384 ) -> Result<Vec<Statement>, ParserError> {
385 let mut stmts = Vec::new();
386 loop {
387 if let Token::EOF = parser.peek_token_ref().token {
388 break;
389 }
390 if let Some(term) = terminal_keyword {
391 if parser.peek_keyword(term) {
392 break;
393 }
394 }
395 stmts.push(parser.parse_statement()?);
396 while let Token::SemiColon = parser.peek_token_ref().token {
397 parser.advance_token();
398 }
399 }
400 Ok(stmts)
401 }
402}