sqlparser/dialect/
postgresql.rs1use 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 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}