From 81732f335abdeb22ff4e174beee48805a7e6f3a0 Mon Sep 17 00:00:00 2001 From: Alex Qyoun-ae <4062971+MazterQyou@users.noreply.github.com> Date: Wed, 10 Aug 2022 05:20:15 +0400 Subject: [PATCH] Support expressions in `LIMIT`/`OFFSET` --- src/parser.rs | 4 ++-- tests/sqlparser_common.rs | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 76190feb9..1d3dccb07 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -4402,13 +4402,13 @@ impl<'a> Parser<'a> { if self.parse_keyword(Keyword::ALL) { Ok(None) } else { - Ok(Some(Expr::Value(self.parse_number_value()?))) + Ok(Some(self.parse_expr()?)) } } /// Parse an OFFSET clause pub fn parse_offset(&mut self) -> Result { - let value = Expr::Value(self.parse_number_value()?); + let value = self.parse_expr()?; let rows = if self.parse_keyword(Keyword::ROW) { OffsetRows::Row } else if self.parse_keyword(Keyword::ROWS) { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index ef6011841..0f818e5fc 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -5010,6 +5010,20 @@ fn test_placeholder() { right: Box::new(Expr::Value(Value::Placeholder("$Id1".into()))) }) ); + + let sql = "SELECT * FROM student LIMIT $1 OFFSET $2"; + let ast = dialects.verified_query(sql); + assert_eq!( + ast.limit, + Some(Expr::Value(Value::Placeholder("$1".into()))) + ); + assert_eq!( + ast.offset, + Some(Offset { + value: Expr::Value(Value::Placeholder("$2".into())), + rows: OffsetRows::None, + }), + ); } #[test] @@ -5058,6 +5072,29 @@ fn parse_offset_and_limit() { // different order is OK one_statement_parses_to("SELECT foo FROM bar OFFSET 2 LIMIT 2", sql); + // expressions are allowed + let sql = "SELECT foo FROM bar LIMIT 1 + 2 OFFSET 3 * 4"; + let ast = verified_query(sql); + assert_eq!( + ast.limit, + Some(Expr::BinaryOp { + left: Box::new(Expr::Value(number("1"))), + op: BinaryOperator::Plus, + right: Box::new(Expr::Value(number("2"))), + }), + ); + assert_eq!( + ast.offset, + Some(Offset { + value: Expr::BinaryOp { + left: Box::new(Expr::Value(number("3"))), + op: BinaryOperator::Multiply, + right: Box::new(Expr::Value(number("4"))), + }, + rows: OffsetRows::None, + }), + ); + // Can't repeat OFFSET / LIMIT let res = parse_sql_statements("SELECT foo FROM bar OFFSET 2 OFFSET 2"); assert_eq!(