pub struct SelectExecutor { /* private fields */ }Expand description
SELECT query executor for SSTable-based storage
Implementations§
Source§impl SelectExecutor
impl SelectExecutor
Sourcepub async fn execute(&self, plan: OptimizedQueryPlan) -> Result<QueryResult>
pub async fn execute(&self, plan: OptimizedQueryPlan) -> Result<QueryResult>
Execute an optimized query plan.
Instrumented as query.select.plan (issue #1035): this span covers the
modern SELECT pipeline — SSTable scan, filtering, projection, aggregation,
and WRITETIME/TTL metadata extraction — and is the parent under which the
read-path spans (issue #1034) nest. On completion it emits
[catalog::QUERY_ROWS_SCANNED] (rows the scan step examined) dimensioned by
the honest access path, so the rows-scanned vs rows-returned gap is
observable. The bounded access-path attribute is recorded on the span; the
query text and key values never are.
Source§impl SelectExecutor
impl SelectExecutor
Sourcepub fn new(schema: Arc<SchemaManager>, storage: Arc<StorageEngine>) -> Self
pub fn new(schema: Arc<SchemaManager>, storage: Arc<StorageEngine>) -> Self
Create a new SELECT executor with a system (wall-clock) now source.
Uses the default materialized-result byte budget
(crate::config::DEFAULT_MAX_RESULT_BYTES); call
SelectExecutor::with_max_result_bytes to override it (the query
engine wires it from crate::config::QueryConfig::max_result_bytes).
Sourcepub fn with_max_result_bytes(self, max_result_bytes: usize) -> Self
pub fn with_max_result_bytes(self, max_result_bytes: usize) -> Self
Override the byte ceiling on a materialized result set (issue #1582).
Builder-style: the query engine calls this with
crate::config::QueryConfig::max_result_bytes so the config knob is
load-bearing on the read path.
Sourcepub fn with_max_result_rows(self, max_result_rows: usize) -> Self
pub fn with_max_result_rows(self, max_result_rows: usize) -> Self
Override the row-count safety valve on a materialized result set (issue #1582).
Builder-style: the query engine calls this with
crate::config::QueryConfig::max_result_rows so the config knob is
load-bearing on the read path (not a hardcoded constant).
Sourcepub fn with_forced_read_path(
self,
forced_read_path: Option<ReadPathMode>,
) -> Self
pub fn with_forced_read_path( self, forced_read_path: Option<ReadPathMode>, ) -> Self
Set the read-path forcing override (issue #1918).
Builder-style: the query engine calls this with
crate::config::QueryConfig::forced_read_path so the config knob is
load-bearing on the read path. Some(mode) takes precedence over the
CQLITE_READ_PATH env var; None leaves routing to the classifier + env.
Sourcepub async fn execute_streaming(
&self,
plan: OptimizedQueryPlan,
config: StreamingConfig,
) -> Result<QueryResultIterator>
pub async fn execute_streaming( &self, plan: OptimizedQueryPlan, config: StreamingConfig, ) -> Result<QueryResultIterator>
Execute an optimized query plan with streaming results (Issue #280)
Instead of materializing all rows in memory, this method returns a
QueryResultIterator that yields rows incrementally via a bounded channel.
This enables memory-efficient processing of large result sets.
§Memory Budget
With default StreamingConfig::buffer_size of 1024 rows and ~1KB avg row size:
- Channel buffer: ~1MB in flight
- Background task: minimal overhead
- Total streaming overhead: ~1-2MB (well within 128MB target)
§Limitations
Currently supports:
- SSTableScan with predicates (streaming)
- Filter/Limit/Project (applied during scan)
LIMIT (and OFFSET, when present in the plan) is enforced by the
streaming producer (execute_streaming_background): it skips OFFSET
matches and stops scanning once count rows have been sent, so a
LIMIT N query yields exactly N rows without materializing the rest
(Issue #581).
For ORDER BY/GROUP BY/DISTINCT, falls back to full execution then streams results.