@@ -171,6 +171,37 @@ pub trait TableProvider: Debug + Sync + Send {
171
171
limit : Option < usize > ,
172
172
) -> Result < Arc < dyn ExecutionPlan > > ;
173
173
174
+ /// Create an [`ExecutionPlan`] for scanning the table using structured arguments.
175
+ ///
176
+ /// This method uses [`ScanArgs`] to pass scan parameters in a structured way
177
+ /// and returns a [`ScanResult`] containing the execution plan.
178
+ ///
179
+ /// Table providers can override this method to take advantage of additional
180
+ /// parameters like the upcoming `preferred_ordering` that may not be available through
181
+ /// other scan methods.
182
+ ///
183
+ /// # Arguments
184
+ /// * `state` - The session state containing configuration and context
185
+ /// * `args` - Structured scan arguments including projection, filters, limit, and ordering preferences
186
+ ///
187
+ /// # Returns
188
+ /// A [`ScanResult`] containing the [`ExecutionPlan`] for scanning the table
189
+ ///
190
+ /// See [`Self::scan`] for detailed documentation about projection, filters, and limits.
191
+ async fn scan_with_args < ' a > (
192
+ & self ,
193
+ state : & dyn Session ,
194
+ args : ScanArgs < ' a > ,
195
+ ) -> Result < ScanResult > {
196
+ let filters = args. filters ( ) . unwrap_or ( & [ ] ) ;
197
+ let projection = args. projection ( ) . map ( |p| p. to_vec ( ) ) ;
198
+ let limit = args. limit ( ) ;
199
+ let plan = self
200
+ . scan ( state, projection. as_ref ( ) , filters, limit)
201
+ . await ?;
202
+ Ok ( plan. into ( ) )
203
+ }
204
+
174
205
/// Specify if DataFusion should provide filter expressions to the
175
206
/// TableProvider to apply *during* the scan.
176
207
///
@@ -299,6 +330,114 @@ pub trait TableProvider: Debug + Sync + Send {
299
330
}
300
331
}
301
332
333
+ /// Arguments for scanning a table with [`TableProvider::scan_with_args`].
334
+ #[ derive( Debug , Clone , Default ) ]
335
+ pub struct ScanArgs < ' a > {
336
+ filters : Option < & ' a [ Expr ] > ,
337
+ projection : Option < & ' a [ usize ] > ,
338
+ limit : Option < usize > ,
339
+ }
340
+
341
+ impl < ' a > ScanArgs < ' a > {
342
+ /// Set the column projection for the scan.
343
+ ///
344
+ /// The projection is a list of column indices from [`TableProvider::schema`]
345
+ /// that should be included in the scan results. If `None`, all columns are included.
346
+ ///
347
+ /// # Arguments
348
+ /// * `projection` - Optional slice of column indices to project
349
+ pub fn with_projection ( mut self , projection : Option < & ' a [ usize ] > ) -> Self {
350
+ self . projection = projection;
351
+ self
352
+ }
353
+
354
+ /// Get the column projection for the scan.
355
+ ///
356
+ /// Returns a reference to the projection column indices, or `None` if
357
+ /// no projection was specified (meaning all columns should be included).
358
+ pub fn projection ( & self ) -> Option < & ' a [ usize ] > {
359
+ self . projection
360
+ }
361
+
362
+ /// Set the filter expressions for the scan.
363
+ ///
364
+ /// Filters are boolean expressions that should be evaluated during the scan
365
+ /// to reduce the number of rows returned. All expressions are combined with AND logic.
366
+ /// Whether filters are actually pushed down depends on [`TableProvider::supports_filters_pushdown`].
367
+ ///
368
+ /// # Arguments
369
+ /// * `filters` - Optional slice of filter expressions
370
+ pub fn with_filters ( mut self , filters : Option < & ' a [ Expr ] > ) -> Self {
371
+ self . filters = filters;
372
+ self
373
+ }
374
+
375
+ /// Get the filter expressions for the scan.
376
+ ///
377
+ /// Returns a reference to the filter expressions, or `None` if no filters were specified.
378
+ pub fn filters ( & self ) -> Option < & ' a [ Expr ] > {
379
+ self . filters
380
+ }
381
+
382
+ /// Set the maximum number of rows to return from the scan.
383
+ ///
384
+ /// If specified, the scan should return at most this many rows. This is typically
385
+ /// used to optimize queries with `LIMIT` clauses.
386
+ ///
387
+ /// # Arguments
388
+ /// * `limit` - Optional maximum number of rows to return
389
+ pub fn with_limit ( mut self , limit : Option < usize > ) -> Self {
390
+ self . limit = limit;
391
+ self
392
+ }
393
+
394
+ /// Get the maximum number of rows to return from the scan.
395
+ ///
396
+ /// Returns the row limit, or `None` if no limit was specified.
397
+ pub fn limit ( & self ) -> Option < usize > {
398
+ self . limit
399
+ }
400
+ }
401
+
402
+ /// Result of a table scan operation from [`TableProvider::scan_with_args`].
403
+ #[ derive( Debug , Clone ) ]
404
+ pub struct ScanResult {
405
+ /// The ExecutionPlan to run.
406
+ plan : Arc < dyn ExecutionPlan > ,
407
+ }
408
+
409
+ impl ScanResult {
410
+ /// Create a new `ScanResult` with the given execution plan.
411
+ ///
412
+ /// # Arguments
413
+ /// * `plan` - The execution plan that will perform the table scan
414
+ pub fn new ( plan : Arc < dyn ExecutionPlan > ) -> Self {
415
+ Self { plan }
416
+ }
417
+
418
+ /// Get a reference to the execution plan for this scan result.
419
+ ///
420
+ /// Returns a reference to the [`ExecutionPlan`] that will perform
421
+ /// the actual table scanning and data retrieval.
422
+ pub fn plan ( & self ) -> & Arc < dyn ExecutionPlan > {
423
+ & self . plan
424
+ }
425
+
426
+ /// Consume this ScanResult and return the execution plan.
427
+ ///
428
+ /// Returns the owned [`ExecutionPlan`] that will perform
429
+ /// the actual table scanning and data retrieval.
430
+ pub fn into_inner ( self ) -> Arc < dyn ExecutionPlan > {
431
+ self . plan
432
+ }
433
+ }
434
+
435
+ impl From < Arc < dyn ExecutionPlan > > for ScanResult {
436
+ fn from ( plan : Arc < dyn ExecutionPlan > ) -> Self {
437
+ Self :: new ( plan)
438
+ }
439
+ }
440
+
302
441
/// A factory which creates [`TableProvider`]s at runtime given a URL.
303
442
///
304
443
/// For example, this can be used to create a table "on the fly"
0 commit comments