@@ -83,13 +83,12 @@ use std::{
8383 any:: Any ,
8484 fmt:: { self , Debug , Formatter } ,
8585 hash:: { Hash , Hasher } ,
86- ops:: { Add , Div , Mul , Sub } ,
8786 pin:: Pin ,
88- str:: FromStr ,
8987 sync:: Arc ,
9088 task:: { Context , Poll } ,
9189} ;
9290
91+ use arrow:: datatypes:: { Float64Type , Int64Type } ;
9392use arrow:: {
9493 array:: { ArrayRef , Int32Array , RecordBatch , StringArray , UInt32Array } ,
9594 compute,
@@ -102,6 +101,7 @@ use futures::{
102101use rand:: { Rng , SeedableRng , rngs:: StdRng } ;
103102use tonic:: async_trait;
104103
104+ use datafusion:: optimizer:: simplify_expressions:: simplify_literal:: parse_literal;
105105use datafusion:: {
106106 execution:: {
107107 RecordBatchStream , SendableRecordBatchStream , SessionState , SessionStateBuilder ,
@@ -410,11 +410,12 @@ impl RelationPlanner for TableSamplePlanner {
410410 "TABLESAMPLE requires a quantity (percentage, fraction, or row count)"
411411 ) ;
412412 } ;
413+ let quantity_value_expr = context. sql_to_expr ( quantity. value , input. schema ( ) ) ?;
413414
414415 match quantity. unit {
415416 // TABLESAMPLE (N ROWS) - exact row limit
416417 Some ( TableSampleUnit :: Rows ) => {
417- let rows = parse_quantity :: < i64 > ( & quantity . value ) ?;
418+ let rows: i64 = parse_literal :: < Int64Type > ( & quantity_value_expr ) ?;
418419 if rows < 0 {
419420 return plan_err ! ( "row count must be non-negative, got {}" , rows) ;
420421 }
@@ -426,15 +427,15 @@ impl RelationPlanner for TableSamplePlanner {
426427
427428 // TABLESAMPLE (N PERCENT) - percentage sampling
428429 Some ( TableSampleUnit :: Percent ) => {
429- let percent = parse_quantity :: < f64 > ( & quantity . value ) ?;
430+ let percent: f64 = parse_literal :: < Float64Type > ( & quantity_value_expr ) ?;
430431 let fraction = percent / 100.0 ;
431432 let plan = TableSamplePlanNode :: new ( input, fraction, seed) . into_plan ( ) ;
432433 Ok ( RelationPlanning :: Planned ( PlannedRelation :: new ( plan, alias) ) )
433434 }
434435
435436 // TABLESAMPLE (N) - fraction if <1.0, row limit if >=1.0
436437 None => {
437- let value = parse_quantity :: < f64 > ( & quantity . value ) ?;
438+ let value = parse_literal :: < Float64Type > ( & quantity_value_expr ) ?;
438439 if value < 0.0 {
439440 return plan_err ! ( "sample value must be non-negative, got {}" , value) ;
440441 }
@@ -453,40 +454,6 @@ impl RelationPlanner for TableSamplePlanner {
453454 }
454455}
455456
456- /// Parse a SQL expression as a numeric value (supports basic arithmetic).
457- fn parse_quantity < T > ( expr : & ast:: Expr ) -> Result < T >
458- where
459- T : FromStr + Add < Output = T > + Sub < Output = T > + Mul < Output = T > + Div < Output = T > ,
460- {
461- eval_numeric_expr ( expr)
462- . ok_or_else ( || plan_datafusion_err ! ( "invalid numeric expression: {:?}" , expr) )
463- }
464-
465- /// Recursively evaluate numeric SQL expressions.
466- fn eval_numeric_expr < T > ( expr : & ast:: Expr ) -> Option < T >
467- where
468- T : FromStr + Add < Output = T > + Sub < Output = T > + Mul < Output = T > + Div < Output = T > ,
469- {
470- match expr {
471- ast:: Expr :: Value ( v) => match & v. value {
472- ast:: Value :: Number ( n, _) => n. to_string ( ) . parse ( ) . ok ( ) ,
473- _ => None ,
474- } ,
475- ast:: Expr :: BinaryOp { left, op, right } => {
476- let l = eval_numeric_expr :: < T > ( left) ?;
477- let r = eval_numeric_expr :: < T > ( right) ?;
478- match op {
479- ast:: BinaryOperator :: Plus => Some ( l + r) ,
480- ast:: BinaryOperator :: Minus => Some ( l - r) ,
481- ast:: BinaryOperator :: Multiply => Some ( l * r) ,
482- ast:: BinaryOperator :: Divide => Some ( l / r) ,
483- _ => None ,
484- }
485- }
486- _ => None ,
487- }
488- }
489-
490457/// Custom logical plan node representing a TABLESAMPLE operation.
491458///
492459/// Stores sampling parameters (bounds, seed) and wraps the input plan.
0 commit comments