org.apache.spark.sql.catalyst.expressions.SpecificMutableRow.scala Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.spark.sql.catalyst.expressions
import org.apache.spark.sql.catalyst.InternalRow
import org.apache.spark.sql.types._
import org.apache.spark.unsafe.types.UTF8String
/**
* A parent class for mutable container objects that are reused when the values are changed,
* resulting in less garbage. These values are held by a [[SpecificMutableRow]].
*
* The following code was roughly used to generate these objects:
* {{{
* val types = "Int,Float,Boolean,Double,Short,Long,Byte,Any".split(",")
* types.map {tpe =>
* s"""
* final class Mutable$tpe extends MutableValue {
* var value: $tpe = 0
* def boxed = if (isNull) null else value
* def update(v: Any) = value = {
* isNull = false
* v.asInstanceOf[$tpe]
* }
* def copy() = {
* val newCopy = new Mutable$tpe
* newCopy.isNull = isNull
* newCopy.value = value
* newCopy
* }
* }"""
* }.foreach(println)
*
* types.map { tpe =>
* s"""
* override def set$tpe(ordinal: Int, value: $tpe): Unit = {
* val currentValue = values(ordinal).asInstanceOf[Mutable$tpe]
* currentValue.isNull = false
* currentValue.value = value
* }
*
* override def get$tpe(i: Int): $tpe = {
* values(i).asInstanceOf[Mutable$tpe].value
* }"""
* }.foreach(println)
* }}}
*/
abstract class MutableValue extends Serializable {
var isNull: Boolean = true
def boxed: Any
def update(v: Any)
def copy(): MutableValue
}
final class MutableInt extends MutableValue {
var value: Int = 0
override def boxed: Any = if (isNull) null else value
override def update(v: Any): Unit = {
isNull = false
value = v.asInstanceOf[Int]
}
override def copy(): MutableInt = {
val newCopy = new MutableInt
newCopy.isNull = isNull
newCopy.value = value
newCopy
}
}
final class MutableFloat extends MutableValue {
var value: Float = 0
override def boxed: Any = if (isNull) null else value
override def update(v: Any): Unit = {
isNull = false
value = v.asInstanceOf[Float]
}
override def copy(): MutableFloat = {
val newCopy = new MutableFloat
newCopy.isNull = isNull
newCopy.value = value
newCopy
}
}
final class MutableBoolean extends MutableValue {
var value: Boolean = false
override def boxed: Any = if (isNull) null else value
override def update(v: Any): Unit = {
isNull = false
value = v.asInstanceOf[Boolean]
}
override def copy(): MutableBoolean = {
val newCopy = new MutableBoolean
newCopy.isNull = isNull
newCopy.value = value
newCopy
}
}
final class MutableDouble extends MutableValue {
var value: Double = 0
override def boxed: Any = if (isNull) null else value
override def update(v: Any): Unit = {
isNull = false
value = v.asInstanceOf[Double]
}
override def copy(): MutableDouble = {
val newCopy = new MutableDouble
newCopy.isNull = isNull
newCopy.value = value
newCopy
}
}
final class MutableShort extends MutableValue {
var value: Short = 0
override def boxed: Any = if (isNull) null else value
override def update(v: Any): Unit = value = {
isNull = false
v.asInstanceOf[Short]
}
override def copy(): MutableShort = {
val newCopy = new MutableShort
newCopy.isNull = isNull
newCopy.value = value
newCopy
}
}
final class MutableLong extends MutableValue {
var value: Long = 0
override def boxed: Any = if (isNull) null else value
override def update(v: Any): Unit = value = {
isNull = false
v.asInstanceOf[Long]
}
override def copy(): MutableLong = {
val newCopy = new MutableLong
newCopy.isNull = isNull
newCopy.value = value
newCopy
}
}
final class MutableByte extends MutableValue {
var value: Byte = 0
override def boxed: Any = if (isNull) null else value
override def update(v: Any): Unit = value = {
isNull = false
v.asInstanceOf[Byte]
}
override def copy(): MutableByte = {
val newCopy = new MutableByte
newCopy.isNull = isNull
newCopy.value = value
newCopy
}
}
final class MutableAny extends MutableValue {
var value: Any = _
override def boxed: Any = if (isNull) null else value
override def update(v: Any): Unit = {
isNull = false
value = v.asInstanceOf[Any]
}
override def copy(): MutableAny = {
val newCopy = new MutableAny
newCopy.isNull = isNull
newCopy.value = value
newCopy
}
}
/**
* A row type that holds an array specialized container objects, of type [[MutableValue]], chosen
* based on the dataTypes of each column. The intent is to decrease garbage when modifying the
* values of primitive columns.
*/
class SpecificMutableRow(val values: Array[MutableValue])
extends MutableRow with BaseGenericInternalRow {
def this(dataTypes: Seq[DataType]) =
this(
dataTypes.map {
case BooleanType => new MutableBoolean
case ByteType => new MutableByte
case ShortType => new MutableShort
// We use INT for DATE internally
case IntegerType | DateType => new MutableInt
// We use Long for Timestamp internally
case LongType | TimestampType => new MutableLong
case FloatType => new MutableFloat
case DoubleType => new MutableDouble
case _ => new MutableAny
}.toArray)
def this() = this(Seq.empty)
override final def numFields: Int = values.length
override final def setNullAt(i: Int): Unit = {
values(i).isNull = true
}
override final def isNullAt(i: Int): Boolean = values(i).isNull
override final def copy(): InternalRow = {
val newValues = new Array[Any](values.length)
var i = 0
while (i < values.length) {
newValues(i) = values(i).boxed
i += 1
}
new GenericInternalRow(newValues)
}
override final protected def genericGet(i: Int): Any = values(i).boxed
override final def update(ordinal: Int, value: Any) {
if (value == null) {
setNullAt(ordinal)
} else {
values(ordinal).update(value)
}
}
override final def setInt(ordinal: Int, value: Int): Unit = {
val currentValue = values(ordinal).asInstanceOf[MutableInt]
currentValue.isNull = false
currentValue.value = value
}
override final def getInt(i: Int): Int = {
values(i).asInstanceOf[MutableInt].value
}
override final def setFloat(ordinal: Int, value: Float): Unit = {
val currentValue = values(ordinal).asInstanceOf[MutableFloat]
currentValue.isNull = false
currentValue.value = value
}
override final def getFloat(i: Int): Float = {
values(i).asInstanceOf[MutableFloat].value
}
override final def setBoolean(ordinal: Int, value: Boolean): Unit = {
val currentValue = values(ordinal).asInstanceOf[MutableBoolean]
currentValue.isNull = false
currentValue.value = value
}
override final def getBoolean(i: Int): Boolean = {
values(i).asInstanceOf[MutableBoolean].value
}
override final def setDouble(ordinal: Int, value: Double): Unit = {
val currentValue = values(ordinal).asInstanceOf[MutableDouble]
currentValue.isNull = false
currentValue.value = value
}
override final def getDouble(i: Int): Double = {
values(i).asInstanceOf[MutableDouble].value
}
override final def setShort(ordinal: Int, value: Short): Unit = {
val currentValue = values(ordinal).asInstanceOf[MutableShort]
currentValue.isNull = false
currentValue.value = value
}
override final def getShort(i: Int): Short = {
values(i).asInstanceOf[MutableShort].value
}
override final def setLong(ordinal: Int, value: Long): Unit = {
val currentValue = values(ordinal).asInstanceOf[MutableLong]
currentValue.isNull = false
currentValue.value = value
}
override final def getLong(i: Int): Long = {
values(i).asInstanceOf[MutableLong].value
}
override final def setByte(ordinal: Int, value: Byte): Unit = {
val currentValue = values(ordinal).asInstanceOf[MutableByte]
currentValue.isNull = false
currentValue.value = value
}
override final def getByte(i: Int): Byte = {
values(i).asInstanceOf[MutableByte].value
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy