17
17
18
18
package org .apache .spark .sql .catalyst .expressions
19
19
20
+ import java .sql .{Date , Timestamp }
21
+
20
22
import scala .collection .JavaConverters ._
21
23
import scala .reflect .ClassTag
22
24
@@ -28,9 +30,11 @@ import org.apache.spark.sql.catalyst.analysis.ResolveTimeZone
28
30
import org .apache .spark .sql .catalyst .encoders .ExpressionEncoder
29
31
import org .apache .spark .sql .catalyst .expressions .codegen .GenerateUnsafeProjection
30
32
import org .apache .spark .sql .catalyst .expressions .objects ._
31
- import org .apache .spark .sql .catalyst .util .{ArrayBasedMapData , ArrayData , GenericArrayData }
33
+ import org .apache .spark .sql .catalyst .util ._
34
+ import org .apache .spark .sql .catalyst .util .DateTimeUtils .{SQLDate , SQLTimestamp }
32
35
import org .apache .spark .sql .internal .SQLConf
33
36
import org .apache .spark .sql .types ._
37
+ import org .apache .spark .unsafe .types .UTF8String
34
38
35
39
class InvokeTargetClass extends Serializable {
36
40
def filterInt (e : Any ): Any = e.asInstanceOf [Int ] > 0
@@ -93,6 +97,66 @@ class ObjectExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
93
97
UnsafeProjection ) // TODO(hvanhovell) revert this when SPARK-23587 is fixed
94
98
}
95
99
100
+ test(" SPARK-23582: StaticInvoke should support interpreted execution" ) {
101
+ Seq ((classOf [java.lang.Boolean ], " true" , true ),
102
+ (classOf [java.lang.Byte ], " 1" , 1 .toByte),
103
+ (classOf [java.lang.Short ], " 257" , 257 .toShort),
104
+ (classOf [java.lang.Integer ], " 12345" , 12345 ),
105
+ (classOf [java.lang.Long ], " 12345678" , 12345678 .toLong),
106
+ (classOf [java.lang.Float ], " 12.34" , 12.34 .toFloat),
107
+ (classOf [java.lang.Double ], " 1.2345678" , 1.2345678 )
108
+ ).foreach { case (cls, arg, expected) =>
109
+ checkObjectExprEvaluation(StaticInvoke (cls, ObjectType (cls), " valueOf" ,
110
+ Seq (BoundReference (0 , ObjectType (classOf [java.lang.String ]), true ))),
111
+ expected, InternalRow .fromSeq(Seq (arg)))
112
+ }
113
+
114
+ // Return null when null argument is passed with propagateNull = true
115
+ val stringCls = classOf [java.lang.String ]
116
+ checkObjectExprEvaluation(StaticInvoke (stringCls, ObjectType (stringCls), " valueOf" ,
117
+ Seq (BoundReference (0 , ObjectType (classOf [Object ]), true )), propagateNull = true ),
118
+ null , InternalRow .fromSeq(Seq (null )))
119
+ checkObjectExprEvaluation(StaticInvoke (stringCls, ObjectType (stringCls), " valueOf" ,
120
+ Seq (BoundReference (0 , ObjectType (classOf [Object ]), true )), propagateNull = false ),
121
+ " null" , InternalRow .fromSeq(Seq (null )))
122
+
123
+ // test no argument
124
+ val clCls = classOf [java.lang.ClassLoader ]
125
+ checkObjectExprEvaluation(StaticInvoke (clCls, ObjectType (clCls), " getSystemClassLoader" , Nil ),
126
+ ClassLoader .getSystemClassLoader, InternalRow .empty)
127
+ // test more than one argument
128
+ val intCls = classOf [java.lang.Integer ]
129
+ checkObjectExprEvaluation(StaticInvoke (intCls, ObjectType (intCls), " compare" ,
130
+ Seq (BoundReference (0 , IntegerType , false ), BoundReference (1 , IntegerType , false ))),
131
+ 0 , InternalRow .fromSeq(Seq (7 , 7 )))
132
+
133
+ Seq ((DateTimeUtils .getClass, TimestampType , " fromJavaTimestamp" , ObjectType (classOf [Timestamp ]),
134
+ new Timestamp (77777 ), DateTimeUtils .fromJavaTimestamp(new Timestamp (77777 ))),
135
+ (DateTimeUtils .getClass, DateType , " fromJavaDate" , ObjectType (classOf [Date ]),
136
+ new Date (88888888 ), DateTimeUtils .fromJavaDate(new Date (88888888 ))),
137
+ (classOf [UTF8String ], StringType , " fromString" , ObjectType (classOf [String ]),
138
+ " abc" , UTF8String .fromString(" abc" )),
139
+ (Decimal .getClass, DecimalType (38 , 0 ), " fromDecimal" , ObjectType (classOf [Any ]),
140
+ BigInt (88888888 ), Decimal .fromDecimal(BigInt (88888888 ))),
141
+ (Decimal .getClass, DecimalType .SYSTEM_DEFAULT ,
142
+ " apply" , ObjectType (classOf [java.math.BigInteger ]),
143
+ new java.math.BigInteger (" 88888888" ), Decimal .apply(new java.math.BigInteger (" 88888888" ))),
144
+ (classOf [ArrayData ], ArrayType (IntegerType ), " toArrayData" , ObjectType (classOf [Any ]),
145
+ Array [Int ](1 , 2 , 3 ), ArrayData .toArrayData(Array [Int ](1 , 2 , 3 ))),
146
+ (classOf [UnsafeArrayData ], ArrayType (IntegerType , false ),
147
+ " fromPrimitiveArray" , ObjectType (classOf [Array [Int ]]),
148
+ Array [Int ](1 , 2 , 3 ), UnsafeArrayData .fromPrimitiveArray(Array [Int ](1 , 2 , 3 ))),
149
+ (DateTimeUtils .getClass, ObjectType (classOf [Date ]),
150
+ " toJavaDate" , ObjectType (classOf [SQLDate ]), 77777 , DateTimeUtils .toJavaDate(77777 )),
151
+ (DateTimeUtils .getClass, ObjectType (classOf [Timestamp ]),
152
+ " toJavaTimestamp" , ObjectType (classOf [SQLTimestamp ]),
153
+ 88888888 .toLong, DateTimeUtils .toJavaTimestamp(88888888 ))
154
+ ).foreach { case (cls, dataType, methodName, argType, arg, expected) =>
155
+ checkObjectExprEvaluation(StaticInvoke (cls, dataType, methodName,
156
+ Seq (BoundReference (0 , argType, true ))), expected, InternalRow .fromSeq(Seq (arg)))
157
+ }
158
+ }
159
+
96
160
test(" SPARK-23583: Invoke should support interpreted execution" ) {
97
161
val targetObject = new InvokeTargetClass
98
162
val funcClass = classOf [InvokeTargetClass ]
0 commit comments