From d03a0dbd39dd5a5bfc2f46b461dc5034dae39180 Mon Sep 17 00:00:00 2001 From: ben594 Date: Thu, 23 Jan 2025 10:16:35 -0500 Subject: [PATCH] Added parsing of offset clause --- core/translate/delete.rs | 5 +++-- core/translate/plan.rs | 4 ++++ core/translate/planner.rs | 23 +++++++++++++++++------ core/translate/select.rs | 6 ++++-- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/core/translate/delete.rs b/core/translate/delete.rs index 373a74024..6bbe6270b 100644 --- a/core/translate/delete.rs +++ b/core/translate/delete.rs @@ -44,8 +44,8 @@ pub fn prepare_delete_plan( // Parse the WHERE clause let resolved_where_clauses = parse_where(where_clause, &referenced_tables)?; - // Parse the LIMIT clause - let resolved_limit = limit.and_then(|l| parse_limit(*l)); + // Parse the LIMIT/OFFSET clause + let (resolved_limit, resolved_offset) = limit.map_or(Ok((None, None)), |l| parse_limit(*l))?; let plan = DeletePlan { source: SourceOperator::Scan { @@ -58,6 +58,7 @@ pub fn prepare_delete_plan( where_clause: resolved_where_clauses, order_by: None, limit: resolved_limit, + offset: resolved_offset, referenced_tables, available_indexes: vec![], contains_constant_false_condition: false, diff --git a/core/translate/plan.rs b/core/translate/plan.rs index 6164428fb..87420b622 100644 --- a/core/translate/plan.rs +++ b/core/translate/plan.rs @@ -65,6 +65,8 @@ pub struct SelectPlan { pub aggregates: Vec, /// limit clause pub limit: Option, + /// offset clause + pub offset: Option, /// all the tables referenced in the query pub referenced_tables: Vec, /// all the indexes available @@ -88,6 +90,8 @@ pub struct DeletePlan { pub order_by: Option>, /// limit clause pub limit: Option, + /// offset clause + pub offset: Option, /// all the tables referenced in the query pub referenced_tables: Vec, /// all the indexes available diff --git a/core/translate/planner.rs b/core/translate/planner.rs index 86132fb60..5c5920896 100644 --- a/core/translate/planner.rs +++ b/core/translate/planner.rs @@ -566,19 +566,30 @@ fn parse_join( }) } -pub fn parse_limit(limit: Limit) -> Option { +pub fn parse_limit(limit: Limit) -> Result<(Option, Option)> { + let offset = match limit.offset { + Some(offset_expr) => { + if let Expr::Literal(ast::Literal::Numeric(n)) = offset_expr { + n.parse().ok() + } else { + crate::bail_parse_error!("Invalid OFFSET clause"); + } + } + None => Some(0), + }; + if let Expr::Literal(ast::Literal::Numeric(n)) = limit.expr { - n.parse().ok() + Ok((n.parse().ok(), offset)) } else if let Expr::Id(id) = limit.expr { if id.0.eq_ignore_ascii_case("true") { - Some(1) + Ok((Some(1), offset)) } else if id.0.eq_ignore_ascii_case("false") { - Some(0) + Ok((Some(0), offset)) } else { - None + crate::bail_parse_error!("Invalid LIMIT clause"); } } else { - None + crate::bail_parse_error!("Invalid LIMIT clause"); } } diff --git a/core/translate/select.rs b/core/translate/select.rs index 196a1d284..46226abbd 100644 --- a/core/translate/select.rs +++ b/core/translate/select.rs @@ -57,6 +57,7 @@ pub fn prepare_select_plan( order_by: None, aggregates: vec![], limit: None, + offset: None, referenced_tables, available_indexes: schema.indexes.clone().into_values().flatten().collect(), contains_constant_false_condition: false, @@ -326,8 +327,9 @@ pub fn prepare_select_plan( plan.order_by = Some(key); } - // Parse the LIMIT clause - plan.limit = select.limit.and_then(|l| parse_limit(*l)); + // Parse the LIMIT/OFFSET clause + (plan.limit, plan.offset) = + select.limit.map_or(Ok((None, None)), |l| parse_limit(*l))?; // Return the unoptimized query plan Ok(Plan::Select(plan))