@@ -37,6 +37,19 @@ object CatalystTypeConverters {
37
37
// Since the map values can be mutable, we explicitly import scala.collection.Map at here.
38
38
import scala .collection .Map
39
39
40
+ private def isPrimitive (dataType : DataType ): Boolean = {
41
+ dataType match {
42
+ case BooleanType => true
43
+ case ByteType => true
44
+ case ShortType => true
45
+ case IntegerType => true
46
+ case LongType => true
47
+ case FloatType => true
48
+ case DoubleType => true
49
+ case _ => false
50
+ }
51
+ }
52
+
40
53
private def getConverterForType (dataType : DataType ): CatalystTypeConverter [Any , Any , Any ] = {
41
54
val converter = dataType match {
42
55
case udt : UserDefinedType [_] => UDTConverter (udt)
@@ -73,15 +86,17 @@ object CatalystTypeConverters {
73
86
* and Options.
74
87
*/
75
88
final def toCatalyst (@ Nullable maybeScalaValue : Any ): CatalystType = {
76
- maybeScalaValue match {
77
- case opt : Option [ScalaInputType ] =>
78
- if (opt.isDefined) {
79
- toCatalystImpl(opt.get)
80
- } else {
81
- null .asInstanceOf [CatalystType ]
82
- }
83
- case null => null .asInstanceOf [CatalystType ]
84
- case scalaValue : ScalaInputType => toCatalystImpl(scalaValue)
89
+ if (maybeScalaValue == null ) {
90
+ null .asInstanceOf [CatalystType ]
91
+ } else if (maybeScalaValue.isInstanceOf [Option [ScalaInputType ]]) {
92
+ val opt = maybeScalaValue.asInstanceOf [Option [ScalaInputType ]]
93
+ if (opt.isDefined) {
94
+ toCatalystImpl(opt.get)
95
+ } else {
96
+ null .asInstanceOf [CatalystType ]
97
+ }
98
+ } else {
99
+ toCatalystImpl(maybeScalaValue.asInstanceOf [ScalaInputType ])
85
100
}
86
101
}
87
102
@@ -272,46 +287,37 @@ object CatalystTypeConverters {
272
287
}
273
288
}
274
289
275
- private object BooleanConverter extends CatalystTypeConverter [Boolean , Any , Any ] {
290
+ private abstract class PrimitiveConverter [T ] extends CatalystTypeConverter [T , Any , Any ] {
291
+ final override def toScala (catalystValue : Any ): Any = catalystValue
292
+ final override def toCatalystImpl (scalaValue : T ): Any = scalaValue
293
+ }
294
+
295
+ private object BooleanConverter extends PrimitiveConverter [Boolean ] {
276
296
override def toScalaImpl (row : Row , column : Int ): Boolean = row.getBoolean(column)
277
- override def toScala (catalystValue : Any ): Any = catalystValue
278
- override def toCatalystImpl (scalaValue : Boolean ): Boolean = scalaValue
279
297
}
280
298
281
- private object ByteConverter extends CatalystTypeConverter [Byte , Any , Any ] {
299
+ private object ByteConverter extends PrimitiveConverter [Byte ] {
282
300
override def toScalaImpl (row : Row , column : Int ): Byte = row.getByte(column)
283
- override def toScala (catalystValue : Any ): Any = catalystValue
284
- override def toCatalystImpl (scalaValue : Byte ): Byte = scalaValue
285
301
}
286
302
287
- private object ShortConverter extends CatalystTypeConverter [Short , Any , Any ] {
303
+ private object ShortConverter extends PrimitiveConverter [Short ] {
288
304
override def toScalaImpl (row : Row , column : Int ): Short = row.getShort(column)
289
- override def toScala (catalystValue : Any ): Any = catalystValue
290
- override def toCatalystImpl (scalaValue : Short ): Short = scalaValue
291
305
}
292
306
293
- private object IntConverter extends CatalystTypeConverter [Int , Any , Any ] {
307
+ private object IntConverter extends PrimitiveConverter [Int ] {
294
308
override def toScalaImpl (row : Row , column : Int ): Int = row.getInt(column)
295
- override def toScala (catalystValue : Any ): Any = catalystValue
296
- override def toCatalystImpl (scalaValue : Int ): Int = scalaValue
297
309
}
298
310
299
- private object LongConverter extends CatalystTypeConverter [Long , Any , Any ] {
311
+ private object LongConverter extends PrimitiveConverter [Long ] {
300
312
override def toScalaImpl (row : Row , column : Int ): Long = row.getLong(column)
301
- override def toScala (catalystValue : Any ): Any = catalystValue
302
- override def toCatalystImpl (scalaValue : Long ): Long = scalaValue
303
313
}
304
314
305
- private object FloatConverter extends CatalystTypeConverter [Float , Any , Any ] {
315
+ private object FloatConverter extends PrimitiveConverter [Float ] {
306
316
override def toScalaImpl (row : Row , column : Int ): Float = row.getFloat(column)
307
- override def toScala (catalystValue : Any ): Any = catalystValue
308
- override def toCatalystImpl (scalaValue : Float ): Float = scalaValue
309
317
}
310
318
311
- private object DoubleConverter extends CatalystTypeConverter [Double , Any , Any ] {
319
+ private object DoubleConverter extends PrimitiveConverter [Double ] {
312
320
override def toScalaImpl (row : Row , column : Int ): Double = row.getDouble(column)
313
- override def toScala (catalystValue : Any ): Any = catalystValue
314
- override def toCatalystImpl (scalaValue : Double ): Double = scalaValue
315
321
}
316
322
317
323
/**
@@ -330,7 +336,25 @@ object CatalystTypeConverters {
330
336
* call this function once to get a converter, and apply it to every row.
331
337
*/
332
338
private [sql] def createToCatalystConverter (dataType : DataType ): Any => Any = {
333
- getConverterForType(dataType).toCatalyst
339
+ if (isPrimitive(dataType)) {
340
+ // Although the `else` branch here is capable of handling inbound conversion of primitives,
341
+ // we add some special-case handling for those types here. The motivation for this relates to
342
+ // Java method invocation costs: if we have rows that consist entirely of primitive columns,
343
+ // then returning the same conversion function for all of the columns means that the call site
344
+ // will be monomorphic instead of polymorphic. In microbenchmarks, this actually resulted in
345
+ // a measurable performance impact. Note that this optimization will be unnecessary if we
346
+ // use code generation to construct Scala Row -> Catalyst Row converters.
347
+ def convert (maybeScalaValue : Any ): Any = {
348
+ if (maybeScalaValue.isInstanceOf [Option [Any ]]) {
349
+ maybeScalaValue.asInstanceOf [Option [Any ]].orNull
350
+ } else {
351
+ maybeScalaValue
352
+ }
353
+ }
354
+ convert
355
+ } else {
356
+ getConverterForType(dataType).toCatalyst
357
+ }
334
358
}
335
359
336
360
/**
0 commit comments