use crate::parser::{
ParseError, QueryParser,
ast::{Literal, ScalarExpr},
};
pub struct LimitAndOffsetParser;
impl LimitAndOffsetParser {
pub fn parse(parser: &mut QueryParser) -> Result<(Option<i64>, Option<i64>), ParseError> {
let mut limit = None;
let mut offset = None;
while !parser.check_next_phase() {
if parser.comparers.limit.compare(parser) {
parser.jump(parser.comparers.limit.length);
let value = ScalarExpr::parse(parser, false)?;
match value {
ScalarExpr::Literal(Literal::Int(value)) => limit = Some(value),
_ => {
return ParseError::new(
"Invalid limit",
parser.get_initial_sequence_pos(),
parser,
)
.err();
}
}
} else if parser.comparers.offset.compare(parser) {
parser.jump(parser.comparers.offset.length);
let value = ScalarExpr::parse(parser, false)?;
match value {
ScalarExpr::Literal(Literal::Int(value)) => offset = Some(value),
_ => {
return ParseError::new(
"Invalid offset",
parser.get_initial_sequence_pos(),
parser,
)
.err();
}
}
} else {
return ParseError::new(
"Invalid offset",
parser.get_initial_sequence_pos(),
parser,
)
.err();
}
}
Ok((limit, offset))
}
}
#[cfg(test)]
mod tests {
use crate::parser::{QueryParser, ast::LimitAndOffsetParser};
#[test]
pub fn test_limit() {
let text = "LIMIT 10";
let mut parser = QueryParser::new(text);
parser.check_next_phase();
let (limit, offset) =
LimitAndOffsetParser::parse(&mut parser).expect("Failed to parse limit and offset");
assert_eq!(limit.unwrap(), 10);
assert!(offset.is_none());
}
#[test]
pub fn test_offset() {
let text = "OFFSET 10";
let mut parser = QueryParser::new(text);
parser.check_next_phase();
let (limit, offset) =
LimitAndOffsetParser::parse(&mut parser).expect("Failed to parse limit and offset");
assert!(limit.is_none());
assert_eq!(offset.unwrap(), 10);
}
#[test]
pub fn test_offset_and_limit() {
let text = "OFFSET 20 LIMIT 30";
let mut parser = QueryParser::new(text);
parser.check_next_phase();
let (limit, offset) =
LimitAndOffsetParser::parse(&mut parser).expect("Failed to parse limit and offset");
assert_eq!(limit.unwrap(), 30);
assert_eq!(offset.unwrap(), 20);
}
#[test]
pub fn test_offset_and_limit_wrong_limit() {
let text = "OFFSET 20 LIMIT AB";
let mut parser = QueryParser::new(text);
parser.check_next_phase();
let result = LimitAndOffsetParser::parse(&mut parser);
match result {
Ok(_) => panic!(),
Err(err) => {
assert_eq!(err.text, "AB");
assert_eq!(err.start, 16);
assert_eq!(err.end, 18);
}
}
}
#[test]
pub fn test_offset_and_limit_wrong_offset() {
let text = "OFFSET 20 30 LIMIT AB";
let mut parser = QueryParser::new(text);
parser.check_next_phase();
let result = LimitAndOffsetParser::parse(&mut parser);
match result {
Ok(_) => panic!(),
Err(err) => {
assert_eq!(err.text, "3");
assert_eq!(err.start, 10);
assert_eq!(err.end, 10);
}
}
}
#[test]
pub fn test_offset_and_limit_wrong_phase() {
let text = "OFFSET 20 LIMIT 60 GROUP BY ";
let mut parser = QueryParser::new(text);
parser.check_next_phase();
let result = LimitAndOffsetParser::parse(&mut parser);
match result {
Ok(_) => panic!(),
Err(err) => {
assert_eq!(err.text, "G");
assert_eq!(err.start, 19);
assert_eq!(err.end, 19);
}
}
}
}