sqlparser/dialect/
postgresql.rs1use log::debug;
30
31use crate::dialect::{Dialect, Precedence};
32use crate::keywords::Keyword;
33use crate::parser::{Parser, ParserError};
34use crate::tokenizer::Token;
35
36#[derive(Debug)]
38pub struct PostgreSqlDialect {}
39
40const PERIOD_PREC: u8 = 200;
41const DOUBLE_COLON_PREC: u8 = 140;
42const BRACKET_PREC: u8 = 130;
43const COLLATE_PREC: u8 = 120;
44const AT_TZ_PREC: u8 = 110;
45const CARET_PREC: u8 = 100;
46const MUL_DIV_MOD_OP_PREC: u8 = 90;
47const PLUS_MINUS_PREC: u8 = 80;
48const XOR_PREC: u8 = 75;
50const PG_OTHER_PREC: u8 = 70;
51const BETWEEN_LIKE_PREC: u8 = 60;
52const EQ_PREC: u8 = 50;
53const IS_PREC: u8 = 40;
54const NOT_PREC: u8 = 30;
55const AND_PREC: u8 = 20;
56const OR_PREC: u8 = 10;
57
58impl Dialect for PostgreSqlDialect {
59 fn identifier_quote_style(&self, _identifier: &str) -> Option<char> {
60 Some('"')
61 }
62
63 fn is_delimited_identifier_start(&self, ch: char) -> bool {
64 ch == '"' }
66
67 fn is_identifier_start(&self, ch: char) -> bool {
68 ch.is_alphabetic() || ch == '_'
72 }
73
74 fn is_identifier_part(&self, ch: char) -> bool {
75 ch.is_alphabetic() || ch.is_ascii_digit() || ch == '$' || ch == '_'
76 }
77
78 fn supports_unicode_string_literal(&self) -> bool {
79 true
80 }
81
82 fn is_custom_operator_part(&self, ch: char) -> bool {
84 matches!(
85 ch,
86 '+' | '-'
87 | '*'
88 | '/'
89 | '<'
90 | '>'
91 | '='
92 | '~'
93 | '!'
94 | '@'
95 | '#'
96 | '%'
97 | '^'
98 | '&'
99 | '|'
100 | '`'
101 | '?'
102 )
103 }
104
105 fn get_next_precedence(&self, parser: &Parser) -> Option<Result<u8, ParserError>> {
106 let token = parser.peek_token();
107 debug!("get_next_precedence() {:?}", token);
108
109 match token.token {
112 Token::Word(w) if w.keyword == Keyword::COLLATE => Some(Ok(COLLATE_PREC)),
113 Token::LBracket => Some(Ok(BRACKET_PREC)),
114 Token::Arrow
115 | Token::LongArrow
116 | Token::HashArrow
117 | Token::HashLongArrow
118 | Token::AtArrow
119 | Token::ArrowAt
120 | Token::HashMinus
121 | Token::AtQuestion
122 | Token::AtAt
123 | Token::Question
124 | Token::QuestionAnd
125 | Token::QuestionPipe
126 | Token::ExclamationMark
127 | Token::Overlap
128 | Token::CaretAt
129 | Token::StringConcat
130 | Token::Sharp
131 | Token::ShiftRight
132 | Token::ShiftLeft
133 | Token::CustomBinaryOperator(_) => Some(Ok(PG_OTHER_PREC)),
134 _ => None,
135 }
136 }
137
138 fn supports_filter_during_aggregation(&self) -> bool {
139 true
140 }
141
142 fn supports_group_by_expr(&self) -> bool {
143 true
144 }
145
146 fn prec_value(&self, prec: Precedence) -> u8 {
147 match prec {
148 Precedence::Period => PERIOD_PREC,
149 Precedence::DoubleColon => DOUBLE_COLON_PREC,
150 Precedence::AtTz => AT_TZ_PREC,
151 Precedence::MulDivModOp => MUL_DIV_MOD_OP_PREC,
152 Precedence::PlusMinus => PLUS_MINUS_PREC,
153 Precedence::Xor => XOR_PREC,
154 Precedence::Ampersand => PG_OTHER_PREC,
155 Precedence::Caret => CARET_PREC,
156 Precedence::Pipe => PG_OTHER_PREC,
157 Precedence::Between => BETWEEN_LIKE_PREC,
158 Precedence::Eq => EQ_PREC,
159 Precedence::Like => BETWEEN_LIKE_PREC,
160 Precedence::Is => IS_PREC,
161 Precedence::PgOther => PG_OTHER_PREC,
162 Precedence::UnaryNot => NOT_PREC,
163 Precedence::And => AND_PREC,
164 Precedence::Or => OR_PREC,
165 }
166 }
167
168 fn allow_extract_custom(&self) -> bool {
169 true
170 }
171
172 fn allow_extract_single_quotes(&self) -> bool {
173 true
174 }
175
176 fn supports_create_index_with_clause(&self) -> bool {
177 true
178 }
179
180 fn supports_explain_with_utility_options(&self) -> bool {
182 true
183 }
184
185 fn supports_listen_notify(&self) -> bool {
189 true
190 }
191
192 fn supports_factorial_operator(&self) -> bool {
194 true
195 }
196
197 fn supports_comment_on(&self) -> bool {
199 true
200 }
201
202 fn supports_load_extension(&self) -> bool {
204 true
205 }
206
207 fn supports_named_fn_args_with_colon_operator(&self) -> bool {
214 true
215 }
216
217 fn supports_named_fn_args_with_expr_name(&self) -> bool {
224 true
225 }
226
227 fn supports_empty_projections(&self) -> bool {
234 true
235 }
236
237 fn supports_nested_comments(&self) -> bool {
238 true
239 }
240
241 fn supports_string_escape_constant(&self) -> bool {
242 true
243 }
244
245 fn supports_numeric_literal_underscores(&self) -> bool {
246 true
247 }
248
249 fn supports_array_typedef_with_brackets(&self) -> bool {
251 true
252 }
253
254 fn supports_geometric_types(&self) -> bool {
255 true
256 }
257
258 fn supports_set_names(&self) -> bool {
259 true
260 }
261}