shape_ast/parser/queries/
helpers.rs1use crate::error::{Result, ShapeError};
4use crate::parser::pair_location;
5use pest::iterators::Pair;
6
7use crate::ast::{Expr, OrderByClause, QueryModifiers, SortDirection};
8use crate::parser::{Rule, expressions};
9
10pub fn parse_query_modifiers(pair: Pair<Rule>, modifiers: &mut QueryModifiers) -> Result<()> {
12 match pair.as_rule() {
13 Rule::limit_clause => {
14 let inner = pair
15 .into_inner()
16 .next()
17 .ok_or_else(|| ShapeError::ParseError {
18 message: "expected integer after 'limit'".to_string(),
19 location: None,
20 })?;
21 let limit_str = inner.as_str();
22 let limit_val = limit_str
23 .parse::<usize>()
24 .map_err(|_| ShapeError::ParseError {
25 message: format!(
26 "invalid limit value: '{}' - must be a positive integer",
27 limit_str
28 ),
29 location: Some(pair_location(&inner)),
30 })?;
31 modifiers.limit = Some(limit_val);
32 }
33 Rule::order_by_clause => {
34 let mut columns = Vec::new();
35 for inner in pair.into_inner() {
36 if inner.as_rule() == Rule::order_by_list {
37 for item in inner.into_inner() {
38 if item.as_rule() == Rule::order_by_item {
39 let (expr, direction) = parse_order_by_item(item)?;
40 columns.push((expr, direction));
41 }
42 }
43 }
44 }
45 modifiers.order_by = Some(OrderByClause { columns });
46 }
47 _ => {}
48 }
49 Ok(())
50}
51
52fn parse_order_by_item(pair: Pair<Rule>) -> Result<(Expr, SortDirection)> {
54 let mut inner = pair.into_inner();
55
56 let expr_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
58 message: "expected expression in ORDER BY clause".to_string(),
59 location: None,
60 })?;
61 let expr = expressions::parse_expression(expr_pair)?;
62
63 let direction = if let Some(dir_pair) = inner.next() {
65 match dir_pair.as_str().to_lowercase().as_str() {
66 "asc" => SortDirection::Ascending,
67 "desc" => SortDirection::Descending,
68 _ => SortDirection::Ascending,
69 }
70 } else {
71 SortDirection::Ascending
72 };
73
74 Ok((expr, direction))
75}