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        // See https://www.postgresql.org/docs/11/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
69        // We don't yet support identifiers beginning with "letters with
70        // diacritical marks"
71        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    /// See <https://www.postgresql.org/docs/current/sql-createoperator.html>
83    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        // we only return some custom value here when the behaviour (not merely the numeric value) differs
110        // from the default implementation
111        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    /// see <https://www.postgresql.org/docs/current/sql-explain.html>
181    fn supports_explain_with_utility_options(&self) -> bool {
182        true
183    }
184
185    /// see <https://www.postgresql.org/docs/current/sql-listen.html>
186    /// see <https://www.postgresql.org/docs/current/sql-unlisten.html>
187    /// see <https://www.postgresql.org/docs/current/sql-notify.html>
188    fn supports_listen_notify(&self) -> bool {
189        true
190    }
191
192    /// see <https://www.postgresql.org/docs/13/functions-math.html>
193    fn supports_factorial_operator(&self) -> bool {
194        true
195    }
196
197    /// see <https://www.postgresql.org/docs/current/sql-comment.html>
198    fn supports_comment_on(&self) -> bool {
199        true
200    }
201
202    /// See <https://www.postgresql.org/docs/current/sql-load.html>
203    fn supports_load_extension(&self) -> bool {
204        true
205    }
206
207    /// See <https://www.postgresql.org/docs/current/functions-json.html>
208    ///
209    /// Required to support the colon in:
210    /// ```sql
211    /// SELECT json_object('a': 'b')
212    /// ```
213    fn supports_named_fn_args_with_colon_operator(&self) -> bool {
214        true
215    }
216
217    /// See <https://www.postgresql.org/docs/current/functions-json.html>
218    ///
219    /// Required to support the label in:
220    /// ```sql
221    /// SELECT json_object('label': 'value')
222    /// ```
223    fn supports_named_fn_args_with_expr_name(&self) -> bool {
224        true
225    }
226
227    /// Return true if the dialect supports empty projections in SELECT statements
228    ///
229    /// Example
230    /// ```sql
231    /// SELECT from table_name
232    /// ```
233    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    /// See: <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-DECLARATION>
250    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}