use log::debug;
use crate::dialect::{Dialect, Precedence};
use crate::keywords::Keyword;
use crate::parser::{Parser, ParserError};
use crate::tokenizer::Token;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PostgreSqlDialect {}
const PERIOD_PREC: u8 = 200;
const DOUBLE_COLON_PREC: u8 = 140;
const BRACKET_PREC: u8 = 130;
const COLLATE_PREC: u8 = 120;
const AT_TZ_PREC: u8 = 110;
const CARET_PREC: u8 = 100;
const MUL_DIV_MOD_OP_PREC: u8 = 90;
const PLUS_MINUS_PREC: u8 = 80;
const XOR_PREC: u8 = 75;
const PG_OTHER_PREC: u8 = 70;
const BETWEEN_LIKE_PREC: u8 = 60;
const EQ_PREC: u8 = 50;
const IS_PREC: u8 = 40;
const NOT_PREC: u8 = 30;
const AND_PREC: u8 = 20;
const OR_PREC: u8 = 10;
impl Dialect for PostgreSqlDialect {
fn identifier_quote_style(&self, _identifier: &str) -> Option<char> {
Some('"')
}
fn is_delimited_identifier_start(&self, ch: char) -> bool {
ch == '"' }
fn is_identifier_start(&self, ch: char) -> bool {
ch.is_alphabetic() || ch == '_' ||
!ch.is_ascii()
}
fn is_identifier_part(&self, ch: char) -> bool {
ch.is_alphabetic() || ch.is_ascii_digit() || ch == '$' || ch == '_' ||
!ch.is_ascii()
}
fn supports_unicode_string_literal(&self) -> bool {
true
}
fn is_custom_operator_part(&self, ch: char) -> bool {
matches!(
ch,
'+' | '-'
| '*'
| '/'
| '<'
| '>'
| '='
| '~'
| '!'
| '@'
| '#'
| '%'
| '^'
| '&'
| '|'
| '`'
| '?'
)
}
fn get_next_precedence(&self, parser: &Parser) -> Option<Result<u8, ParserError>> {
let token = parser.peek_token();
debug!("get_next_precedence() {token:?}");
match token.token {
Token::Word(w)
if w.keyword == Keyword::COLLATE && !parser.in_column_definition_state() =>
{
Some(Ok(COLLATE_PREC))
}
Token::LBracket => Some(Ok(BRACKET_PREC)),
Token::Arrow
| Token::LongArrow
| Token::HashArrow
| Token::HashLongArrow
| Token::AtArrow
| Token::ArrowAt
| Token::HashMinus
| Token::AtQuestion
| Token::AtAt
| Token::Question
| Token::QuestionAnd
| Token::QuestionPipe
| Token::ExclamationMark
| Token::Overlap
| Token::CaretAt
| Token::StringConcat
| Token::Sharp
| Token::ShiftRight
| Token::ShiftLeft
| Token::CustomBinaryOperator(_) => Some(Ok(PG_OTHER_PREC)),
Token::Colon => Some(Ok(self.prec_unknown())),
_ => None,
}
}
fn supports_filter_during_aggregation(&self) -> bool {
true
}
fn supports_group_by_expr(&self) -> bool {
true
}
fn prec_value(&self, prec: Precedence) -> u8 {
match prec {
Precedence::Period => PERIOD_PREC,
Precedence::DoubleColon => DOUBLE_COLON_PREC,
Precedence::AtTz => AT_TZ_PREC,
Precedence::MulDivModOp => MUL_DIV_MOD_OP_PREC,
Precedence::PlusMinus => PLUS_MINUS_PREC,
Precedence::Xor => XOR_PREC,
Precedence::Ampersand => PG_OTHER_PREC,
Precedence::Caret => CARET_PREC,
Precedence::Pipe => PG_OTHER_PREC,
Precedence::Colon => PG_OTHER_PREC,
Precedence::Between => BETWEEN_LIKE_PREC,
Precedence::Eq => EQ_PREC,
Precedence::Like => BETWEEN_LIKE_PREC,
Precedence::Is => IS_PREC,
Precedence::PgOther => PG_OTHER_PREC,
Precedence::UnaryNot => NOT_PREC,
Precedence::And => AND_PREC,
Precedence::Or => OR_PREC,
}
}
fn allow_extract_custom(&self) -> bool {
true
}
fn allow_extract_single_quotes(&self) -> bool {
true
}
fn supports_create_index_with_clause(&self) -> bool {
true
}
fn supports_explain_with_utility_options(&self) -> bool {
true
}
fn supports_listen_notify(&self) -> bool {
true
}
fn supports_factorial_operator(&self) -> bool {
true
}
fn supports_bitwise_shift_operators(&self) -> bool {
true
}
fn supports_comment_on(&self) -> bool {
true
}
fn supports_load_extension(&self) -> bool {
true
}
fn supports_named_fn_args_with_colon_operator(&self) -> bool {
true
}
fn supports_named_fn_args_with_expr_name(&self) -> bool {
true
}
fn supports_empty_projections(&self) -> bool {
true
}
fn supports_nested_comments(&self) -> bool {
true
}
fn supports_string_escape_constant(&self) -> bool {
true
}
fn supports_numeric_literal_underscores(&self) -> bool {
true
}
fn supports_array_typedef_with_brackets(&self) -> bool {
true
}
fn supports_geometric_types(&self) -> bool {
true
}
fn supports_set_names(&self) -> bool {
true
}
fn supports_alter_column_type_using(&self) -> bool {
true
}
fn supports_notnull_operator(&self) -> bool {
true
}
fn supports_interval_options(&self) -> bool {
true
}
}