@@ -207,14 +207,23 @@ fn resolve_start_from(
207207 match third_arg {
208208 None => Ok ( vec ! [ 0i64 ; num_rows] ) ,
209209 Some ( ColumnarValue :: Scalar ( ScalarValue :: Int64 ( Some ( v) ) ) ) => {
210- Ok ( vec ! [ v - 1 ; num_rows] )
210+ Ok ( vec ! [ normalize_start_from ( * v ) ? ; num_rows] )
211211 }
212212 Some ( ColumnarValue :: Scalar ( s) ) => {
213213 exec_err ! ( "array_position expected Int64 for start_from, got {s}" )
214214 }
215- Some ( ColumnarValue :: Array ( a) ) => {
216- Ok ( as_int64_array ( a) ?. values ( ) . iter ( ) . map ( |& x| x - 1 ) . collect ( ) )
217- }
215+ Some ( ColumnarValue :: Array ( a) ) => as_int64_array ( a) ?
216+ . values ( )
217+ . iter ( )
218+ . map ( |& x| normalize_start_from ( x) )
219+ . collect ( ) ,
220+ }
221+ }
222+
223+ fn normalize_start_from ( start_from : i64 ) -> Result < i64 > {
224+ match start_from. checked_sub ( 1 ) {
225+ Some ( start_from) => Ok ( start_from) ,
226+ None => exec_err ! ( "start_from out of bounds: {start_from}" ) ,
218227 }
219228}
220229
@@ -309,8 +318,8 @@ fn general_position_dispatch<O: OffsetSizeTrait>(args: &[ArrayRef]) -> Result<Ar
309318 as_int64_array ( & args[ 2 ] ) ?
310319 . values ( )
311320 . iter ( )
312- . map ( |& x| x - 1 )
313- . collect :: < Vec < _ > > ( )
321+ . map ( |& x| normalize_start_from ( x ) )
322+ . collect :: < Result < Vec < _ > > > ( ) ?
314323 } else {
315324 vec ! [ 0 ; haystack. len( ) ]
316325 } ;
@@ -592,9 +601,24 @@ fn array_positions_scalar<O: OffsetSizeTrait>(
592601mod tests {
593602 use super :: * ;
594603 use arrow:: array:: AsArray ;
604+ use arrow:: array:: Int64Array ;
595605 use arrow:: datatypes:: Int32Type ;
596606 use datafusion_common:: config:: ConfigOptions ;
597607
608+ #[ test]
609+ fn test_array_position_start_from_min_value ( ) {
610+ let scalar_arg = ColumnarValue :: Scalar ( ScalarValue :: Int64 ( Some ( i64:: MIN ) ) ) ;
611+ let array_arg = ColumnarValue :: Array ( Arc :: new ( Int64Array :: from ( vec ! [ i64 :: MIN ] ) ) ) ;
612+
613+ for arg in [ scalar_arg, array_arg] {
614+ let err = resolve_start_from ( Some ( & arg) , 1 ) . unwrap_err ( ) . to_string ( ) ;
615+ assert ! (
616+ err. contains( "start_from out of bounds: -9223372036854775808" ) ,
617+ "unexpected error: {err}"
618+ ) ;
619+ }
620+ }
621+
598622 #[ test]
599623 fn test_array_position_sliced_list ( ) -> Result < ( ) > {
600624 // [[10, 20], [30, 40], [50, 60], [70, 80]] → slice(1,2) → [[30, 40], [50, 60]]
0 commit comments