Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SPARK-4205][SQL] Timestamp and Date classes which work in the catalyst DSL. #3066

Closed
wants to merge 80 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
495eacd
Adding Timestamp and Date classes which support the standard comparison
culler Nov 3, 2014
0c389a7
Correcting a typo in the documentation.
culler Nov 3, 2014
d6e4c59
Close #2971.
rxin Nov 3, 2014
001acc4
[SPARK-4177][Doc]update build doc since JDBC/CLI support hive 13 now
scwf Nov 3, 2014
76386e1
[SPARK-4163][Core][WebUI] Send the fetch failure message back to Web UI
zsxwing Nov 3, 2014
7c8b2c0
Correcting the bugs and issues pointed out in liancheng's very helpfu…
culler Nov 3, 2014
2aca97c
[EC2] Factor out Mesos spark-ec2 branch
nchammas Nov 3, 2014
3cca196
[SPARK-4148][PySpark] fix seed distribution and add some tests for rd…
mengxr Nov 3, 2014
75690de
Make implicit conversions for Literal op Symbol return a specific type,
culler Nov 3, 2014
df607da
[SPARK-4211][Build] Fixes hive.version in Maven profile hive-0.13.1
coderfi Nov 3, 2014
2b6e1ce
[SPARK-4207][SQL] Query which has syntax like 'not like' is not worki…
ravipesala Nov 3, 2014
24544fb
[SPARK-3594] [PySpark] [SQL] take more rows to infer schema or sampling
davies Nov 3, 2014
c238fb4
[SPARK-4202][SQL] Simple DSL support for Scala UDF
liancheng Nov 3, 2014
e83f13e
[SPARK-4152] [SQL] Avoid data change in CTAS while table already existed
chenghao-intel Nov 3, 2014
25bef7e
[SQL] More aggressive defaults
marmbrus Nov 3, 2014
2812815
SPARK-4178. Hadoop input metrics ignore bytes read in RecordReader in…
sryza Nov 3, 2014
15b58a2
[SQL] Convert arguments to Scala UDFs
marmbrus Nov 4, 2014
97a466e
[SPARK-4168][WebUI] web statges number should show correctly when sta…
liyezhang556520 Nov 4, 2014
4f035dd
[SPARK-611] Display executor thread dumps in web UI
JoshRosen Nov 4, 2014
c5912ec
[FIX][MLLIB] fix seed in BaggedPointSuite
mengxr Nov 4, 2014
04450d1
[SPARK-4192][SQL] Internal API for Python UDT
mengxr Nov 4, 2014
39b8ad1
Reversed random line permutations. Eliminated all getters and setter…
culler Nov 4, 2014
3dd0da9
A couple more pointless changes undone.
culler Nov 4, 2014
1a9c6cd
[SPARK-3573][MLLIB] Make MLlib's Vector compatible with SQL's SchemaRDD
mengxr Nov 4, 2014
9bdc841
[SPARK-4163][Core] Add a backward compatibility test for FetchFailed
zsxwing Nov 4, 2014
b671ce0
[SPARK-4166][Core] Add a backward compatibility test for ExecutorLost…
zsxwing Nov 4, 2014
e4f4263
[SPARK-3886] [PySpark] simplify serializer, use AutoBatchedSerializer…
Nov 4, 2014
bcecd73
fixed MLlib Naive-Bayes java example bug
dkobylarz Nov 4, 2014
f90ad5d
[Spark-4060] [MLlib] exposing special rdd functions to the public
Nov 4, 2014
5e73138
[SPARK-2938] Support SASL authentication in NettyBlockTransferService
aarondav Nov 5, 2014
515abb9
[SQL] Add String option for DSL AS
marmbrus Nov 5, 2014
c8abddc
[SPARK-3964] [MLlib] [PySpark] add Hypothesis test Python API
Nov 5, 2014
5f13759
[SPARK-4029][Streaming] Update streaming driver to reliably save and …
tdas Nov 5, 2014
73d8017
In tests where the scalatest assert conversion collides with the new DSL
culler Nov 5, 2014
a911240
Removed Date and Timestamp from NativeTypes as this would force changes
culler Nov 5, 2014
5b3b6f6
[SPARK-4197] [mllib] GradientBoosting API cleanup and examples in Sca…
jkbradley Nov 5, 2014
3a9e31b
Added tests for the features in this PR. Added Date and Timestamp as
culler Nov 5, 2014
4c42986
[SPARK-4242] [Core] Add SASL to external shuffle service
aarondav Nov 5, 2014
a46497e
[SPARK-3984] [SPARK-3983] Fix incorrect scheduler delay and display t…
kayousterhout Nov 5, 2014
f37817b
SPARK-4222 [CORE] use readFully in FixedLengthBinaryRecordReader
industrial-sloth Nov 5, 2014
61a5cce
[SPARK-3797] Run external shuffle service in Yarn NM
Nov 5, 2014
868cd4c
SPARK-4040. Update documentation to exemplify use of local (n) value,…
Nov 5, 2014
f7ac8c2
SPARK-3223 runAsSparkUser cannot change HDFS write permission properl…
jongyoul Nov 5, 2014
cb0eae3
[SPARK-4158] Fix for missing resources.
brndnmtthws Nov 6, 2014
c315d13
[SPARK-4254] [mllib] MovieLensALS bug fix
jkbradley Nov 6, 2014
3d2b5bc
[SPARK-4262][SQL] add .schemaRDD to JavaSchemaRDD
mengxr Nov 6, 2014
db45f5a
[SPARK-4137] [EC2] Don't change working dir on user
nchammas Nov 6, 2014
5f27ae1
[SPARK-4255] Fix incorrect table striping
kayousterhout Nov 6, 2014
b41a39e
[SPARK-4186] add binaryFiles and binaryRecords in Python
Nov 6, 2014
6e87d72
Removed accidentlay extraneous import from Row.scala.
culler Nov 6, 2014
a5205b5
... and removed another extraneous import.
culler Nov 6, 2014
76a18dc
Tiny style issue.
culler Nov 6, 2014
b6a4374
Cleaning up comments.
culler Nov 6, 2014
0dc0ff0
One last comment clarification.
culler Nov 6, 2014
23eaf0e
[SPARK-4264] Completion iterator should only invoke callback once
aarondav Nov 6, 2014
d15c6e9
[SPARK-4249][GraphX]fix a problem of EdgePartitionBuilder in Graphx
lianhuiwang Nov 6, 2014
0d2e389
Adding a test which appeared after the PR and uses assert(X === Y).
culler Nov 6, 2014
470881b
[HOT FIX] Make distribution fails
Nov 6, 2014
96136f2
[SPARK-3797] Minor addendum to Yarn shuffle service
Nov 7, 2014
6e9ef10
[SPARK-4277] Support external shuffle service on Standalone Worker
aarondav Nov 7, 2014
f165b2b
[SPARK-4188] [Core] Perform network-level retry of shuffle file fetches
aarondav Nov 7, 2014
48a19a6
[SPARK-4236] Cleanup removed applications' files in shuffle service
aarondav Nov 7, 2014
3abdb1b
[SPARK-4204][Core][WebUI] Change Utils.exceptionString to contain the…
zsxwing Nov 7, 2014
c3f9ce1
Removing new test until I rebase the repository.
culler Nov 7, 2014
908fc6a
Adding Timestamp and Date classes which support the standard comparison
culler Nov 3, 2014
dc2ed72
Correcting a typo in the documentation.
culler Nov 3, 2014
b003619
Correcting the bugs and issues pointed out in liancheng's very helpfu…
culler Nov 3, 2014
a006ddb
Make implicit conversions for Literal op Symbol return a specific type,
culler Nov 3, 2014
1935289
Reversed random line permutations. Eliminated all getters and setter…
culler Nov 4, 2014
d59e5d9
A couple more pointless changes undone.
culler Nov 4, 2014
43406fe
In tests where the scalatest assert conversion collides with the new DSL
culler Nov 5, 2014
c304b16
Removed Date and Timestamp from NativeTypes as this would force changes
culler Nov 5, 2014
32df474
Added tests for the features in this PR. Added Date and Timestamp as
culler Nov 5, 2014
d52e6d7
Removed accidentlay extraneous import from Row.scala.
culler Nov 6, 2014
45f9478
... and removed another extraneous import.
culler Nov 6, 2014
f126042
Tiny style issue.
culler Nov 6, 2014
2ec6f6b
Cleaning up comments.
culler Nov 6, 2014
3a14915
One last comment clarification.
culler Nov 6, 2014
d0a27ab
One more test to fix after rebasing.
culler Nov 7, 2014
098bb5d
Rebasing PR to current master.
culler Nov 7, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ object ScalaReflection {
case obj: LongType.JvmType => LongType
case obj: FloatType.JvmType => FloatType
case obj: DoubleType.JvmType => DoubleType
case obj: DateType.JvmType => DateType
case obj: BigDecimal => DecimalType.Unlimited
case obj: Decimal => DecimalType.Unlimited
case obj: DateType.JvmType => DateType
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess you moved this line here because DateType and TimestampType are more tightly related. This is consideration is legitimate and I'd also choose this order if I were the original author. However, this change introduces larger probability of future merge conflicts, while the benefit is rather limited. Same principle applies to all other similar reordering changes related to Date and Timestamp in this PR.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Well, the truth is that I was originally working with the source for Spark 1.1.0. When I pulled the current code it turned out that many lines such as this one had already been added after the release of 1.1.0, so I had to go through and remove many duplicates. In the course of that process it seemed better for me to have some logical scheme to guide me in choosing which of the two duplicates to delete.

case obj: TimestampType.JvmType => TimestampType
case null => NullType
// For other cases, there is no obvious mapping from the type of the given object to a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ package object dsl {
implicit def floatToLiteral(f: Float) = Literal(f)
implicit def doubleToLiteral(d: Double) = Literal(d)
implicit def stringToLiteral(s: String) = Literal(s)
implicit def dateToLiteral(d: Date) = Literal(d)
implicit def bigDecimalToLiteral(d: BigDecimal) = Literal(d)
implicit def decimalToLiteral(d: Decimal) = Literal(d)
implicit def dateToLiteral(d: Date) = Literal(d)
implicit def timestampToLiteral(t: Timestamp) = Literal(t)
implicit def binaryToLiteral(a: Array[Byte]) = Literal(a)

Expand All @@ -146,6 +146,31 @@ package object dsl {
def upper(e: Expression) = Upper(e)
def lower(e: Expression) = Lower(e)

/*
* Conversions to provide the standard operators in the special case
* where a literal is being combined with a symbol. Without these an
* expression such as 0 < 'x is not recognized.
*/
implicit class InitialLiteral(x: Any) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about LhsLiteral (left hand side literal)? Also, converting Any to this class implicitly seems a bit dangerous. I'd prefer this style:

case class LhsLiteral(x: Any) {
  ...
}

// Similar to all the xxToLiteral implicit conversions:
implicit booleanToLhsLiteral(b: Boolean) = new LhsLiteral(b)
implicit byteToLhsLiteral(b: Byte) = new LhsLiteral(b)
...

val literal = Literal(x)
def + (other: Symbol):Expression = {literal + other}
def - (other: Symbol):Expression = {literal - other}
def * (other: Symbol):Expression = {literal * other}
def / (other: Symbol):Expression = {literal / other}
def % (other: Symbol):Expression = {literal % other}

def && (other: Symbol):Expression = {literal && other}
def || (other: Symbol):Expression = {literal || other}

def < (other: Symbol):Expression = {literal < other}
def <= (other: Symbol):Expression = {literal <= other}
def > (other: Symbol):Expression = {literal > other}
def >= (other: Symbol):Expression = {literal >= other}
def === (other: Symbol):Expression = {literal === other}
def <=> (other: Symbol):Expression = {literal <=> other}
def !== (other: Symbol):Expression = {literal !== other}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a space after :, and remove the braces.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

}

implicit class DslSymbol(sym: Symbol) extends ImplicitAttribute { def s = sym.name }
// TODO more implicit class for literal?
implicit class DslString(val s: String) extends ImplicitOperators {
Expand Down Expand Up @@ -182,16 +207,16 @@ package object dsl {
/** Creates a new AttributeReference of type string */
def string = AttributeReference(s, StringType, nullable = true)()

/** Creates a new AttributeReference of type date */
def date = AttributeReference(s, DateType, nullable = true)()

/** Creates a new AttributeReference of type decimal */
def decimal = AttributeReference(s, DecimalType.Unlimited, nullable = true)()

/** Creates a new AttributeReference of type decimal */
def decimal(precision: Int, scale: Int) =
AttributeReference(s, DecimalType(precision, scale), nullable = true)()

/** Creates a new AttributeReference of type date */
def date = AttributeReference(s, DateType, nullable = true)()

/** Creates a new AttributeReference of type timestamp */
def timestamp = AttributeReference(s, TimestampType, nullable = true)()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ case class Cast(child: Expression, dataType: DataType) extends UnaryExpression w

override def nullable = (child.dataType, dataType) match {
case (StringType, _: NumericType) => true
case (StringType, TimestampType) => true
case (StringType, DateType) => true
case (StringType, TimestampType) => true
case (_: NumericType, DateType) => true
case (BooleanType, DateType) => true
case (DateType, _: NumericType) => true
Expand Down Expand Up @@ -333,8 +333,8 @@ case class Cast(child: Expression, dataType: DataType) extends UnaryExpression w
case dt if dt == child.dataType => identity[Any]
case StringType => castToString
case BinaryType => castToBinary
case DateType => castToDate
case decimal: DecimalType => castToDecimal(decimal)
case DateType => castToDate
case TimestampType => castToTimestamp
case BooleanType => castToBoolean
case ByteType => castToByte
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package org.apache.spark.sql.catalyst.expressions

import java.sql.{Date, Timestamp}

/**
* A [[Projection]] that is calculated by calling the `eval` of each of the specified expressions.
Expand Down Expand Up @@ -139,6 +140,12 @@ class JoinedRow extends Row {
def getString(i: Int): String =
if (i < row1.size) row1.getString(i) else row2.getString(i - row1.size)

def getDate(i: Int): Date =
if (i < row1.size) row1.getDate(i) else row2.getDate(i - row1.size)

def getTimestamp(i: Int): Timestamp =
if (i < row1.size) row1.getTimestamp(i) else row2.getTimestamp(i - row1.size)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getters like getDate and getTimestamp are not implemented for a reason, please refer to this PR discussion for details #2284 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And you can always replace these specialized getters with Row.getAs[T].

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I am removing them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for not being clear enough, all getters/setters for Date and Timestamp in all Row classes should be removed, including:

override def getAs[T](i: Int): T =
if (i < row1.size) row1.getAs[T](i) else row2.getAs[T](i - row1.size)

Expand Down Expand Up @@ -231,6 +238,13 @@ class JoinedRow2 extends Row {
def getString(i: Int): String =
if (i < row1.size) row1.getString(i) else row2.getString(i - row1.size)


def getDate(i: Int): Date =
if (i < row1.size) row1.getDate(i) else row2.getDate(i - row1.size)

def getTimestamp(i: Int): Timestamp =
if (i < row1.size) row1.getTimestamp(i) else row2.getTimestamp(i - row1.size)

override def getAs[T](i: Int): T =
if (i < row1.size) row1.getAs[T](i) else row2.getAs[T](i - row1.size)

Expand Down Expand Up @@ -317,6 +331,13 @@ class JoinedRow3 extends Row {
def getString(i: Int): String =
if (i < row1.size) row1.getString(i) else row2.getString(i - row1.size)


def getDate(i: Int): Date =
if (i < row1.size) row1.getDate(i) else row2.getDate(i - row1.size)

def getTimestamp(i: Int): Timestamp =
if (i < row1.size) row1.getTimestamp(i) else row2.getTimestamp(i - row1.size)

override def getAs[T](i: Int): T =
if (i < row1.size) row1.getAs[T](i) else row2.getAs[T](i - row1.size)

Expand Down Expand Up @@ -403,6 +424,13 @@ class JoinedRow4 extends Row {
def getString(i: Int): String =
if (i < row1.size) row1.getString(i) else row2.getString(i - row1.size)


def getDate(i: Int): Date =
if (i < row1.size) row1.getDate(i) else row2.getDate(i - row1.size)

def getTimestamp(i: Int): Timestamp =
if (i < row1.size) row1.getTimestamp(i) else row2.getTimestamp(i - row1.size)

override def getAs[T](i: Int): T =
if (i < row1.size) row1.getAs[T](i) else row2.getAs[T](i - row1.size)

Expand Down Expand Up @@ -489,6 +517,13 @@ class JoinedRow5 extends Row {
def getString(i: Int): String =
if (i < row1.size) row1.getString(i) else row2.getString(i - row1.size)


def getDate(i: Int): Date =
if (i < row1.size) row1.getDate(i) else row2.getDate(i - row1.size)

def getTimestamp(i: Int): Timestamp =
if (i < row1.size) row1.getTimestamp(i) else row2.getTimestamp(i - row1.size)

override def getAs[T](i: Int): T =
if (i < row1.size) row1.getAs[T](i) else row2.getAs[T](i - row1.size)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

package org.apache.spark.sql.catalyst.expressions

import org.apache.spark.sql.catalyst.types.NativeType
import org.apache.spark.sql.catalyst.types._
import java.sql.{Date, Timestamp}
import java.math.BigDecimal

object Row {
/**
Expand All @@ -42,6 +44,31 @@ object Row {
* This method can be used to construct a [[Row]] from a [[Seq]] of values.
*/
def fromSeq(values: Seq[Any]): Row = new GenericRow(values.toArray)

/**
* This method can be used to construct a [[Row]] from a [[Seq]] of Strings,
* converting each item to the type specified in a [[StructType]] schema.
* Only primitive types can be used.
*/
def fromStringsBySchema(strings: Seq[String], schema: StructType): Row = {
val values = for {
(field, str) <- schema.fields zip strings
item = field.dataType match {
case IntegerType => str.toInt
case LongType => str.toLong
case DoubleType => str.toDouble
case FloatType => str.toFloat
case ByteType => str.toByte
case ShortType => str.toShort
case StringType => str
case BooleanType => (str != "")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be rather error prone: string "false" is considered to be true.

case DateType => Date.valueOf(str)
case TimestampType => Timestamp.valueOf(str)
case DecimalType() => new BigDecimal(str)
}
} yield item
new GenericRow(values.toArray)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind to elaborate on the reason why we need this function? Esp. I don't see it's used/tested in this PR.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't need to be a Row method. I will move it outside ( and worry about the Boolean case.)

There is an issue lurking here, however. A SchemaRDD should have Rows which match its schema. But mismatches generate no errors until the last stage, e.g. when one collects the results of a query. My thought was that it would be helpful to have a "safe" Row constructor which would check its data against a schema and raise an error if they do not match (after applying whatever implicit conversions are available. (Yes, this is a separate issue and does not belong here.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I see you point. However, Row is used extremely frequently on many critical paths, so in general we choose to detect type errors while query planning, rather than introduce per row type checking cost here. It's somewhat similar to static typed programming languages like C++: once your program compiles, types are guaranteed to be matched (unless you add nasty type casting tricks intentionally), and you don't need to check types everywhere manually. The query planner is just the compiler here.

}

/**
Expand All @@ -64,6 +91,8 @@ trait Row extends Seq[Any] with Serializable {
def getShort(i: Int): Short
def getByte(i: Int): Byte
def getString(i: Int): String
def getDate(i: Int): Date
def getTimestamp(i: Int): Timestamp
def getAs[T](i: Int): T = apply(i).asInstanceOf[T]

override def toString() =
Expand Down Expand Up @@ -99,6 +128,8 @@ trait MutableRow extends Row {
def setByte(ordinal: Int, value: Byte)
def setFloat(ordinal: Int, value: Float)
def setString(ordinal: Int, value: String)
def setDate(ordinal: Int, value: Date)
def setTimestamp(ordinal: Int, value: Timestamp)
}

/**
Expand All @@ -119,6 +150,9 @@ object EmptyRow extends Row {
def getShort(i: Int): Short = throw new UnsupportedOperationException
def getByte(i: Int): Byte = throw new UnsupportedOperationException
def getString(i: Int): String = throw new UnsupportedOperationException
def getDate(i: Int): Date = throw new UnsupportedOperationException
def getTimestamp(i: Int): Timestamp = throw new UnsupportedOperationException

override def getAs[T](i: Int): T = throw new UnsupportedOperationException

def copy() = this
Expand Down Expand Up @@ -183,6 +217,16 @@ class GenericRow(protected[sql] val values: Array[Any]) extends Row {
values(i).asInstanceOf[String]
}

def getDate(i: Int): Date = {
if (values(i) == null) sys.error("Failed to check null bit for primitive String value.")
values(i).asInstanceOf[Date]
}

def getTimestamp(i: Int): Timestamp = {
if (values(i) == null) sys.error("Failed to check null bit for primitive String value.")
values(i).asInstanceOf[Timestamp]
}

// Custom hashCode function that matches the efficient code generated version.
override def hashCode(): Int = {
var result: Int = 37
Expand Down Expand Up @@ -226,6 +270,8 @@ class GenericMutableRow(size: Int) extends GenericRow(size) with MutableRow {
override def setInt(ordinal: Int, value: Int): Unit = { values(ordinal) = value }
override def setLong(ordinal: Int, value: Long): Unit = { values(ordinal) = value }
override def setString(ordinal: Int, value: String): Unit = { values(ordinal) = value }
override def setDate(ordinal: Int,value: Date): Unit = { values(ordinal) = value }
override def setTimestamp(ordinal: Int,value: Timestamp): Unit = { values(ordinal) = value }

override def setNullAt(i: Int): Unit = { values(i) = null }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.spark.sql.catalyst.expressions

import org.apache.spark.sql.catalyst.types._
import java.sql.{Date, Timestamp}

/**
* A parent class for mutable container objects that are reused when the values are changed,
Expand Down Expand Up @@ -169,6 +170,35 @@ final class MutableByte extends MutableValue {
newCopy.asInstanceOf[this.type]
}
}
final class MutableDate extends MutableValue {
var value: Date = new Date(0)
def boxed = if (isNull) null else value
def update(v: Any) = value = {
isNull = false
v.asInstanceOf[Date]
}
def copy() = {
val newCopy = new MutableDate
newCopy.isNull = isNull
newCopy.value = value
newCopy.asInstanceOf[this.type]
}
}

final class MutableTimestamp extends MutableValue {
var value: Timestamp = new Timestamp(0)
def boxed = if (isNull) null else value
def update(v: Any) = value = {
isNull = false
v.asInstanceOf[Timestamp]
}
def copy() = {
val newCopy = new MutableTimestamp
newCopy.isNull = isNull
newCopy.value = value
newCopy.asInstanceOf[this.type]
}
}

final class MutableAny extends MutableValue {
var value: Any = _
Expand Down Expand Up @@ -307,6 +337,25 @@ final class SpecificMutableRow(val values: Array[MutableValue]) extends MutableR
values(i).asInstanceOf[MutableByte].value
}

override def setDate(ordinal: Int, value: Date): Unit = {
val currentValue = values(ordinal).asInstanceOf[MutableDate]
currentValue.isNull = false
currentValue.value = value
}

override def getDate(i: Int): Date = {
values(i).asInstanceOf[MutableDate].value
}
override def setTimestamp(ordinal: Int, value: Timestamp): Unit = {
val currentValue = values(ordinal).asInstanceOf[MutableTimestamp]
currentValue.isNull = false
currentValue.value = value
}

override def getTimestamp(i: Int): Timestamp = {
values(i).asInstanceOf[MutableTimestamp].value
}

override def getAs[T](i: Int): T = {
values(i).boxed.asInstanceOf[T]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ object Literal {
case b: Boolean => Literal(b, BooleanType)
case d: BigDecimal => Literal(Decimal(d), DecimalType.Unlimited)
case d: Decimal => Literal(d, DecimalType.Unlimited)
case t: Timestamp => Literal(t, TimestampType)
case d: Date => Literal(d, DateType)
case t: Timestamp => Literal(t, TimestampType)
case a: Array[Byte] => Literal(a, BinaryType)
case null => Literal(null, NullType)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ object DataType {
| "LongType" ^^^ LongType
| "BinaryType" ^^^ BinaryType
| "BooleanType" ^^^ BooleanType
| "DateType" ^^^ DateType
| "DecimalType()" ^^^ DecimalType.Unlimited
| fixedDecimalType
| "DateType" ^^^ DateType
| "TimestampType" ^^^ TimestampType
)

Expand Down Expand Up @@ -187,7 +187,8 @@ case object NullType extends DataType

object NativeType {
val all = Seq(
IntegerType, BooleanType, LongType, DoubleType, FloatType, ShortType, ByteType, StringType)
IntegerType, BooleanType, LongType, DoubleType, FloatType, ShortType,
ByteType, StringType, DateType, TimestampType)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original line doesn't exceed 100 columns thus doesn't require a wrap.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but the new line does exceed 100 columns due to the addition of two new items DateType and TimestampType. (Or so the compiler tells me.)

Perhaps there is a reason why these types should not be regarded as "Native" but I could not see any such reason.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, sorry I missed the newly added DateType and TimestampType here. Then would you mind to also add these two in NativeType.defaultSizeOf?


def unapply(dt: DataType): Boolean = all.contains(dt)

Expand Down
Loading