Thanks to visit codestin.com
Credit goes to docs.rs

sqlparser/dialect/
postgresql.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18// Licensed under the Apache License, Version 2.0 (the "License");
19// you may not use this file except in compliance with the License.
20// You may obtain a copy of the License at
21//
22// http://www.apache.org/licenses/LICENSE-2.0
23//
24// Unless required by applicable law or agreed to in writing, software
25// distributed under the License is distributed on an "AS IS" BASIS,
26// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27// See the License for the specific language governing permissions and
28// limitations under the License.
29use log::debug;
30
31use crate::dialect::{Dialect, Precedence};
32use crate::keywords::Keyword;
33use crate::parser::{Parser, ParserError};
34use crate::tokenizer::Token;
35
36/// A [`Dialect`] for [PostgreSQL](https://www.postgresql.org/)
37#[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;
48// there's no XOR operator in PostgreSQL, but support it here to avoid breaking tests
49const 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 == '"' // Postgres does not support backticks to quote identifiers
65    }
66
67    fn is_identifier_start(&self, ch: char) -> bool {
68        ch.is_alphabetic() || ch == '_' ||
69        // PostgreSQL implements Unicode characters in identifiers.
70        !ch.is_ascii()
71    }
72
73    fn is_identifier_part(&self, ch: char) -> bool {
74        ch.is_alphabetic() || ch.is_ascii_digit() || ch == '$' || ch == '_'  ||
75        // PostgreSQL implements Unicode characters in identifiers.
76        !ch.is_ascii()
77    }
78
79    fn supports_unicode_string_literal(&self) -> bool {
80        true
81    }
82
83    /// See <https://www.postgresql.org/docs/current/sql-createoperator.html>
84    fn is_custom_operator_part(&self, ch: char) -> bool {
85        matches!(
86            ch,
87            '+' | '-'
88                | '*'
89                | '/'
90                | '<'
91                | '>'
92                | '='
93                | '~'
94                | '!'
95                | '@'
96                | '#'
97                | '%'
98                | '^'
99                | '&'
100                | '|'
101                | '`'
102                | '?'
103        )
104    }
105
106    fn get_next_precedence(&self, parser: &Parser) -> Option<Result<u8, ParserError>> {
107        let token = parser.peek_token();
108        debug!("get_next_precedence() {token:?}");
109
110        // we only return some custom value here when the behaviour (not merely the numeric value) differs
111        // from the default implementation
112        match token.token {
113            Token::Word(w)
114                if w.keyword == Keyword::COLLATE && !parser.in_column_definition_state() =>
115            {
116                Some(Ok(COLLATE_PREC))
117            }
118            Token::LBracket => Some(Ok(BRACKET_PREC)),
119            Token::Arrow
120            | Token::LongArrow
121            | Token::HashArrow
122            | Token::HashLongArrow
123            | Token::AtArrow
124            | Token::ArrowAt
125            | Token::HashMinus
126            | Token::AtQuestion
127            | Token::AtAt
128            | Token::Question
129            | Token::QuestionAnd
130            | Token::QuestionPipe
131            | Token::ExclamationMark
132            | Token::Overlap
133            | Token::CaretAt
134            | Token::StringConcat
135            | Token::Sharp
136            | Token::ShiftRight
137            | Token::ShiftLeft
138            | Token::CustomBinaryOperator(_) => Some(Ok(PG_OTHER_PREC)),
139            _ => None,
140        }
141    }
142
143    fn supports_filter_during_aggregation(&self) -> bool {
144        true
145    }
146
147    fn supports_group_by_expr(&self) -> bool {
148        true
149    }
150
151    fn prec_value(&self, prec: Precedence) -> u8 {
152        match prec {
153            Precedence::Period => PERIOD_PREC,
154            Precedence::DoubleColon => DOUBLE_COLON_PREC,
155            Precedence::AtTz => AT_TZ_PREC,
156            Precedence::MulDivModOp => MUL_DIV_MOD_OP_PREC,
157            Precedence::PlusMinus => PLUS_MINUS_PREC,
158            Precedence::Xor => XOR_PREC,
159            Precedence::Ampersand => PG_OTHER_PREC,
160            Precedence::Caret => CARET_PREC,
161            Precedence::Pipe => PG_OTHER_PREC,
162            Precedence::Between => BETWEEN_LIKE_PREC,
163            Precedence::Eq => EQ_PREC,
164            Precedence::Like => BETWEEN_LIKE_PREC,
165            Precedence::Is => IS_PREC,
166            Precedence::PgOther => PG_OTHER_PREC,
167            Precedence::UnaryNot => NOT_PREC,
168            Precedence::And => AND_PREC,
169            Precedence::Or => OR_PREC,
170        }
171    }
172
173    fn allow_extract_custom(&self) -> bool {
174        true
175    }
176
177    fn allow_extract_single_quotes(&self) -> bool {
178        true
179    }
180
181    fn supports_create_index_with_clause(&self) -> bool {
182        true
183    }
184
185    /// see <https://www.postgresql.org/docs/current/sql-explain.html>
186    fn supports_explain_with_utility_options(&self) -> bool {
187        true
188    }
189
190    /// see <https://www.postgresql.org/docs/current/sql-listen.html>
191    /// see <https://www.postgresql.org/docs/current/sql-unlisten.html>
192    /// see <https://www.postgresql.org/docs/current/sql-notify.html>
193    fn supports_listen_notify(&self) -> bool {
194        true
195    }
196
197    /// see <https://www.postgresql.org/docs/13/functions-math.html>
198    fn supports_factorial_operator(&self) -> bool {
199        true
200    }
201
202    /// see <https://www.postgresql.org/docs/current/sql-comment.html>
203    fn supports_comment_on(&self) -> bool {
204        true
205    }
206
207    /// See <https://www.postgresql.org/docs/current/sql-load.html>
208    fn supports_load_extension(&self) -> bool {
209        true
210    }
211
212    /// See <https://www.postgresql.org/docs/current/functions-json.html>
213    ///
214    /// Required to support the colon in:
215    /// ```sql
216    /// SELECT json_object('a': 'b')
217    /// ```
218    fn supports_named_fn_args_with_colon_operator(&self) -> bool {
219        true
220    }
221
222    /// See <https://www.postgresql.org/docs/current/functions-json.html>
223    ///
224    /// Required to support the label in:
225    /// ```sql
226    /// SELECT json_object('label': 'value')
227    /// ```
228    fn supports_named_fn_args_with_expr_name(&self) -> bool {
229        true
230    }
231
232    /// Return true if the dialect supports empty projections in SELECT statements
233    ///
234    /// Example
235    /// ```sql
236    /// SELECT from table_name
237    /// ```
238    fn supports_empty_projections(&self) -> bool {
239        true
240    }
241
242    fn supports_nested_comments(&self) -> bool {
243        true
244    }
245
246    fn supports_string_escape_constant(&self) -> bool {
247        true
248    }
249
250    fn supports_numeric_literal_underscores(&self) -> bool {
251        true
252    }
253
254    /// See: <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-DECLARATION>
255    fn supports_array_typedef_with_brackets(&self) -> bool {
256        true
257    }
258
259    fn supports_geometric_types(&self) -> bool {
260        true
261    }
262
263    fn supports_set_names(&self) -> bool {
264        true
265    }
266
267    fn supports_alter_column_type_using(&self) -> bool {
268        true
269    }
270
271    /// Postgres supports `NOTNULL` as an alias for `IS NOT NULL`
272    /// See: <https://www.postgresql.org/docs/17/functions-comparison.html>
273    fn supports_notnull_operator(&self) -> bool {
274        true
275    }
276
277    /// [Postgres] supports optional field and precision options for `INTERVAL` data type.
278    ///
279    /// [Postgres]: https://www.postgresql.org/docs/17/datatype-datetime.html
280    fn supports_interval_options(&self) -> bool {
281        true
282    }
283}