Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
b75a80f
Add Millennium
MaxGekk Sep 29, 2019
b233c90
Add Century
MaxGekk Sep 29, 2019
6f017a6
Add Decade
MaxGekk Sep 29, 2019
ac1c3a8
Add Year
MaxGekk Sep 29, 2019
7265508
Add Quarter
MaxGekk Sep 29, 2019
554df71
Move MONTHS_PER_QUARTER up
MaxGekk Sep 29, 2019
d0f89f4
Eliminate a warning
MaxGekk Sep 30, 2019
8174fd5
Extend with ExpectsInputTypes
MaxGekk Sep 30, 2019
6378b95
Remove blank lines
MaxGekk Sep 30, 2019
8e4ca7d
Add Month
MaxGekk Sep 30, 2019
8ed01c7
Week is not supported by PostgreSQL
MaxGekk Sep 30, 2019
f1eea12
Remove not-supported fields
MaxGekk Sep 30, 2019
561f789
Week of interval is not supported
MaxGekk Sep 30, 2019
0a671a9
Add Day
MaxGekk Sep 30, 2019
894a6c7
Add Hour
MaxGekk Sep 30, 2019
f86f4f5
Change Month type to ByteType
MaxGekk Sep 30, 2019
283fd99
Change Quarter type to ByteType
MaxGekk Sep 30, 2019
5e189ca
Put common code to IntervalPart
MaxGekk Sep 30, 2019
62c21b9
Run scalafmt
MaxGekk Sep 30, 2019
a4fbb5e
Add Minute
MaxGekk Sep 30, 2019
e1c9415
Add Second
MaxGekk Sep 30, 2019
7f4100f
Run scalafmt
MaxGekk Sep 30, 2019
f3cf7f0
Refactoring
MaxGekk Sep 30, 2019
9262f9d
Add a test for overflow
MaxGekk Sep 30, 2019
b9890ec
Add Milliseconds
MaxGekk Sep 30, 2019
bea3faf
Add Microseconds
MaxGekk Sep 30, 2019
77e0fb3
Add Epoch
MaxGekk Sep 30, 2019
58017a7
Support intervals by date_part
MaxGekk Sep 30, 2019
f5620b3
Update comments for DatePart
MaxGekk Sep 30, 2019
dcaf5b2
Regenerate results of date_part.sql
MaxGekk Sep 30, 2019
f202b15
Add tests for intervals to date_part.sql
MaxGekk Sep 30, 2019
dca29e5
Remove wrong test
MaxGekk Sep 30, 2019
f8a2385
Make Dongjoon and Scala style checker happy
MaxGekk Oct 1, 2019
7b1663e
Merge remote-tracking branch 'remotes/origin/master' into extract-fro…
MaxGekk Oct 8, 2019
8a494a2
Improve an example
MaxGekk Oct 8, 2019
f08531b
Precise epoch calculation from intervals
MaxGekk Oct 8, 2019
e8a61c8
Fix expected results in IntervalExpressionsSuite
MaxGekk Oct 8, 2019
f8a45b3
Revert "Precise epoch calculation from intervals"
MaxGekk Oct 12, 2019
a496d73
Precise calculation micros per month
MaxGekk Oct 12, 2019
47a0290
Revert "Precise calculation micros per month"
MaxGekk Oct 18, 2019
2099a91
Fix expected results in IntervalExpressionsSuite
MaxGekk Oct 18, 2019
d4375b5
Add the Extract prefix to all classes
MaxGekk Oct 18, 2019
5620472
Change indentation for extends to 2 spaces
MaxGekk Oct 18, 2019
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
Prev Previous commit
Next Next commit
Refactoring
  • Loading branch information
MaxGekk committed Sep 30, 2019
commit f3cf7f01e060f75611768ef80c1ebce36561aded
Original file line number Diff line number Diff line change
Expand Up @@ -44,47 +44,48 @@ abstract class IntervalPart(
}
}

case class Millennium(child: Expression)
extends IntervalPart(child, IntegerType, getMillennium, "getMillennium")
case class Millenniums(child: Expression)
extends IntervalPart(child, IntegerType, getMillenniums, "getMillenniums")

case class Century(child: Expression)
extends IntervalPart(child, IntegerType, getCentury, "getCentury")
case class Centuries(child: Expression)
extends IntervalPart(child, IntegerType, getCenturies, "getCenturies")

case class Decade(child: Expression)
extends IntervalPart(child, IntegerType, getDecade, "getDecade")
case class Decades(child: Expression)
extends IntervalPart(child, IntegerType, getDecades, "getDecades")

case class Year(child: Expression) extends IntervalPart(child, IntegerType, getYear, "getYear")
case class Years(child: Expression) extends IntervalPart(child, IntegerType, getYears, "getYears")

case class Quarter(child: Expression)
extends IntervalPart(child, ByteType, getQuarter, "getQuarter")
case class Quarters(child: Expression)
extends IntervalPart(child, ByteType, getQuarters, "getQuarters")

case class Month(child: Expression) extends IntervalPart(child, ByteType, getMonth, "getMonth")
case class Months(child: Expression) extends IntervalPart(child, ByteType, getMonths, "getMonths")

case class Day(child: Expression) extends IntervalPart(child, LongType, getDay, "getDay")
case class Days(child: Expression) extends IntervalPart(child, LongType, getDays, "getDays")

case class Hour(child: Expression) extends IntervalPart(child, ByteType, getHour, "getHour")
case class Hours(child: Expression) extends IntervalPart(child, ByteType, getHours, "getHours")

case class Minute(child: Expression) extends IntervalPart(child, ByteType, getMinute, "getMinute")
case class Minutes(child: Expression)
extends IntervalPart(child, ByteType, getMinutes, "getMinutes")

case class Second(child: Expression)
extends IntervalPart(child, DecimalType(8, 6), getSecond, "getSecond")
case class Seconds(child: Expression)
extends IntervalPart(child, DecimalType(8, 6), getSeconds, "getSeconds")

object IntervalPart {

def parseExtractField(
extractField: String,
source: Expression,
errorHandleFunc: => Nothing): Expression = extractField.toUpperCase(Locale.ROOT) match {
case "MILLENNIUM" | "MILLENNIA" | "MIL" | "MILS" => Millennium(source)
case "CENTURY" | "CENTURIES" | "C" | "CENT" => Century(source)
case "DECADE" | "DECADES" | "DEC" | "DECS" => Decade(source)
case "YEAR" | "Y" | "YEARS" | "YR" | "YRS" => Year(source)
case "QUARTER" | "QTR" => Quarter(source)
case "MONTH" | "MON" | "MONS" | "MONTHS" => Month(source)
case "DAY" | "D" | "DAYS" => Day(source)
case "HOUR" | "H" | "HOURS" | "HR" | "HRS" => Hour(source)
case "MINUTE" | "M" | "MIN" | "MINS" | "MINUTES" => Minute(source)
case "SECOND" | "S" | "SEC" | "SECONDS" | "SECS" => Second(source)
case "MILLENNIUM" | "MILLENNIA" | "MIL" | "MILS" => Millenniums(source)
case "CENTURY" | "CENTURIES" | "C" | "CENT" => Centuries(source)
case "DECADE" | "DECADES" | "DEC" | "DECS" => Decades(source)
case "YEAR" | "Y" | "YEARS" | "YR" | "YRS" => Years(source)
case "QUARTER" | "QTR" => Quarters(source)
case "MONTH" | "MON" | "MONS" | "MONTHS" => Months(source)
case "DAY" | "D" | "DAYS" => Days(source)
case "HOUR" | "H" | "HOURS" | "HR" | "HRS" => Hours(source)
case "MINUTE" | "M" | "MIN" | "MINS" | "MINUTES" => Minutes(source)
case "SECOND" | "S" | "SEC" | "SECONDS" | "SECS" => Seconds(source)
// case "MILLISECONDS" | "MSEC" | "MSECS" | "MILLISECON" | "MSECONDS" | "MS" =>
// Milliseconds(source)
// case "MICROSECONDS" | "USEC" | "USECS" | "USECONDS" | "MICROSECON" | "US" =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,43 +29,43 @@ object IntervalUtils {
val MICROS_PER_HOUR: Long = DateTimeUtils.MILLIS_PER_HOUR * DateTimeUtils.MICROS_PER_MILLIS
val MICROS_PER_MINUTE: Long = DateTimeUtils.MILLIS_PER_MINUTE * DateTimeUtils.MICROS_PER_MILLIS

def getYear(interval: CalendarInterval): Int = {
def getYears(interval: CalendarInterval): Int = {
interval.months / MONTHS_PER_YEAR
}

def getMillennium(interval: CalendarInterval): Int = {
getYear(interval) / YEARS_PER_MILLENNIUM
def getMillenniums(interval: CalendarInterval): Int = {
getYears(interval) / YEARS_PER_MILLENNIUM
}

def getCentury(interval: CalendarInterval): Int = {
getYear(interval) / YEARS_PER_CENTURY
def getCenturies(interval: CalendarInterval): Int = {
getYears(interval) / YEARS_PER_CENTURY
}

def getDecade(interval: CalendarInterval): Int = {
getYear(interval) / YEARS_PER_DECADE
def getDecades(interval: CalendarInterval): Int = {
getYears(interval) / YEARS_PER_DECADE
}

def getMonth(interval: CalendarInterval): Byte = {
def getMonths(interval: CalendarInterval): Byte = {
(interval.months % MONTHS_PER_YEAR).toByte
}

def getQuarter(interval: CalendarInterval): Byte = {
(getMonth(interval) / MONTHS_PER_QUARTER + 1).toByte
def getQuarters(interval: CalendarInterval): Byte = {
(getMonths(interval) / MONTHS_PER_QUARTER + 1).toByte
}

def getDay(interval: CalendarInterval): Long = {
def getDays(interval: CalendarInterval): Long = {
interval.microseconds / DateTimeUtils.MICROS_PER_DAY
}

def getHour(interval: CalendarInterval): Byte = {
def getHours(interval: CalendarInterval): Byte = {
((interval.microseconds % DateTimeUtils.MICROS_PER_DAY) / MICROS_PER_HOUR).toByte
}

def getMinute(interval: CalendarInterval): Byte = {
def getMinutes(interval: CalendarInterval): Byte = {
((interval.microseconds % MICROS_PER_HOUR) / MICROS_PER_MINUTE).toByte
}

def getSecond(interval: CalendarInterval): Decimal = {
def getSeconds(interval: CalendarInterval): Decimal = {
Decimal(interval.microseconds % MICROS_PER_MINUTE, 8, 6)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,132 +18,133 @@
package org.apache.spark.sql.catalyst.expressions.interval
Copy link
Member

Choose a reason for hiding this comment

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

ditto. Let's remove the interval directory and move this suite to the parent directory.

Copy link
Member Author

Choose a reason for hiding this comment

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

I moved the interval related expressions to the separate package to not clash to date-time expressions. Though I renamed interval expressions in f3cf7f0 but having Millennium and Millenniums in the same name space looks confusing, doesn't it?

Copy link
Member

Choose a reason for hiding this comment

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

New changes look better to me.


import scala.language.implicitConversions

import org.apache.spark.SparkFunSuite
import org.apache.spark.sql.catalyst.expressions.{ExpressionEvalHelper, Literal}
import org.apache.spark.sql.types.Decimal
import org.apache.spark.unsafe.types.CalendarInterval

class IntervalExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
class IntervalExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
implicit def interval(s: String): Literal = {
Literal(CalendarInterval.fromString("interval " + s))
}

test("millennium") {
checkEvaluation(Millennium("0 years"), 0)
checkEvaluation(Millennium("9999 years"), 9)
checkEvaluation(Millennium("1000 years"), 1)
checkEvaluation(Millennium("-2000 years"), -2)
test("millenniums") {
checkEvaluation(Millenniums("0 years"), 0)
checkEvaluation(Millenniums("9999 years"), 9)
checkEvaluation(Millenniums("1000 years"), 1)
checkEvaluation(Millenniums("-2000 years"), -2)
// Microseconds part must not be taken into account
checkEvaluation(Millennium("999 years 400 days"), 0)
checkEvaluation(Millenniums("999 years 400 days"), 0)
// Millennium must be taken from years and months
checkEvaluation(Millennium("999 years 12 months"), 1)
checkEvaluation(Millennium("1000 years -1 months"), 0)
checkEvaluation(Millenniums("999 years 12 months"), 1)
checkEvaluation(Millenniums("1000 years -1 months"), 0)
}

test("century") {
checkEvaluation(Century("0 years"), 0)
checkEvaluation(Century("9999 years"), 99)
checkEvaluation(Century("1000 years"), 10)
checkEvaluation(Century("-2000 years"), -20)
test("centuries") {
checkEvaluation(Centuries("0 years"), 0)
checkEvaluation(Centuries("9999 years"), 99)
checkEvaluation(Centuries("1000 years"), 10)
checkEvaluation(Centuries("-2000 years"), -20)
// Microseconds part must not be taken into account
checkEvaluation(Century("99 years 400 days"), 0)
checkEvaluation(Centuries("99 years 400 days"), 0)
// Century must be taken from years and months
checkEvaluation(Century("99 years 12 months"), 1)
checkEvaluation(Century("100 years -1 months"), 0)
checkEvaluation(Centuries("99 years 12 months"), 1)
checkEvaluation(Centuries("100 years -1 months"), 0)
}

test("decade") {
checkEvaluation(Decade("0 years"), 0)
checkEvaluation(Decade("9999 years"), 999)
checkEvaluation(Decade("1000 years"), 100)
checkEvaluation(Decade("-2000 years"), -200)
test("decades") {
checkEvaluation(Decades("0 years"), 0)
checkEvaluation(Decades("9999 years"), 999)
checkEvaluation(Decades("1000 years"), 100)
checkEvaluation(Decades("-2000 years"), -200)
// Microseconds part must not be taken into account
checkEvaluation(Decade("9 years 400 days"), 0)
checkEvaluation(Decades("9 years 400 days"), 0)
// Decade must be taken from years and months
checkEvaluation(Decade("9 years 12 months"), 1)
checkEvaluation(Decade("10 years -1 months"), 0)
checkEvaluation(Decades("9 years 12 months"), 1)
checkEvaluation(Decades("10 years -1 months"), 0)
}

test("year") {
checkEvaluation(Year("0 years"), 0)
checkEvaluation(Year("9999 years"), 9999)
checkEvaluation(Year("1000 years"), 1000)
checkEvaluation(Year("-2000 years"), -2000)
test("years") {
checkEvaluation(Years("0 years"), 0)
checkEvaluation(Years("9999 years"), 9999)
checkEvaluation(Years("1000 years"), 1000)
checkEvaluation(Years("-2000 years"), -2000)
// Microseconds part must not be taken into account
checkEvaluation(Year("9 years 400 days"), 9)
checkEvaluation(Years("9 years 400 days"), 9)
// Year must be taken from years and months
checkEvaluation(Year("9 years 12 months"), 10)
checkEvaluation(Year("10 years -1 months"), 9)
checkEvaluation(Years("9 years 12 months"), 10)
checkEvaluation(Years("10 years -1 months"), 9)
}

test("quarter") {
checkEvaluation(Quarter("0 months"), 1.toByte)
checkEvaluation(Quarter("1 months"), 1.toByte)
checkEvaluation(Quarter("-1 months"), 1.toByte)
checkEvaluation(Quarter("2 months"), 1.toByte)
checkEvaluation(Quarter("-2 months"), 1.toByte)
checkEvaluation(Quarter("1 years -1 months"), 4.toByte)
checkEvaluation(Quarter("-1 years 1 months"), -2.toByte)
checkEvaluation(Quarter("2 years 3 months"), 2.toByte)
checkEvaluation(Quarter("-2 years -3 months"), 0.toByte)
checkEvaluation(Quarter("9999 years"), 1.toByte)
test("quarters") {
checkEvaluation(Quarters("0 months"), 1.toByte)
checkEvaluation(Quarters("1 months"), 1.toByte)
checkEvaluation(Quarters("-1 months"), 1.toByte)
checkEvaluation(Quarters("2 months"), 1.toByte)
checkEvaluation(Quarters("-2 months"), 1.toByte)
checkEvaluation(Quarters("1 years -1 months"), 4.toByte)
checkEvaluation(Quarters("-1 years 1 months"), -2.toByte)
checkEvaluation(Quarters("2 years 3 months"), 2.toByte)
checkEvaluation(Quarters("-2 years -3 months"), 0.toByte)
checkEvaluation(Quarters("9999 years"), 1.toByte)
}

test("month") {
checkEvaluation(Month("0 year"), 0.toByte)
test("months") {
checkEvaluation(Months("0 year"), 0.toByte)
for (m <- -24 to 24) {
checkEvaluation(Month(s"$m months"), (m % 12).toByte)
checkEvaluation(Months(s"$m months"), (m % 12).toByte)
}
checkEvaluation(Month("1 year 10 months"), 10.toByte)
checkEvaluation(Month("-2 year -10 months"), -10.toByte)
checkEvaluation(Month("9999 years"), 0.toByte)
checkEvaluation(Months("1 year 10 months"), 10.toByte)
checkEvaluation(Months("-2 year -10 months"), -10.toByte)
checkEvaluation(Months("9999 years"), 0.toByte)
}

private val largeInterval: String =
"9999 years 11 months 31 days 11 hours 59 minutes 59 seconds"

test("day") {
checkEvaluation(Day("0 days"), 0L)
checkEvaluation(Day("1 days 100 seconds"), 1L)
checkEvaluation(Day("-1 days -100 seconds"), -1L)
checkEvaluation(Day("-365 days"), -365L)
checkEvaluation(Day("365 days"), 365L)
test("days") {
checkEvaluation(Days("0 days"), 0L)
checkEvaluation(Days("1 days 100 seconds"), 1L)
checkEvaluation(Days("-1 days -100 seconds"), -1L)
checkEvaluation(Days("-365 days"), -365L)
checkEvaluation(Days("365 days"), 365L)
// Years and months must not be taken into account
checkEvaluation(Day("100 year 10 months 5 days"), 5L)
checkEvaluation(Day(largeInterval), 31L)
checkEvaluation(Days("100 year 10 months 5 days"), 5L)
checkEvaluation(Days(largeInterval), 31L)
}

test("hour") {
checkEvaluation(Hour("0 hours"), 0.toByte)
checkEvaluation(Hour("1 hour"), 1.toByte)
checkEvaluation(Hour("-1 hour"), -1.toByte)
checkEvaluation(Hour("23 hours"), 23.toByte)
checkEvaluation(Hour("-23 hours"), -23.toByte)
test("hours") {
checkEvaluation(Hours("0 hours"), 0.toByte)
checkEvaluation(Hours("1 hour"), 1.toByte)
checkEvaluation(Hours("-1 hour"), -1.toByte)
checkEvaluation(Hours("23 hours"), 23.toByte)
checkEvaluation(Hours("-23 hours"), -23.toByte)
// Years and months must not be taken into account
checkEvaluation(Hour("100 year 10 months 10 hours"), 10.toByte)
checkEvaluation(Hour(largeInterval), 11.toByte)
checkEvaluation(Hours("100 year 10 months 10 hours"), 10.toByte)
checkEvaluation(Hours(largeInterval), 11.toByte)
}

test("minute") {
checkEvaluation(Minute("0 minute"), 0.toByte)
checkEvaluation(Minute("1 minute"), 1.toByte)
checkEvaluation(Minute("-1 minute"), -1.toByte)
checkEvaluation(Minute("59 minute"), 59.toByte)
checkEvaluation(Minute("-59 minute"), -59.toByte)
test("minutes") {
checkEvaluation(Minutes("0 minute"), 0.toByte)
checkEvaluation(Minutes("1 minute"), 1.toByte)
checkEvaluation(Minutes("-1 minute"), -1.toByte)
checkEvaluation(Minutes("59 minute"), 59.toByte)
checkEvaluation(Minutes("-59 minute"), -59.toByte)
// Years and months must not be taken into account
checkEvaluation(Minute("100 year 10 months 10 minutes"), 10.toByte)
checkEvaluation(Minute(largeInterval), 59.toByte)
checkEvaluation(Minutes("100 year 10 months 10 minutes"), 10.toByte)
checkEvaluation(Minutes(largeInterval), 59.toByte)
}

test("second") {
checkEvaluation(Second("0 second"), Decimal(0, 8, 6))
checkEvaluation(Second("1 second"), Decimal(1.0, 8, 6))
checkEvaluation(Second("-1 second"), Decimal(-1.0, 8, 6))
checkEvaluation(Second("1 minute 59 second"), Decimal(59.0, 8, 6))
checkEvaluation(Second("-59 minutes -59 seconds"), Decimal(-59.0, 8, 6))
test("seconds") {
checkEvaluation(Seconds("0 second"), Decimal(0, 8, 6))
checkEvaluation(Seconds("1 second"), Decimal(1.0, 8, 6))
checkEvaluation(Seconds("-1 second"), Decimal(-1.0, 8, 6))
checkEvaluation(Seconds("1 minute 59 second"), Decimal(59.0, 8, 6))
checkEvaluation(Seconds("-59 minutes -59 seconds"), Decimal(-59.0, 8, 6))
// Years and months must not be taken into account
checkEvaluation(Second("100 year 10 months 10 seconds"), Decimal(10.0, 8, 6))
checkEvaluation(Second(largeInterval), Decimal(59.0, 8, 6))
checkEvaluation(Second("10 seconds 1 milliseconds 1 microseconds"), Decimal(10001001, 8, 6))
checkEvaluation(Seconds("100 year 10 months 10 seconds"), Decimal(10.0, 8, 6))
checkEvaluation(Seconds(largeInterval), Decimal(59.0, 8, 6))
checkEvaluation(Seconds("10 seconds 1 milliseconds 1 microseconds"), Decimal(10001001, 8, 6))
}
}