use crate::{
db::{
predicate::CompareOp,
reduced_sql::{Keyword, SqlParseError, TokenKind},
sql::parser::{Parser, SqlHavingClause, SqlHavingSymbol, SqlOrderDirection, SqlOrderTerm},
},
value::Value,
};
impl Parser {
pub(super) fn parse_order_terms(&mut self) -> Result<Vec<SqlOrderTerm>, SqlParseError> {
let mut terms = Vec::new();
loop {
let field = self.expect_identifier()?;
let direction = if self.eat_keyword(Keyword::Desc) {
SqlOrderDirection::Desc
} else {
self.eat_keyword(Keyword::Asc);
SqlOrderDirection::Asc
};
terms.push(SqlOrderTerm { field, direction });
if !self.eat_comma() {
break;
}
}
Ok(terms)
}
pub(super) fn parse_having_clauses(&mut self) -> Result<Vec<SqlHavingClause>, SqlParseError> {
let mut clauses = vec![self.parse_having_clause()?];
while self.eat_keyword(Keyword::And) {
clauses.push(self.parse_having_clause()?);
}
if self.peek_keyword(Keyword::Or) || self.peek_keyword(Keyword::Not) {
return Err(SqlParseError::unsupported_feature(
"HAVING boolean operators beyond AND",
));
}
Ok(clauses)
}
pub(super) fn parse_identifier_list(&mut self) -> Result<Vec<String>, SqlParseError> {
let mut fields = vec![self.expect_identifier()?];
while self.eat_comma() {
fields.push(self.expect_identifier()?);
}
Ok(fields)
}
pub(super) fn reject_table_alias_if_present(&self) -> Result<(), SqlParseError> {
if self.peek_keyword(Keyword::As)
|| matches!(self.peek_kind(), Some(TokenKind::Identifier(_)))
{
return Err(SqlParseError::unsupported_feature("table aliases"));
}
Ok(())
}
fn parse_having_clause(&mut self) -> Result<SqlHavingClause, SqlParseError> {
let symbol = self.parse_having_symbol()?;
if self.eat_keyword(Keyword::Is) {
let is_not = self.eat_keyword(Keyword::Not);
self.expect_keyword(Keyword::Null)?;
return Ok(SqlHavingClause {
symbol,
op: if is_not { CompareOp::Ne } else { CompareOp::Eq },
value: Value::Null,
});
}
let op = self.parse_compare_operator()?;
let value = self.parse_literal()?;
Ok(SqlHavingClause { symbol, op, value })
}
fn parse_having_symbol(&mut self) -> Result<SqlHavingSymbol, SqlParseError> {
if let Some(kind) = self.parse_aggregate_kind() {
return Ok(SqlHavingSymbol::Aggregate(self.parse_aggregate_call(kind)?));
}
let field = self.expect_identifier()?;
if self.peek_lparen() {
return Err(SqlParseError::unsupported_feature(
"SQL function namespace beyond supported aggregate forms",
));
}
Ok(SqlHavingSymbol::Field(field))
}
}