sqlparser/dialect/
bigquery.rs1use crate::ast::Statement;
19use crate::dialect::Dialect;
20use crate::keywords::Keyword;
21use crate::parser::{Parser, ParserError};
22
23const RESERVED_FOR_COLUMN_ALIAS: &[Keyword] = &[
26 Keyword::WITH,
27 Keyword::SELECT,
28 Keyword::WHERE,
29 Keyword::GROUP,
30 Keyword::HAVING,
31 Keyword::ORDER,
32 Keyword::LATERAL,
33 Keyword::LIMIT,
34 Keyword::FETCH,
35 Keyword::UNION,
36 Keyword::EXCEPT,
37 Keyword::INTERSECT,
38 Keyword::FROM,
39 Keyword::INTO,
40 Keyword::END,
41];
42
43#[derive(Debug, Default)]
45pub struct BigQueryDialect;
46
47impl Dialect for BigQueryDialect {
48 fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
49 self.maybe_parse_statement(parser)
50 }
51
52 fn is_delimited_identifier_start(&self, ch: char) -> bool {
54 ch == '`'
55 }
56
57 fn supports_projection_trailing_commas(&self) -> bool {
58 true
59 }
60
61 fn supports_column_definition_trailing_commas(&self) -> bool {
63 true
64 }
65
66 fn is_identifier_start(&self, ch: char) -> bool {
67 ch.is_ascii_lowercase() || ch.is_ascii_uppercase() || ch == '_'
68 || ch == '@'
71 }
72
73 fn is_identifier_part(&self, ch: char) -> bool {
74 ch.is_ascii_lowercase() || ch.is_ascii_uppercase() || ch.is_ascii_digit() || ch == '_'
75 }
76
77 fn supports_triple_quoted_string(&self) -> bool {
79 true
80 }
81
82 fn supports_window_function_null_treatment_arg(&self) -> bool {
84 true
85 }
86
87 fn supports_string_literal_backslash_escape(&self) -> bool {
89 true
90 }
91
92 fn supports_window_clause_named_window_reference(&self) -> bool {
94 true
95 }
96
97 fn supports_parenthesized_set_variables(&self) -> bool {
99 true
100 }
101
102 fn supports_select_wildcard_except(&self) -> bool {
104 true
105 }
106
107 fn require_interval_qualifier(&self) -> bool {
108 true
109 }
110
111 fn supports_struct_literal(&self) -> bool {
113 true
114 }
115
116 fn supports_select_expr_star(&self) -> bool {
118 true
119 }
120
121 fn supports_execute_immediate(&self) -> bool {
123 true
124 }
125
126 fn supports_timestamp_versioning(&self) -> bool {
128 true
129 }
130
131 fn supports_group_by_expr(&self) -> bool {
133 true
134 }
135
136 fn is_column_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
137 !RESERVED_FOR_COLUMN_ALIAS.contains(kw)
138 }
139
140 fn supports_pipe_operator(&self) -> bool {
141 true
142 }
143}
144
145impl BigQueryDialect {
146 fn maybe_parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
147 if parser.peek_keyword(Keyword::BEGIN) {
148 return Some(self.parse_begin(parser));
149 }
150 None
151 }
152
153 fn parse_begin(&self, parser: &mut Parser) -> Result<Statement, ParserError> {
156 parser.expect_keyword(Keyword::BEGIN)?;
157
158 let statements = parser.parse_statement_list(&[Keyword::EXCEPTION, Keyword::END])?;
159
160 let has_exception_when_clause = parser.parse_keywords(&[
161 Keyword::EXCEPTION,
162 Keyword::WHEN,
163 Keyword::ERROR,
164 Keyword::THEN,
165 ]);
166 let exception_statements = if has_exception_when_clause {
167 if !parser.peek_keyword(Keyword::END) {
168 Some(parser.parse_statement_list(&[Keyword::END])?)
169 } else {
170 Some(Default::default())
171 }
172 } else {
173 None
174 };
175
176 parser.expect_keyword(Keyword::END)?;
177
178 Ok(Statement::StartTransaction {
179 begin: true,
180 statements,
181 exception_statements,
182 has_end_keyword: true,
183 transaction: None,
184 modifier: None,
185 modes: Default::default(),
186 })
187 }
188}