18
18
use std:: any:: Any ;
19
19
use std:: sync:: Arc ;
20
20
21
- use arrow:: array:: { ArrayRef , GenericStringArray , OffsetSizeTrait } ;
21
+ use arrow:: array:: {
22
+ Array , ArrayAccessor , ArrayIter , ArrayRef , AsArray , GenericStringArray ,
23
+ OffsetSizeTrait ,
24
+ } ;
22
25
use arrow:: datatypes:: DataType ;
23
-
24
- use datafusion_common:: cast:: as_generic_string_array;
25
26
use datafusion_common:: { exec_err, Result } ;
26
27
use datafusion_expr:: { ColumnarValue , ScalarUDFImpl , Signature , Volatility } ;
28
+ use DataType :: { LargeUtf8 , Utf8 , Utf8View } ;
27
29
28
30
use crate :: utils:: { make_scalar_function, utf8_to_str_type} ;
29
31
@@ -44,7 +46,7 @@ impl ReverseFunc {
44
46
Self {
45
47
signature : Signature :: uniform (
46
48
1 ,
47
- vec ! [ Utf8 , LargeUtf8 ] ,
49
+ vec ! [ Utf8View , Utf8 , LargeUtf8 ] ,
48
50
Volatility :: Immutable ,
49
51
) ,
50
52
}
@@ -70,8 +72,8 @@ impl ScalarUDFImpl for ReverseFunc {
70
72
71
73
fn invoke ( & self , args : & [ ColumnarValue ] ) -> Result < ColumnarValue > {
72
74
match args[ 0 ] . data_type ( ) {
73
- DataType :: Utf8 => make_scalar_function ( reverse :: < i32 > , vec ! [ ] ) ( args) ,
74
- DataType :: LargeUtf8 => make_scalar_function ( reverse :: < i64 > , vec ! [ ] ) ( args) ,
75
+ Utf8 | Utf8View => make_scalar_function ( reverse :: < i32 > , vec ! [ ] ) ( args) ,
76
+ LargeUtf8 => make_scalar_function ( reverse :: < i64 > , vec ! [ ] ) ( args) ,
75
77
other => {
76
78
exec_err ! ( "Unsupported data type {other:?} for function reverse" )
77
79
}
@@ -83,10 +85,17 @@ impl ScalarUDFImpl for ReverseFunc {
83
85
/// reverse('abcde') = 'edcba'
84
86
/// The implementation uses UTF-8 code points as characters
85
87
pub fn reverse < T : OffsetSizeTrait > ( args : & [ ArrayRef ] ) -> Result < ArrayRef > {
86
- let string_array = as_generic_string_array :: < T > ( & args[ 0 ] ) ?;
88
+ if args[ 0 ] . data_type ( ) == & Utf8View {
89
+ reverse_impl :: < T , _ > ( args[ 0 ] . as_string_view ( ) )
90
+ } else {
91
+ reverse_impl :: < T , _ > ( args[ 0 ] . as_string :: < T > ( ) )
92
+ }
93
+ }
87
94
88
- let result = string_array
89
- . iter ( )
95
+ fn reverse_impl < ' a , T : OffsetSizeTrait , V : ArrayAccessor < Item = & ' a str > > (
96
+ string_array : V ,
97
+ ) -> Result < ArrayRef > {
98
+ let result = ArrayIter :: new ( string_array)
90
99
. map ( |string| string. map ( |string : & str | string. chars ( ) . rev ( ) . collect :: < String > ( ) ) )
91
100
. collect :: < GenericStringArray < T > > ( ) ;
92
101
@@ -95,59 +104,58 @@ pub fn reverse<T: OffsetSizeTrait>(args: &[ArrayRef]) -> Result<ArrayRef> {
95
104
96
105
#[ cfg( test) ]
97
106
mod tests {
98
- use arrow:: array:: { Array , StringArray } ;
99
- use arrow:: datatypes:: DataType :: Utf8 ;
107
+ use arrow:: array:: { Array , LargeStringArray , StringArray } ;
108
+ use arrow:: datatypes:: DataType :: { LargeUtf8 , Utf8 } ;
100
109
101
110
use datafusion_common:: { Result , ScalarValue } ;
102
111
use datafusion_expr:: { ColumnarValue , ScalarUDFImpl } ;
103
112
104
113
use crate :: unicode:: reverse:: ReverseFunc ;
105
114
use crate :: utils:: test:: test_function;
106
115
116
+ macro_rules! test_reverse {
117
+ ( $INPUT: expr, $EXPECTED: expr) => {
118
+ test_function!(
119
+ ReverseFunc :: new( ) ,
120
+ & [ ColumnarValue :: Scalar ( ScalarValue :: Utf8 ( $INPUT) ) ] ,
121
+ $EXPECTED,
122
+ & str ,
123
+ Utf8 ,
124
+ StringArray
125
+ ) ;
126
+
127
+ test_function!(
128
+ ReverseFunc :: new( ) ,
129
+ & [ ColumnarValue :: Scalar ( ScalarValue :: LargeUtf8 ( $INPUT) ) ] ,
130
+ $EXPECTED,
131
+ & str ,
132
+ LargeUtf8 ,
133
+ LargeStringArray
134
+ ) ;
135
+
136
+ test_function!(
137
+ ReverseFunc :: new( ) ,
138
+ & [ ColumnarValue :: Scalar ( ScalarValue :: Utf8View ( $INPUT) ) ] ,
139
+ $EXPECTED,
140
+ & str ,
141
+ Utf8 ,
142
+ StringArray
143
+ ) ;
144
+ } ;
145
+ }
146
+
107
147
#[ test]
108
148
fn test_functions ( ) -> Result < ( ) > {
109
- test_function ! (
110
- ReverseFunc :: new( ) ,
111
- & [ ColumnarValue :: Scalar ( ScalarValue :: from( "abcde" ) ) ] ,
112
- Ok ( Some ( "edcba" ) ) ,
113
- & str ,
114
- Utf8 ,
115
- StringArray
116
- ) ;
117
- test_function ! (
118
- ReverseFunc :: new( ) ,
119
- & [ ColumnarValue :: Scalar ( ScalarValue :: from( "loẅks" ) ) ] ,
120
- Ok ( Some ( "sk̈wol" ) ) ,
121
- & str ,
122
- Utf8 ,
123
- StringArray
124
- ) ;
125
- test_function ! (
126
- ReverseFunc :: new( ) ,
127
- & [ ColumnarValue :: Scalar ( ScalarValue :: from( "loẅks" ) ) ] ,
128
- Ok ( Some ( "sk̈wol" ) ) ,
129
- & str ,
130
- Utf8 ,
131
- StringArray
132
- ) ;
133
- test_function ! (
134
- ReverseFunc :: new( ) ,
135
- & [ ColumnarValue :: Scalar ( ScalarValue :: Utf8 ( None ) ) ] ,
136
- Ok ( None ) ,
137
- & str ,
138
- Utf8 ,
139
- StringArray
140
- ) ;
149
+ test_reverse ! ( Some ( "abcde" . into( ) ) , Ok ( Some ( "edcba" ) ) ) ;
150
+ test_reverse ! ( Some ( "loẅks" . into( ) ) , Ok ( Some ( "sk̈wol" ) ) ) ;
151
+ test_reverse ! ( Some ( "loẅks" . into( ) ) , Ok ( Some ( "sk̈wol" ) ) ) ;
152
+ test_reverse ! ( None , Ok ( None ) ) ;
141
153
#[ cfg( not( feature = "unicode_expressions" ) ) ]
142
- test_function ! (
143
- ReverseFunc :: new( ) ,
144
- & [ ColumnarValue :: Scalar ( ScalarValue :: from( "abcde" ) ) ] ,
154
+ test_reverse ! (
155
+ Some ( "abcde" . into( ) ) ,
145
156
internal_err!(
146
157
"function reverse requires compilation with feature flag: unicode_expressions."
147
158
) ,
148
- & str ,
149
- Utf8 ,
150
- StringArray
151
159
) ;
152
160
153
161
Ok ( ( ) )
0 commit comments