pub struct SelectExecutor<'a> {
pub timeout_seconds: u64,
/* private fields */
}Expand description
Executes SELECT queries
Fields§
§timeout_seconds: u64Timeout in seconds (defaults to MAX_QUERY_EXECUTION_SECONDS)
Implementations§
Source§impl SelectExecutor<'_>
impl SelectExecutor<'_>
Sourcepub fn execute_select_arena<'arena>(
&self,
stmt: &ArenaSelectStmt<'arena>,
params: &[SqlValue],
interner: &'arena ArenaInterner<'arena>,
) -> Result<Vec<Row>, ExecutorError>
pub fn execute_select_arena<'arena>( &self, stmt: &ArenaSelectStmt<'arena>, params: &[SqlValue], interner: &'arena ArenaInterner<'arena>, ) -> Result<Vec<Row>, ExecutorError>
Execute an arena-allocated SELECT statement with inline placeholder resolution.
This method provides zero-allocation query execution for prepared statements. Parameters are resolved inline during evaluation, avoiding AST cloning.
§Arguments
stmt- Arena-allocated SELECT statementparams- Parameter values for placeholder resolution
§Returns
Vector of result rows.
§Limitations
Currently supports simple SELECT queries without:
- JOINs (single table only)
- Subqueries
- Aggregates, GROUP BY, HAVING
- Window functions
- CTEs (WITH clause)
For unsupported features, returns an error. Fall back to standard execution.
Source§impl<'a> SelectExecutor<'a>
impl<'a> SelectExecutor<'a>
Sourcepub fn new(database: &'a Database) -> Self
pub fn new(database: &'a Database) -> Self
Create a new SELECT executor
§Performance
This constructor is optimized for OLTP workloads:
- Arena is lazily initialized (10MB allocation deferred until needed)
- Aggregate cache is lazily initialized (HashMap allocation deferred)
- Simple queries that don’t use aggregates or complex allocations skip these costs
Sourcepub fn new_with_outer_context(
database: &'a Database,
outer_row: &'a Row,
outer_schema: &'a CombinedSchema,
) -> Self
pub fn new_with_outer_context( database: &'a Database, outer_row: &'a Row, outer_schema: &'a CombinedSchema, ) -> Self
Create a new SELECT executor with outer context for correlated subqueries
Sourcepub fn new_with_depth(database: &'a Database, parent_depth: usize) -> Self
pub fn new_with_depth(database: &'a Database, parent_depth: usize) -> Self
Create a new SELECT executor with explicit depth tracking Used for non-correlated subqueries to propagate depth limit enforcement
Sourcepub fn new_with_outer_context_and_depth(
database: &'a Database,
outer_row: &'a Row,
outer_schema: &'a CombinedSchema,
parent_depth: usize,
) -> Self
pub fn new_with_outer_context_and_depth( database: &'a Database, outer_row: &'a Row, outer_schema: &'a CombinedSchema, parent_depth: usize, ) -> Self
Create a new SELECT executor with outer context and explicit depth Used when creating subquery executors to track nesting depth
§Note on Timeout Inheritance
Currently subqueries get their own 60s timeout rather than sharing parent’s timeout. This means a query with N subqueries could run for up to N*60s instead of 60s total.
However, this is acceptable for the initial fix because:
- The main regression (100% timeout) was caused by ZERO timeout enforcement
- Having per-subquery timeouts still prevents infinite loops (the core issue)
- Most problematic queries cause recursive subquery execution, which IS caught
- Threading timeout through evaluators requires extensive refactoring
Future improvement: Add timeout fields to ExpressionEvaluator and pass through See: https://github.com/rjwalters/vibesql/issues/1012#subquery-timeout
Sourcepub fn new_with_procedural_context(
database: &'a Database,
procedural_context: &'a ExecutionContext,
) -> Self
pub fn new_with_procedural_context( database: &'a Database, procedural_context: &'a ExecutionContext, ) -> Self
Create a new SELECT executor with procedural context for stored procedures/functions
Sourcepub fn new_with_cte_and_depth(
database: &'a Database,
cte_context: &'a HashMap<String, CteResult>,
parent_depth: usize,
) -> Self
pub fn new_with_cte_and_depth( database: &'a Database, cte_context: &'a HashMap<String, CteResult>, parent_depth: usize, ) -> Self
Create a new SELECT executor with CTE context and depth tracking Used for non-correlated subqueries that need access to parent CTEs
Sourcepub fn new_with_outer_and_cte_and_depth(
database: &'a Database,
outer_row: &'a Row,
outer_schema: &'a CombinedSchema,
cte_context: &'a HashMap<String, CteResult>,
parent_depth: usize,
) -> Self
pub fn new_with_outer_and_cte_and_depth( database: &'a Database, outer_row: &'a Row, outer_schema: &'a CombinedSchema, cte_context: &'a HashMap<String, CteResult>, parent_depth: usize, ) -> Self
Create a new SELECT executor with outer context, CTE context, and depth tracking Used for correlated subqueries that need access to both outer row and parent CTEs
Sourcepub fn with_timeout(self, seconds: u64) -> Self
pub fn with_timeout(self, seconds: u64) -> Self
Override default timeout for this query (useful for testing)
Sourcepub fn check_timeout(&self) -> Result<(), ExecutorError>
pub fn check_timeout(&self) -> Result<(), ExecutorError>
Check if query has exceeded timeout Call this in hot loops to prevent infinite execution
Sourcepub fn reset_for_reuse(&mut self)
pub fn reset_for_reuse(&mut self)
Reset the executor for reuse between queries
This method prepares the executor for a new query execution by:
- Resetting the start time to now
- Clearing memory tracking counters
- Resetting the arena (if initialized)
- Clearing the aggregate cache (if initialized)
§Performance
Call this method to reuse an executor instead of creating a new one. This avoids the allocation overhead of creating new HashMap and arena instances.
Source§impl SelectExecutor<'_>
impl SelectExecutor<'_>
Sourcepub fn execute(&self, stmt: &SelectStmt) -> Result<Vec<Row>, ExecutorError>
pub fn execute(&self, stmt: &SelectStmt) -> Result<Vec<Row>, ExecutorError>
Execute a SELECT statement
Sourcepub fn execute_iter(
&self,
stmt: &SelectStmt,
) -> Result<impl Iterator<Item = Row>, ExecutorError>
pub fn execute_iter( &self, stmt: &SelectStmt, ) -> Result<impl Iterator<Item = Row>, ExecutorError>
Execute a SELECT statement and return an iterator over results
This enables early termination when the full result set is not needed, such as for IN subqueries where we stop after finding the first match.
§Phase 1 Implementation (Early Termination for IN subqueries)
Current implementation materializes results then returns an iterator. This still enables early termination in the consumer (e.g., eval_in_subquery) by stopping iteration when a match is found.
Future optimization: Leverage the existing RowIterator infrastructure (crate::select::iterator) for truly lazy evaluation that stops execution early, not just iteration.
Sourcepub fn execute_with_columns(
&self,
stmt: &SelectStmt,
) -> Result<SelectResult, ExecutorError>
pub fn execute_with_columns( &self, stmt: &SelectStmt, ) -> Result<SelectResult, ExecutorError>
Execute a SELECT statement and return both columns and rows
Auto Trait Implementations§
impl<'a> !Freeze for SelectExecutor<'a>
impl<'a> !RefUnwindSafe for SelectExecutor<'a>
impl<'a> Send for SelectExecutor<'a>
impl<'a> !Sync for SelectExecutor<'a>
impl<'a> Unpin for SelectExecutor<'a>
impl<'a> !UnwindSafe for SelectExecutor<'a>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more