diff --git a/vortex-layout/src/scan/scan_builder.rs b/vortex-layout/src/scan/scan_builder.rs index 11fd5c7b882..7af7207a849 100644 --- a/vortex-layout/src/scan/scan_builder.rs +++ b/vortex-layout/src/scan/scan_builder.rs @@ -82,6 +82,8 @@ pub struct ScanBuilder { /// The row-offset assigned to the first row of the file. Used by the `row_idx` expression, /// but not by the scan [`Selection`] which remains relative. row_offset: u64, + /// Whether projection and filter expressions should be optimized during prepare. + optimize_expressions: bool, } impl ScanBuilder { @@ -104,6 +106,7 @@ impl ScanBuilder { file_stats: None, limit: None, row_offset: 0, + optimize_expressions: true, } } @@ -149,6 +152,13 @@ impl ScanBuilder { self } + /// Configure whether projection and filter expressions are optimized during + /// [`prepare`](Self::prepare). + pub fn with_expression_optimization(mut self, enabled: bool) -> Self { + self.optimize_expressions = enabled; + self + } + /// Returns whether output chunks are yielded in file order. pub fn ordered(&self) -> bool { self.ordered @@ -257,6 +267,7 @@ impl ScanBuilder { file_stats: self.file_stats, limit: self.limit, row_offset: self.row_offset, + optimize_expressions: self.optimize_expressions, map_fn: Arc::new(move |a| old_map_fn(a).and_then(&map_fn)), } } @@ -283,12 +294,19 @@ impl ScanBuilder { )); // Normalize and simplify the expressions. - let projection = self.projection.optimize_recursive(layout_reader.dtype())?; - - let filter = self - .filter - .map(|f| f.optimize_recursive(layout_reader.dtype())) - .transpose()?; + let projection = if self.optimize_expressions { + self.projection.optimize_recursive(layout_reader.dtype())? + } else { + self.projection + }; + + let filter = if self.optimize_expressions { + self.filter + .map(|f| f.optimize_recursive(layout_reader.dtype())) + .transpose()? + } else { + self.filter + }; // Construct field masks and compute the row splits of the scan. let field_mask =