Skip to content

Commit 1d5bad1

Browse files
committed
fix
1 parent 5278349 commit 1d5bad1

File tree

3 files changed

+50
-55
lines changed

3 files changed

+50
-55
lines changed

datafusion/catalog/src/table.rs

Lines changed: 38 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -189,21 +189,18 @@ pub trait TableProvider: Debug + Sync + Send {
189189
/// A [`ScanResult`] containing the [`ExecutionPlan`] for scanning the table
190190
///
191191
/// See [`Self::scan`] for detailed documentation about projection, filters, and limits.
192-
async fn scan_with_args(
192+
async fn scan_with_args<'a>(
193193
&self,
194194
state: &dyn Session,
195-
args: ScanArgs,
195+
args: ScanArgs<'a>,
196196
) -> Result<ScanResult> {
197-
let ScanArgs {
198-
filters,
199-
projection,
200-
limit,
201-
} = args;
202-
let filters = filters.unwrap_or_default();
197+
let filters = args.filters().unwrap_or(&[]);
198+
let projection = args.projection().map(|p| p.to_vec());
199+
let limit = args.limit();
203200
let plan = self
204-
.scan(state, projection.as_ref(), &filters, limit)
201+
.scan(state, projection.as_ref(), filters, limit)
205202
.await?;
206-
Ok(ScanResult::new(plan))
203+
Ok(plan.into())
207204
}
208205

209206
/// Specify if DataFusion should provide filter expressions to the
@@ -335,46 +332,32 @@ pub trait TableProvider: Debug + Sync + Send {
335332
}
336333

337334
/// Arguments for scanning a table with [`TableProvider::scan_with_args`].
338-
///
339-
/// `ScanArgs` provides a structured way to pass scan parameters to table providers,
340-
/// replacing the multiple individual parameters used by [`TableProvider::scan`].
341-
/// This struct uses the builder pattern for convenient construction.
342-
///
343-
/// # Examples
344-
///
345-
/// ```
346-
/// # use datafusion_catalog::ScanArgs;
347-
/// # use datafusion_expr::Expr;
348-
/// let args = ScanArgs::default()
349-
/// .with_projection(Some(vec![0, 2, 4]))
350-
/// .with_limit(Some(1000));
351-
/// ```
352335
#[derive(Debug, Clone, Default)]
353-
pub struct ScanArgs {
354-
filters: Option<Vec<Expr>>,
355-
projection: Option<Vec<usize>>,
336+
pub struct ScanArgs<'a> {
337+
filters: Option<&'a [Expr]>,
338+
projection: Option<&'a [usize]>,
356339
limit: Option<usize>,
357340
}
358341

359-
impl ScanArgs {
342+
impl<'a> ScanArgs<'a> {
360343
/// Set the column projection for the scan.
361344
///
362345
/// The projection is a list of column indices from [`TableProvider::schema`]
363346
/// that should be included in the scan results. If `None`, all columns are included.
364347
///
365348
/// # Arguments
366-
/// * `projection` - Optional list of column indices to project
367-
pub fn with_projection(mut self, projection: Option<Vec<usize>>) -> Self {
349+
/// * `projection` - Optional slice of column indices to project
350+
pub fn with_projection(mut self, projection: Option<&'a [usize]>) -> Self {
368351
self.projection = projection;
369352
self
370353
}
371354

372355
/// Get the column projection for the scan.
373356
///
374-
/// Returns a cloned copy of the projection column indices, or `None` if
357+
/// Returns a reference to the projection column indices, or `None` if
375358
/// no projection was specified (meaning all columns should be included).
376-
pub fn projection(&self) -> Option<Vec<usize>> {
377-
self.projection.clone()
359+
pub fn projection(&self) -> Option<&'a [usize]> {
360+
self.projection
378361
}
379362

380363
/// Set the filter expressions for the scan.
@@ -384,17 +367,17 @@ impl ScanArgs {
384367
/// Whether filters are actually pushed down depends on [`TableProvider::supports_filters_pushdown`].
385368
///
386369
/// # Arguments
387-
/// * `filters` - Optional list of filter expressions
388-
pub fn with_filters(mut self, filters: Option<Vec<Expr>>) -> Self {
370+
/// * `filters` - Optional slice of filter expressions
371+
pub fn with_filters(mut self, filters: Option<&'a [Expr]>) -> Self {
389372
self.filters = filters;
390373
self
391374
}
392375

393376
/// Get the filter expressions for the scan.
394377
///
395378
/// Returns a reference to the filter expressions, or `None` if no filters were specified.
396-
pub fn filters(&self) -> Option<&[Expr]> {
397-
self.filters.as_deref()
379+
pub fn filters(&self) -> Option<&'a [Expr]> {
380+
self.filters
398381
}
399382

400383
/// Set the maximum number of rows to return from the scan.
@@ -418,11 +401,6 @@ impl ScanArgs {
418401
}
419402

420403
/// Result of a table scan operation from [`TableProvider::scan_with_args`].
421-
///
422-
/// `ScanResult` encapsulates the [`ExecutionPlan`] produced by a table scan,
423-
/// providing a typed return value instead of returning the plan directly.
424-
/// This allows for future extensibility of scan results without breaking
425-
/// the API.
426404
#[derive(Debug, Clone)]
427405
pub struct ScanResult {
428406
/// The ExecutionPlan to run.
@@ -438,12 +416,26 @@ impl ScanResult {
438416
Self { plan }
439417
}
440418

441-
/// Get the execution plan for this scan result.
419+
/// Get a reference to the execution plan for this scan result.
442420
///
443-
/// Returns a cloned reference to the [`ExecutionPlan`] that will perform
421+
/// Returns a reference to the [`ExecutionPlan`] that will perform
444422
/// the actual table scanning and data retrieval.
445-
pub fn plan(&self) -> Arc<dyn ExecutionPlan> {
446-
Arc::clone(&self.plan)
423+
pub fn plan(&self) -> &Arc<dyn ExecutionPlan> {
424+
&self.plan
425+
}
426+
427+
/// Consume this ScanResult and return the execution plan.
428+
///
429+
/// Returns the owned [`ExecutionPlan`] that will perform
430+
/// the actual table scanning and data retrieval.
431+
pub fn into_inner(self) -> Arc<dyn ExecutionPlan> {
432+
self.plan
433+
}
434+
}
435+
436+
impl From<Arc<dyn ExecutionPlan>> for ScanResult {
437+
fn from(plan: Arc<dyn ExecutionPlan>) -> Self {
438+
Self::new(plan)
447439
}
448440
}
449441

datafusion/core/src/datasource/listing/table.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,18 +1170,20 @@ impl TableProvider for ListingTable {
11701170
limit: Option<usize>,
11711171
) -> Result<Arc<dyn ExecutionPlan>> {
11721172
let options = ScanArgs::default()
1173-
.with_projection(projection.cloned())
1174-
.with_filters(Some(filters.to_vec()))
1173+
.with_projection(projection.map(|p| p.as_slice()))
1174+
.with_filters(Some(filters))
11751175
.with_limit(limit);
1176-
Ok(self.scan_with_args(state, options).await?.plan())
1176+
Ok(Arc::clone(
1177+
self.scan_with_args(state, options).await?.plan(),
1178+
))
11771179
}
11781180

1179-
async fn scan_with_args(
1181+
async fn scan_with_args<'a>(
11801182
&self,
11811183
state: &dyn Session,
1182-
args: ScanArgs,
1184+
args: ScanArgs<'a>,
11831185
) -> Result<ScanResult> {
1184-
let projection = args.projection();
1186+
let projection = args.projection().map(|p| p.to_vec());
11851187
let filters = args.filters().map(|f| f.to_vec()).unwrap_or_default();
11861188
let limit = args.limit();
11871189

datafusion/core/src/physical_planner.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -460,12 +460,13 @@ impl DefaultPhysicalPlanner {
460460
// doesn't know (nor should care) how the relation was
461461
// referred to in the query
462462
let filters = unnormalize_cols(filters.iter().cloned());
463+
let filters_vec = filters.into_iter().collect::<Vec<_>>();
463464
let opts = ScanArgs::default()
464-
.with_projection(projection.clone())
465-
.with_filters(Some(filters))
465+
.with_projection(projection.as_deref())
466+
.with_filters(Some(&filters_vec))
466467
.with_limit(*fetch);
467468
let res = source.scan_with_args(session_state, opts).await?;
468-
res.plan()
469+
Arc::clone(res.plan())
469470
}
470471
LogicalPlan::Values(Values { values, schema }) => {
471472
let exec_schema = schema.as_ref().to_owned().into();

0 commit comments

Comments
 (0)