use crate::db::sql::parser::projection::SqlExprParseSurface;
use crate::db::{
sql::parser::{
Parser, SqlExpr, SqlExprBinaryOp, SqlOrderDirection, SqlOrderTerm, SqlScalarFunction,
},
sql_shared::{Keyword, SqlParseError},
};
const ORDER_BY_UNSUPPORTED_FEATURE: &str = "ORDER BY terms beyond supported fields, bounded arithmetic, or supported scalar-function forms";
impl Parser {
pub(super) fn parse_order_terms(&mut self) -> Result<Vec<SqlOrderTerm>, SqlParseError> {
let mut terms = Vec::new();
loop {
let field = self.record_expr_parse_stage(Self::parse_order_term_target)?;
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)
}
fn parse_order_term_target(&mut self) -> Result<SqlExpr, SqlParseError> {
if let Some(kind) = self.parse_aggregate_kind() {
let aggregate = self.parse_aggregate_call(kind)?;
if let Some(op) = self.parse_direct_order_arithmetic_op() {
return self
.parse_projection_arithmetic_from_left(SqlExpr::Aggregate(aggregate), op);
}
return Ok(SqlExpr::Aggregate(aggregate));
}
let field = self.expect_identifier()?;
if let Some(op) = self.parse_direct_order_arithmetic_op() {
return self
.parse_projection_arithmetic_from_left(SqlExpr::from_field_identifier(field), op);
}
if !self.peek_lparen() {
return Ok(SqlExpr::from_field_identifier(field));
}
let Some(function) = SqlScalarFunction::from_identifier(field.as_str()) else {
return Err(SqlParseError::unsupported_feature(
ORDER_BY_UNSUPPORTED_FEATURE,
));
};
self.parse_scalar_function_call(function, SqlExprParseSurface::Projection)
}
fn parse_direct_order_arithmetic_op(&mut self) -> Option<SqlExprBinaryOp> {
if self.eat_plus() {
return Some(SqlExprBinaryOp::Add);
}
if self.eat_minus() {
return Some(SqlExprBinaryOp::Sub);
}
if self.eat_star() {
return Some(SqlExprBinaryOp::Mul);
}
if self.eat_slash() {
return Some(SqlExprBinaryOp::Div);
}
None
}
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)
}
}