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)]
21pub struct PostgreSqlDialect {}
22
23impl Dialect for PostgreSqlDialect {
24 fn is_identifier_start(&self, ch: char) -> bool {
25 ch.is_alphabetic() || ch == '_'
29 }
30
31 fn is_identifier_part(&self, ch: char) -> bool {
32 ch.is_alphabetic() || ch.is_ascii_digit() || ch == '$' || ch == '_'
33 }
34
35 fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
36 if parser.parse_keyword(Keyword::COMMENT) {
37 Some(parse_comment(parser))
38 } else {
39 None
40 }
41 }
42
43 fn supports_filter_during_aggregation(&self) -> bool {
44 true
45 }
46
47 fn supports_group_by_expr(&self) -> bool {
48 true
49 }
50}
51
52pub fn parse_comment(parser: &mut Parser) -> Result<Statement, ParserError> {
53 let if_exists = parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
54
55 parser.expect_keyword(Keyword::ON)?;
56 let token = parser.next_token();
57
58 let (object_type, object_name) = match token.token {
59 Token::Word(w) if w.keyword == Keyword::COLUMN => {
60 let object_name = parser.parse_object_name(false)?;
61 (CommentObject::Column, object_name)
62 }
63 Token::Word(w) if w.keyword == Keyword::TABLE => {
64 let object_name = parser.parse_object_name(false)?;
65 (CommentObject::Table, object_name)
66 }
67 _ => parser.expected("comment object_type", token)?,
68 };
69
70 parser.expect_keyword(Keyword::IS)?;
71 let comment = if parser.parse_keyword(Keyword::NULL) {
72 None
73 } else {
74 Some(parser.parse_literal_string()?)
75 };
76 Ok(Statement::Comment {
77 object_type,
78 object_name,
79 comment,
80 if_exists,
81 })
82}