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)]
32pub struct MsSqlDialect {}
33
34impl Dialect for MsSqlDialect {
35 fn is_delimited_identifier_start(&self, ch: char) -> bool {
36 ch == '"' || ch == '['
37 }
38
39 fn is_identifier_start(&self, ch: char) -> bool {
40 ch.is_alphabetic() || ch == '_' || ch == '#' || ch == '@'
42 }
43
44 fn is_identifier_part(&self, ch: char) -> bool {
45 ch.is_alphabetic()
46 || ch.is_ascii_digit()
47 || ch == '@'
48 || ch == '$'
49 || ch == '#'
50 || ch == '_'
51 }
52
53 fn identifier_quote_style(&self, _identifier: &str) -> Option<char> {
54 Some('[')
55 }
56
57 fn convert_type_before_value(&self) -> bool {
60 true
61 }
62
63 fn supports_outer_join_operator(&self) -> bool {
64 true
65 }
66
67 fn supports_connect_by(&self) -> bool {
68 true
69 }
70
71 fn supports_eq_alias_assignment(&self) -> bool {
72 true
73 }
74
75 fn supports_try_convert(&self) -> bool {
76 true
77 }
78
79 fn supports_boolean_literals(&self) -> bool {
81 false
82 }
83
84 fn supports_named_fn_args_with_colon_operator(&self) -> bool {
85 true
86 }
87
88 fn supports_named_fn_args_with_expr_name(&self) -> bool {
89 true
90 }
91
92 fn supports_named_fn_args_with_rarrow_operator(&self) -> bool {
93 false
94 }
95
96 fn supports_start_transaction_modifier(&self) -> bool {
97 true
98 }
99
100 fn supports_end_transaction_modifier(&self) -> bool {
101 true
102 }
103
104 fn supports_set_stmt_without_operator(&self) -> bool {
106 true
107 }
108
109 fn supports_timestamp_versioning(&self) -> bool {
111 true
112 }
113
114 fn supports_nested_comments(&self) -> bool {
116 true
117 }
118
119 fn supports_object_name_double_dot_notation(&self) -> bool {
121 true
122 }
123
124 fn get_reserved_grantees_types(&self) -> &[GranteesType] {
126 &[GranteesType::Public]
127 }
128
129 fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
130 match kw {
131 Keyword::IF | Keyword::ELSE => false,
134 _ => explicit || self.is_column_alias(kw, parser),
135 }
136 }
137
138 fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
139 match kw {
140 Keyword::IF | Keyword::ELSE => false,
143 _ => explicit || self.is_table_alias(kw, parser),
144 }
145 }
146
147 fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
148 if parser.peek_keyword(Keyword::IF) {
149 Some(self.parse_if_stmt(parser))
150 } else if parser.parse_keywords(&[Keyword::CREATE, Keyword::TRIGGER]) {
151 Some(self.parse_create_trigger(parser, false))
152 } else if parser.parse_keywords(&[
153 Keyword::CREATE,
154 Keyword::OR,
155 Keyword::ALTER,
156 Keyword::TRIGGER,
157 ]) {
158 Some(self.parse_create_trigger(parser, true))
159 } else {
160 None
161 }
162 }
163}
164
165impl MsSqlDialect {
166 fn parse_if_stmt(&self, parser: &mut Parser) -> Result<Statement, ParserError> {
173 let if_token = parser.expect_keyword(Keyword::IF)?;
174
175 let condition = parser.parse_expr()?;
176
177 let if_block = if parser.peek_keyword(Keyword::BEGIN) {
178 let begin_token = parser.expect_keyword(Keyword::BEGIN)?;
179 let statements = self.parse_statement_list(parser, Some(Keyword::END))?;
180 let end_token = parser.expect_keyword(Keyword::END)?;
181 ConditionalStatementBlock {
182 start_token: AttachedToken(if_token),
183 condition: Some(condition),
184 then_token: None,
185 conditional_statements: ConditionalStatements::BeginEnd(BeginEndStatements {
186 begin_token: AttachedToken(begin_token),
187 statements,
188 end_token: AttachedToken(end_token),
189 }),
190 }
191 } else {
192 let stmt = parser.parse_statement()?;
193 ConditionalStatementBlock {
194 start_token: AttachedToken(if_token),
195 condition: Some(condition),
196 then_token: None,
197 conditional_statements: ConditionalStatements::Sequence {
198 statements: vec![stmt],
199 },
200 }
201 };
202
203 let mut prior_statement_ended_with_semi_colon = false;
204 while let Token::SemiColon = parser.peek_token_ref().token {
205 parser.advance_token();
206 prior_statement_ended_with_semi_colon = true;
207 }
208
209 let mut else_block = None;
210 if parser.peek_keyword(Keyword::ELSE) {
211 let else_token = parser.expect_keyword(Keyword::ELSE)?;
212 if parser.peek_keyword(Keyword::BEGIN) {
213 let begin_token = parser.expect_keyword(Keyword::BEGIN)?;
214 let statements = self.parse_statement_list(parser, Some(Keyword::END))?;
215 let end_token = parser.expect_keyword(Keyword::END)?;
216 else_block = Some(ConditionalStatementBlock {
217 start_token: AttachedToken(else_token),
218 condition: None,
219 then_token: None,
220 conditional_statements: ConditionalStatements::BeginEnd(BeginEndStatements {
221 begin_token: AttachedToken(begin_token),
222 statements,
223 end_token: AttachedToken(end_token),
224 }),
225 });
226 } else {
227 let stmt = parser.parse_statement()?;
228 else_block = Some(ConditionalStatementBlock {
229 start_token: AttachedToken(else_token),
230 condition: None,
231 then_token: None,
232 conditional_statements: ConditionalStatements::Sequence {
233 statements: vec![stmt],
234 },
235 });
236 }
237 } else if prior_statement_ended_with_semi_colon {
238 parser.prev_token();
239 }
240
241 Ok(IfStatement {
242 if_block,
243 else_block,
244 elseif_blocks: Vec::new(),
245 end_token: None,
246 }
247 .into())
248 }
249
250 fn parse_create_trigger(
254 &self,
255 parser: &mut Parser,
256 or_alter: bool,
257 ) -> Result<Statement, ParserError> {
258 let name = parser.parse_object_name(false)?;
259 parser.expect_keyword_is(Keyword::ON)?;
260 let table_name = parser.parse_object_name(false)?;
261 let period = parser.parse_trigger_period()?;
262 let events = parser.parse_comma_separated(Parser::parse_trigger_event)?;
263
264 parser.expect_keyword_is(Keyword::AS)?;
265 let statements = Some(parser.parse_conditional_statements(&[Keyword::END])?);
266
267 Ok(CreateTrigger {
268 or_alter,
269 temporary: false,
270 or_replace: false,
271 is_constraint: false,
272 name,
273 period: Some(period),
274 period_before_table: false,
275 events,
276 table_name,
277 referenced_table_name: None,
278 referencing: Vec::new(),
279 trigger_object: None,
280 condition: None,
281 exec_body: None,
282 statements_as: true,
283 statements,
284 characteristics: None,
285 }
286 .into())
287 }
288
289 fn parse_statement_list(
293 &self,
294 parser: &mut Parser,
295 terminal_keyword: Option<Keyword>,
296 ) -> Result<Vec<Statement>, ParserError> {
297 let mut stmts = Vec::new();
298 loop {
299 if let Token::EOF = parser.peek_token_ref().token {
300 break;
301 }
302 if let Some(term) = terminal_keyword {
303 if parser.peek_keyword(term) {
304 break;
305 }
306 }
307 stmts.push(parser.parse_statement()?);
308 while let Token::SemiColon = parser.peek_token_ref().token {
309 parser.advance_token();
310 }
311 }
312 Ok(stmts)
313 }
314}