Skip to content

Commit d768468

Browse files
committed
Fix parsing negative nanos
1 parent 012143f commit d768468

File tree

2 files changed

+14
-9
lines changed

2 files changed

+14
-9
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/IntervalUtils.scala

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ object IntervalUtils {
218218
minutes = toLongWithRange("second", m.group(7), 0, 59)
219219
}
220220
// Hive allow nanosecond precision interval
221-
var nanos = parseNanos(m.group(9))
221+
var nanos = parseNanos(m.group(9), seconds < 0)
222222
to match {
223223
case "hour" =>
224224
minutes = 0
@@ -287,9 +287,11 @@ object IntervalUtils {
287287
new CalendarInterval(months, microseconds)
288288
}
289289

290-
private def parseNanos(nanosStr: String): Long = {
290+
private def parseNanos(nanosStr: String, isNegative: Boolean): Long = {
291291
val alignedStr = if (nanosStr == null) nanosStr else (nanosStr + "000000000").substring(0, 9)
292-
toLongWithRange("nanosecond", alignedStr, 0L, 999999999L) / DateTimeUtils.NANOS_PER_MICROS
292+
val nanos = toLongWithRange("nanosecond", alignedStr, 0L, 999999999L)
293+
val micros = nanos / DateTimeUtils.NANOS_PER_MICROS
294+
if (isNegative) -micros else micros
293295
}
294296

295297
/**
@@ -306,9 +308,10 @@ object IntervalUtils {
306308

307309
secondNano.split("\\.") match {
308310
case Array(secondsStr) => parseSeconds(secondsStr)
309-
case Array("", nanosStr) => parseNanos(nanosStr)
311+
case Array("", nanosStr) => parseNanos(nanosStr, false)
310312
case Array(secondsStr, nanosStr) =>
311-
Math.addExact(parseSeconds(secondsStr), parseNanos(nanosStr))
313+
val seconds = parseSeconds(secondsStr)
314+
Math.addExact(seconds, parseNanos(nanosStr, seconds < 0))
312315
case _ =>
313316
throw new IllegalArgumentException(
314317
"Interval string does not match second-nano format of ss.nnnnnnnnn")

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -628,14 +628,16 @@ class ExpressionParserSuite extends AnalysisTest {
628628

629629
// Hive nanosecond notation.
630630
checkIntervals("13.123456789 seconds", intervalLiteral("second", "13.123456789"))
631-
checkIntervals("-13.123456789 second", intervalLiteral("second", "-13.123456789"))
631+
checkIntervals(
632+
"-13.123456789 second",
633+
Literal(new CalendarInterval(
634+
0,
635+
-13 * DateTimeUtils.MICROS_PER_SECOND - 123 * DateTimeUtils.MICROS_PER_MILLIS - 456)))
632636
checkIntervals(
633637
"13.123456 second",
634638
Literal(new CalendarInterval(
635639
0,
636-
13 * DateTimeUtils.MICROS_PER_SECOND +
637-
123 * DateTimeUtils.MICROS_PER_MILLIS +
638-
456)))
640+
13 * DateTimeUtils.MICROS_PER_SECOND + 123 * DateTimeUtils.MICROS_PER_MILLIS + 456)))
639641
checkIntervals("1.001 second", Literal(IntervalUtils.fromString("1 second 1 millisecond")))
640642

641643
// Non Existing unit

0 commit comments

Comments
 (0)