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(#[automatically_derived]
impl ::core::fmt::Debug for MsSqlDialect {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "MsSqlDialect")
}
}Debug, #[automatically_derived]
impl ::core::default::Default for MsSqlDialect {
#[inline]
fn default() -> MsSqlDialect { MsSqlDialect {} }
}Default, #[automatically_derived]
impl ::core::clone::Clone for MsSqlDialect {
#[inline]
fn clone(&self) -> MsSqlDialect { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for MsSqlDialect { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for MsSqlDialect {
#[inline]
fn eq(&self, other: &MsSqlDialect) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for MsSqlDialect {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for MsSqlDialect {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {}
}Hash, #[automatically_derived]
impl ::core::cmp::PartialOrd for MsSqlDialect {
#[inline]
fn partial_cmp(&self, other: &MsSqlDialect)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for MsSqlDialect {
#[inline]
fn cmp(&self, other: &MsSqlDialect) -> ::core::cmp::Ordering {
::core::cmp::Ordering::Equal
}
}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_connect_by(&self) -> bool {
69 true
70 }
71
72 fn supports_eq_alias_assignment(&self) -> bool {
73 true
74 }
75
76 fn supports_try_convert(&self) -> bool {
77 true
78 }
79
80 fn supports_boolean_literals(&self) -> bool {
82 false
83 }
84
85 fn supports_named_fn_args_with_colon_operator(&self) -> bool {
86 true
87 }
88
89 fn supports_named_fn_args_with_expr_name(&self) -> bool {
90 true
91 }
92
93 fn supports_named_fn_args_with_rarrow_operator(&self) -> bool {
94 false
95 }
96
97 fn supports_start_transaction_modifier(&self) -> bool {
98 true
99 }
100
101 fn supports_end_transaction_modifier(&self) -> bool {
102 true
103 }
104
105 fn supports_set_stmt_without_operator(&self) -> bool {
107 true
108 }
109
110 fn supports_table_versioning(&self) -> bool {
112 true
113 }
114
115 fn supports_nested_comments(&self) -> bool {
117 true
118 }
119
120 fn supports_object_name_double_dot_notation(&self) -> bool {
122 true
123 }
124
125 fn get_reserved_grantees_types(&self) -> &[GranteesType] {
127 &[GranteesType::Public]
128 }
129
130 fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
131 match kw {
132 Keyword::IF | Keyword::ELSE => false,
135 _ => explicit || self.is_column_alias(kw, parser),
136 }
137 }
138
139 fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
140 match kw {
141 Keyword::IF | Keyword::ELSE => false,
144 _ => explicit || self.is_table_alias(kw, parser),
145 }
146 }
147
148 fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
149 if parser.parse_keyword(Keyword::BEGIN) {
150 let is_block = parser
152 .maybe_parse(|p| {
153 if p.parse_transaction_modifier().is_some()
154 || p.parse_one_of_keywords(&[Keyword::TRANSACTION, Keyword::WORK])
155 .is_some()
156 || #[allow(non_exhaustive_omitted_patterns)] match p.peek_token_ref().token {
Token::SemiColon | Token::EOF => true,
_ => false,
}matches!(p.peek_token_ref().token, Token::SemiColon | Token::EOF)
157 {
158 p.expected("statement", p.peek_token())
159 } else {
160 Ok(())
161 }
162 })
163 .unwrap_or(None)
164 .is_some();
165 if is_block {
166 Some(parser.parse_begin_exception_end())
167 } else {
168 parser.prev_token();
169 None
170 }
171 } else if parser.peek_keyword(Keyword::IF) {
172 Some(self.parse_if_stmt(parser))
173 } else if parser.parse_keywords(&[Keyword::CREATE, Keyword::TRIGGER]) {
174 Some(self.parse_create_trigger(parser, false))
175 } else if parser.parse_keywords(&[
176 Keyword::CREATE,
177 Keyword::OR,
178 Keyword::ALTER,
179 Keyword::TRIGGER,
180 ]) {
181 Some(self.parse_create_trigger(parser, true))
182 } else {
183 None
184 }
185 }
186
187 fn get_next_precedence(&self, parser: &Parser) -> Option<Result<u8, ParserError>> {
188 let token = parser.peek_token();
189 match token.token {
190 Token::Colon => Some(Ok(self.prec_unknown())),
192 _ => None,
193 }
194 }
195}
196
197impl MsSqlDialect {
198 fn parse_if_stmt(&self, parser: &mut Parser) -> Result<Statement, ParserError> {
205 let if_token = parser.expect_keyword(Keyword::IF)?;
206
207 let condition = parser.parse_expr()?;
208
209 let if_block = if parser.peek_keyword(Keyword::BEGIN) {
210 let begin_token = parser.expect_keyword(Keyword::BEGIN)?;
211 let statements = self.parse_statement_list(parser, Some(Keyword::END))?;
212 let end_token = parser.expect_keyword(Keyword::END)?;
213 ConditionalStatementBlock {
214 start_token: AttachedToken(if_token),
215 condition: Some(condition),
216 then_token: None,
217 conditional_statements: ConditionalStatements::BeginEnd(BeginEndStatements {
218 begin_token: AttachedToken(begin_token),
219 statements,
220 end_token: AttachedToken(end_token),
221 }),
222 }
223 } else {
224 let stmt = parser.parse_statement()?;
225 ConditionalStatementBlock {
226 start_token: AttachedToken(if_token),
227 condition: Some(condition),
228 then_token: None,
229 conditional_statements: ConditionalStatements::Sequence {
230 statements: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[stmt]))vec![stmt],
231 },
232 }
233 };
234
235 let mut prior_statement_ended_with_semi_colon = false;
236 while let Token::SemiColon = parser.peek_token_ref().token {
237 parser.advance_token();
238 prior_statement_ended_with_semi_colon = true;
239 }
240
241 let mut else_block = None;
242 if parser.peek_keyword(Keyword::ELSE) {
243 let else_token = parser.expect_keyword(Keyword::ELSE)?;
244 if parser.peek_keyword(Keyword::BEGIN) {
245 let begin_token = parser.expect_keyword(Keyword::BEGIN)?;
246 let statements = self.parse_statement_list(parser, Some(Keyword::END))?;
247 let end_token = parser.expect_keyword(Keyword::END)?;
248 else_block = Some(ConditionalStatementBlock {
249 start_token: AttachedToken(else_token),
250 condition: None,
251 then_token: None,
252 conditional_statements: ConditionalStatements::BeginEnd(BeginEndStatements {
253 begin_token: AttachedToken(begin_token),
254 statements,
255 end_token: AttachedToken(end_token),
256 }),
257 });
258 } else {
259 let stmt = parser.parse_statement()?;
260 else_block = Some(ConditionalStatementBlock {
261 start_token: AttachedToken(else_token),
262 condition: None,
263 then_token: None,
264 conditional_statements: ConditionalStatements::Sequence {
265 statements: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[stmt]))vec![stmt],
266 },
267 });
268 }
269 } else if prior_statement_ended_with_semi_colon {
270 parser.prev_token();
271 }
272
273 Ok(IfStatement {
274 if_block,
275 else_block,
276 elseif_blocks: Vec::new(),
277 end_token: None,
278 }
279 .into())
280 }
281
282 fn parse_create_trigger(
286 &self,
287 parser: &mut Parser,
288 or_alter: bool,
289 ) -> Result<Statement, ParserError> {
290 let name = parser.parse_object_name(false)?;
291 parser.expect_keyword_is(Keyword::ON)?;
292 let table_name = parser.parse_object_name(false)?;
293 let period = parser.parse_trigger_period()?;
294 let events = parser.parse_comma_separated(Parser::parse_trigger_event)?;
295
296 parser.expect_keyword_is(Keyword::AS)?;
297 let statements = Some(parser.parse_conditional_statements(&[Keyword::END])?);
298
299 Ok(CreateTrigger {
300 or_alter,
301 temporary: false,
302 or_replace: false,
303 is_constraint: false,
304 name,
305 period: Some(period),
306 period_before_table: false,
307 events,
308 table_name,
309 referenced_table_name: None,
310 referencing: Vec::new(),
311 trigger_object: None,
312 condition: None,
313 exec_body: None,
314 statements_as: true,
315 statements,
316 characteristics: None,
317 }
318 .into())
319 }
320
321 fn parse_statement_list(
325 &self,
326 parser: &mut Parser,
327 terminal_keyword: Option<Keyword>,
328 ) -> Result<Vec<Statement>, ParserError> {
329 let mut stmts = Vec::new();
330 loop {
331 if let Token::EOF = parser.peek_token_ref().token {
332 break;
333 }
334 if let Some(term) = terminal_keyword {
335 if parser.peek_keyword(term) {
336 break;
337 }
338 }
339 stmts.push(parser.parse_statement()?);
340 while let Token::SemiColon = parser.peek_token_ref().token {
341 parser.advance_token();
342 }
343 }
344 Ok(stmts)
345 }
346}