sqlparser/dialect/
postgresql.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13use crate::ast::{CommentObject, Statement};
14use crate::dialect::Dialect;
15use crate::keywords::Keyword;
16use crate::parser::{Parser, ParserError};
17use crate::tokenizer::Token;
18
19#[derive(Debug)]
20pub struct PostgreSqlDialect {}
21
22impl Dialect for PostgreSqlDialect {
23    fn is_identifier_start(&self, ch: char) -> bool {
24        // See https://www.postgresql.org/docs/11/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
25        // We don't yet support identifiers beginning with "letters with
26        // diacritical marks"
27        ch.is_alphabetic() || ch == '_'
28    }
29
30    fn is_identifier_part(&self, ch: char) -> bool {
31        ch.is_alphabetic() || ch.is_ascii_digit() || ch == '$' || ch == '_'
32    }
33
34    fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
35        if parser.parse_keyword(Keyword::COMMENT) {
36            Some(parse_comment(parser))
37        } else {
38            None
39        }
40    }
41
42    fn supports_filter_during_aggregation(&self) -> bool {
43        true
44    }
45}
46
47pub fn parse_comment(parser: &mut Parser) -> Result<Statement, ParserError> {
48    let if_exists = parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
49
50    parser.expect_keyword(Keyword::ON)?;
51    let token = parser.next_token();
52
53    let (object_type, object_name) = match token.token {
54        Token::Word(w) if w.keyword == Keyword::COLUMN => {
55            let object_name = parser.parse_object_name()?;
56            (CommentObject::Column, object_name)
57        }
58        Token::Word(w) if w.keyword == Keyword::TABLE => {
59            let object_name = parser.parse_object_name()?;
60            (CommentObject::Table, object_name)
61        }
62        _ => parser.expected("comment object_type", token)?,
63    };
64
65    parser.expect_keyword(Keyword::IS)?;
66    let comment = if parser.parse_keyword(Keyword::NULL) {
67        None
68    } else {
69        Some(parser.parse_literal_string()?)
70    };
71    Ok(Statement::Comment {
72        object_type,
73        object_name,
74        comment,
75        if_exists,
76    })
77}