From 51d40092db459c30a5340aa0a68dae385d1da7dd Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sun, 24 Aug 2025 17:55:30 +0530 Subject: [PATCH] add empty table references, and error out in case if the table references are present in limit/offset --- core/translate/delete.rs | 4 ++-- core/translate/planner.rs | 14 ++++++++++++++ core/translate/select.rs | 10 +++++----- core/translate/update.rs | 5 +++-- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/core/translate/delete.rs b/core/translate/delete.rs index b2bcda24d..8f9cf48ca 100644 --- a/core/translate/delete.rs +++ b/core/translate/delete.rs @@ -2,7 +2,7 @@ use crate::schema::Table; use crate::translate::emitter::emit_program; use crate::translate::optimizer::optimize_plan; use crate::translate::plan::{DeletePlan, Operation, Plan}; -use crate::translate::planner::parse_where; +use crate::translate::planner::{parse_limit, parse_where}; use crate::util::normalize_ident; use crate::vdbe::builder::{ProgramBuilder, ProgramBuilderOpts, TableRefIdCounter}; use crate::{schema::Schema, Result, SymbolTable}; @@ -108,7 +108,7 @@ pub fn prepare_delete_plan( // Parse the LIMIT/OFFSET clause let (resolved_limit, resolved_offset) = - limit.map_or((None, None), |l| (Some(l.expr), l.offset)); + limit.map_or(Ok((None, None)), |mut l| parse_limit(&mut l, connection))?; let plan = DeletePlan { table_references, diff --git a/core/translate/planner.rs b/core/translate/planner.rs index fcc6f572c..9757c05f1 100644 --- a/core/translate/planner.rs +++ b/core/translate/planner.rs @@ -12,6 +12,7 @@ use super::{ }; use crate::translate::expr::WalkControl; use crate::{ + ast::Limit, function::Func, schema::{Schema, Table}, translate::expr::walk_expr_mut, @@ -1138,3 +1139,16 @@ where } Ok(None) } + +#[allow(clippy::type_complexity)] +pub fn parse_limit( + limit: &mut Limit, + connection: &std::sync::Arc, +) -> Result<(Option>, Option>)> { + let mut empty_refs = TableReferences::new(Vec::new(), Vec::new()); + bind_column_references(&mut limit.expr, &mut empty_refs, None, connection)?; + if let Some(ref mut off_expr) = limit.offset { + bind_column_references(off_expr, &mut empty_refs, None, connection)?; + } + Ok((Some(limit.expr.clone()), limit.offset.clone())) +} diff --git a/core/translate/select.rs b/core/translate/select.rs index 65344fc41..21330c53d 100644 --- a/core/translate/select.rs +++ b/core/translate/select.rs @@ -8,8 +8,8 @@ use crate::schema::Table; use crate::translate::optimizer::optimize_plan; use crate::translate::plan::{Aggregate, GroupBy, Plan, ResultSetColumn, SelectPlan}; use crate::translate::planner::{ - bind_column_references, break_predicate_at_and_boundaries, parse_from, parse_where, - resolve_aggregates, + bind_column_references, break_predicate_at_and_boundaries, parse_from, parse_limit, + parse_where, resolve_aggregates, }; use crate::util::normalize_ident; use crate::vdbe::builder::{ProgramBuilderOpts, TableRefIdCounter}; @@ -151,7 +151,7 @@ pub fn prepare_select_plan( } let (limit, offset) = select .limit - .map_or((None, None), |l| (Some(l.expr), l.offset)); + .map_or(Ok((None, None)), |mut l| parse_limit(&mut l, connection))?; // FIXME: handle ORDER BY for compound selects if !select.order_by.is_empty() { @@ -621,8 +621,8 @@ fn prepare_one_select_plan( plan.order_by = key; // Parse the LIMIT/OFFSET clause - (plan.limit, plan.offset) = limit.map_or((None, None), |l| (Some(l.expr), l.offset)); - + (plan.limit, plan.offset) = + limit.map_or(Ok((None, None)), |mut l| parse_limit(&mut l, connection))?; // Return the unoptimized query plan Ok(plan) } diff --git a/core/translate/update.rs b/core/translate/update.rs index 96f4769a5..676fd37ca 100644 --- a/core/translate/update.rs +++ b/core/translate/update.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use crate::schema::{BTreeTable, Column, Type}; use crate::translate::optimizer::optimize_select_plan; use crate::translate::plan::{Operation, QueryDestination, Scan, Search, SelectPlan}; +use crate::translate::planner::parse_limit; use crate::vdbe::builder::CursorType; use crate::{ bail_parse_error, @@ -332,8 +333,8 @@ pub fn prepare_update_plan( // Parse the LIMIT/OFFSET clause let (limit, offset) = body .limit - .as_ref() - .map_or((None, None), |l| (Some(l.expr.clone()), l.offset.clone())); + .as_mut() + .map_or(Ok((None, None)), |l| parse_limit(l, connection))?; // Check what indexes will need to be updated by checking set_clauses and see // if a column is contained in an index.