diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/IntervalUtils.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/IntervalUtils.scala index 6e33c5b24f47..045483551290 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/IntervalUtils.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/IntervalUtils.scala @@ -478,9 +478,8 @@ object IntervalUtils { var months: Int = 0 var days: Int = 0 var microseconds: Long = 0 - var fractionScale: Int = 0 - val initialFractionScale = (NANOS_PER_SECOND / 10).toInt - var fraction: Int = 0 + var fractionScale: Double = 0 + var fraction: Double = 0 var pointPrefixed: Boolean = false def trimToNextState(b: Byte, next: ParseState): Unit = { @@ -515,6 +514,8 @@ object IntervalUtils { case TRIM_BEFORE_SIGN => trimToNextState(b, SIGN) case SIGN => currentValue = 0 + isNegative = false + fractionScale = 10 fraction = 0 // We preset next state from SIGN to TRIM_BEFORE_VALUE. If we meet '.' in the SIGN state, // it means that the interval value we deal with here is a numeric with only fractional @@ -522,22 +523,14 @@ object IntervalUtils { // to reset next state to `VALUE_FRACTIONAL_PART` to go parse the fraction part of the // interval value. state = TRIM_BEFORE_VALUE - // We preset the scale to an invalid value to track fraction presence in the UNIT_BEGIN - // state. If we meet '.', the scale become valid for the VALUE_FRACTIONAL_PART state. - fractionScale = -1 pointPrefixed = false b match { case '-' => isNegative = true i += 1 - case '+' => - isNegative = false - i += 1 + case '+' => i += 1 case _ if '0' <= b && b <= '9' => - isNegative = false case '.' => - isNegative = false - fractionScale = initialFractionScale pointPrefixed = true i += 1 state = VALUE_FRACTIONAL_PART @@ -553,32 +546,22 @@ object IntervalUtils { case e: ArithmeticException => throwIAE(e.getMessage, e) } case _ if b <= ' ' => state = TRIM_BEFORE_UNIT - case '.' => - fractionScale = initialFractionScale - state = VALUE_FRACTIONAL_PART + case '.' => state = VALUE_FRACTIONAL_PART case _ => throwIAE(s"invalid value '$currentWord'") } i += 1 case VALUE_FRACTIONAL_PART => - if ('0' <= b && b <= '9' && fractionScale > 0) { - fraction += (b - '0') * fractionScale - fractionScale /= 10 - } else if (b <= ' ' && (!pointPrefixed || fractionScale < initialFractionScale)) { - fraction /= NANOS_PER_MICROS.toInt + if ('0' <= b && b <= '9') { + fraction += (b - '0') / fractionScale + fractionScale *= 10 + } else if (b <= ' ' && (!pointPrefixed || fractionScale > 10)) { state = TRIM_BEFORE_UNIT - } else if ('0' <= b && b <= '9') { - throwIAE(s"interval can only support nanosecond precision, '$currentWord' is out" + - s" of range") } else { throwIAE(s"invalid value '$currentWord'") } i += 1 case TRIM_BEFORE_UNIT => trimToNextState(b, UNIT_BEGIN) case UNIT_BEGIN => - // Checks that only seconds can have the fractional part - if (b != 's' && fractionScale >= 0) { - throwIAE(s"'$currentWord' cannot have fractional part") - } if (isNegative) { currentValue = -currentValue fraction = -fraction @@ -586,40 +569,42 @@ object IntervalUtils { try { b match { case 'y' if s.matchAt(yearStr, i) => - val monthsInYears = Math.multiplyExact(MONTHS_PER_YEAR, currentValue) - months = Math.toIntExact(Math.addExact(months, monthsInYears)) + val monthsInYears = + Math.toIntExact(((currentValue + fraction) * MONTHS_PER_YEAR).toLong) + months = Math.addExact(months, monthsInYears) i += yearStr.numBytes() case 'w' if s.matchAt(weekStr, i) => - val daysInWeeks = Math.multiplyExact(DAYS_PER_WEEK, currentValue) - days = Math.toIntExact(Math.addExact(days, daysInWeeks)) + val daysInWeeks = (currentValue + fraction) * DAYS_PER_WEEK + val daysTrimmed = Math.toIntExact(daysInWeeks.toLong) + days = Math.addExact(days, daysTrimmed) + microseconds += ((daysInWeeks - daysTrimmed) * MICROS_PER_DAY).round i += weekStr.numBytes() case 'd' if s.matchAt(dayStr, i) => days = Math.addExact(days, Math.toIntExact(currentValue)) + microseconds += (fraction * MICROS_PER_DAY).round i += dayStr.numBytes() case 'h' if s.matchAt(hourStr, i) => - val hoursUs = Math.multiplyExact(currentValue, MICROS_PER_HOUR) - microseconds = Math.addExact(microseconds, hoursUs) + microseconds += ((currentValue + fraction) * MICROS_PER_HOUR).round i += hourStr.numBytes() case 's' if s.matchAt(secondStr, i) => - val secondsUs = Math.multiplyExact(currentValue, MICROS_PER_SECOND) - microseconds = Math.addExact(Math.addExact(microseconds, secondsUs), fraction) + microseconds += ((currentValue + fraction) * MICROS_PER_SECOND).round i += secondStr.numBytes() case 'm' => if (s.matchAt(monthStr, i)) { months = Math.addExact(months, Math.toIntExact(currentValue)) + val dayLeftover = fraction * DAYS_PER_MONTH + val daysTrimmed = Math.toIntExact(dayLeftover.toLong) + days = Math.addExact(days, daysTrimmed) + microseconds += ((dayLeftover - daysTrimmed) * MICROS_PER_DAY).round i += monthStr.numBytes() } else if (s.matchAt(minuteStr, i)) { - val minutesUs = Math.multiplyExact(currentValue, MICROS_PER_MINUTE) - microseconds = Math.addExact(microseconds, minutesUs) + microseconds += ((currentValue + fraction) * MICROS_PER_MINUTE).round i += minuteStr.numBytes() } else if (s.matchAt(millisStr, i)) { - val millisUs = Math.multiplyExact( - currentValue, - MICROS_PER_MILLIS) - microseconds = Math.addExact(microseconds, millisUs) + microseconds += ((currentValue + fraction) * MICROS_PER_MILLIS).round i += millisStr.numBytes() } else if (s.matchAt(microsStr, i)) { - microseconds = Math.addExact(microseconds, currentValue) + microseconds += (currentValue + fraction).round i += microsStr.numBytes() } else throwIAE(s"invalid unit '$currentWord'") case _ => throwIAE(s"invalid unit '$currentWord'") diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala index 371b702722a6..e68355b6aae5 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala @@ -645,7 +645,7 @@ class ExpressionParserSuite extends AnalysisTest { Literal(new CalendarInterval( 0, 0, - -13 * MICROS_PER_SECOND - 123 * MICROS_PER_MILLIS - 456))) + -13 * MICROS_PER_SECOND - 123 * MICROS_PER_MILLIS - 457))) checkIntervals( "13.123456 second", Literal(new CalendarInterval( diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala index c98bb61b6ee7..a4df9eb97142 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala @@ -104,8 +104,6 @@ class IntervalUtilsSuite extends SparkFunSuite { // Allow duplicated units and summarize their values checkFromString("1 day 10 day", new CalendarInterval(0, 11, 0)) // Only the seconds units can have the fractional part - checkFromInvalidString("1.5 days", "'days' cannot have fractional part") - checkFromInvalidString("1. hour", "'hour' cannot have fractional part") checkFromInvalidString("1 hourX", "invalid unit 'hourx'") checkFromInvalidString("~1 hour", "unrecognized number '~1'") checkFromInvalidString("1 Mour", "invalid unit 'mour'") @@ -125,7 +123,7 @@ class IntervalUtilsSuite extends SparkFunSuite { checkFromString("interval\r1\tday", new CalendarInterval(0, 1, 0)) } - test("string to interval: seconds with fractional part") { + test("string to interval: interval with fractional part") { checkFromString("0.1 seconds", new CalendarInterval(0, 0, 100000)) checkFromString("1. seconds", new CalendarInterval(0, 0, 1000000)) checkFromString("123.001 seconds", new CalendarInterval(0, 0, 123001000)) @@ -133,9 +131,10 @@ class IntervalUtilsSuite extends SparkFunSuite { checkFromString("1 minute 1.001001 seconds", new CalendarInterval(0, 0, 61001001)) checkFromString("-1.5 seconds", new CalendarInterval(0, 0, -1500000)) // truncate nanoseconds to microseconds - checkFromString("0.999999999 seconds", new CalendarInterval(0, 0, 999999)) - checkFromString(".999999999 seconds", new CalendarInterval(0, 0, 999999)) - checkFromInvalidString("0.123456789123 seconds", "'0.123456789123' is out of range") + checkFromString("0.999999999 seconds", new CalendarInterval(0, 0, 1000000)) + checkFromString(".999999 seconds", new CalendarInterval(0, 0, 999999)) + checkFromString("0.123456789123 seconds", new CalendarInterval(0, 0, 123457)) + checkFromString("1.5 days", new CalendarInterval(0, 1, 12 * MICROS_PER_HOUR)) } test("from year-month string") { diff --git a/sql/core/benchmarks/IntervalBenchmark-jdk11-results.txt b/sql/core/benchmarks/IntervalBenchmark-jdk11-results.txt index 07dd8d5e44ea..396eab12501a 100644 --- a/sql/core/benchmarks/IntervalBenchmark-jdk11-results.txt +++ b/sql/core/benchmarks/IntervalBenchmark-jdk11-results.txt @@ -1,29 +1,23 @@ -Java HotSpot(TM) 64-Bit Server VM 11.0.5+10-LTS on Mac OS X 10.14.6 +Java HotSpot(TM) 64-Bit Server VM 11.0.5+10-LTS on Mac OS X 10.15.1 Intel(R) Core(TM) i5-5287U CPU @ 2.90GHz cast strings to intervals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative ------------------------------------------------------------------------------------------------------------------------ -prepare string w/ interval 574 610 45 1.7 573.9 1.0X -prepare string w/o interval 518 538 27 1.9 517.7 1.1X -1 units w/ interval 425 439 16 2.4 425.3 1.3X -1 units w/o interval 385 393 10 2.6 385.2 1.5X -2 units w/ interval 553 561 11 1.8 553.1 1.0X -2 units w/o interval 531 543 11 1.9 531.0 1.1X -3 units w/ interval 1134 1159 32 0.9 1134.0 0.5X -3 units w/o interval 1121 1126 6 0.9 1121.3 0.5X -4 units w/ interval 1226 1250 21 0.8 1226.1 0.5X -4 units w/o interval 1227 1239 11 0.8 1227.1 0.5X -5 units w/ interval 1375 1447 93 0.7 1374.7 0.4X -5 units w/o interval 1335 1346 19 0.7 1335.1 0.4X -6 units w/ interval 1530 1556 24 0.7 1529.5 0.4X -6 units w/o interval 1481 1492 17 0.7 1480.7 0.4X -7 units w/ interval 1730 1745 14 0.6 1729.9 0.3X -7 units w/o interval 1788 1859 112 0.6 1788.1 0.3X -8 units w/ interval 1952 2087 117 0.5 1951.7 0.3X -8 units w/o interval 2083 2207 209 0.5 2082.5 0.3X -9 units w/ interval 2228 2291 60 0.4 2227.5 0.3X -9 units w/o interval 2130 2184 75 0.5 2130.1 0.3X -10 units w/ interval 2414 2502 81 0.4 2413.8 0.2X -10 units w/o interval 2463 2488 35 0.4 2463.1 0.2X -11 units w/ interval 2717 2755 42 0.4 2716.8 0.2X -11 units w/o interval 2578 2661 77 0.4 2577.7 0.2X +prepare string w/ interval 644 698 84 1.6 644.1 1.0X +prepare string w/o interval 599 625 39 1.7 598.7 1.1X +1 units w/ interval 441 448 9 2.3 441.0 1.5X +1 units w/o interval 389 394 6 2.6 388.6 1.7X +2 units w/ interval 559 575 22 1.8 559.1 1.2X +2 units w/o interval 542 548 5 1.8 542.2 1.2X +4 units w/ interval 1249 1263 15 0.8 1249.4 0.5X +4 units w/o interval 1237 1252 15 0.8 1237.3 0.5X +6 units w/ interval 1585 1596 12 0.6 1585.1 0.4X +6 units w/o interval 1573 1585 17 0.6 1573.3 0.4X +8 units w/ interval 2029 2032 4 0.5 2029.2 0.3X +8 units w/o interval 2015 2026 18 0.5 2015.1 0.3X +10 units w/ interval 2367 2370 2 0.4 2367.5 0.3X +10 units w/o interval 2356 2357 2 0.4 2356.1 0.3X +12 units w/ interval 2785 2821 43 0.4 2784.9 0.2X +12 units w/o interval 2817 2856 37 0.4 2816.9 0.2X +14 units w/ interval 3303 3319 28 0.3 3302.7 0.2X +14 units w/o interval 3293 3310 21 0.3 3292.6 0.2X diff --git a/sql/core/benchmarks/IntervalBenchmark-results.txt b/sql/core/benchmarks/IntervalBenchmark-results.txt index 8976fb590d8d..bc305b5802aa 100644 --- a/sql/core/benchmarks/IntervalBenchmark-results.txt +++ b/sql/core/benchmarks/IntervalBenchmark-results.txt @@ -1,29 +1,23 @@ Java HotSpot(TM) 64-Bit Server VM 1.8.0_231-b11 on Mac OS X 10.15.1 -Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz +Intel(R) Core(TM) i5-5287U CPU @ 2.90GHz cast strings to intervals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative ------------------------------------------------------------------------------------------------------------------------ -prepare string w/ interval 357 370 22 2.8 357.0 1.0X -prepare string w/o interval 315 333 22 3.2 314.7 1.1X -1 units w/ interval 356 380 21 2.8 355.8 1.0X -1 units w/o interval 317 326 12 3.2 317.1 1.1X -2 units w/ interval 481 488 8 2.1 480.8 0.7X -2 units w/o interval 456 464 9 2.2 456.0 0.8X -3 units w/ interval 1074 1080 5 0.9 1073.7 0.3X -3 units w/o interval 1025 1027 2 1.0 1025.4 0.3X -4 units w/ interval 1192 1196 5 0.8 1192.2 0.3X -4 units w/o interval 1219 1233 14 0.8 1218.9 0.3X -5 units w/ interval 1367 1382 23 0.7 1367.3 0.3X -5 units w/o interval 1295 1301 7 0.8 1295.1 0.3X -6 units w/ interval 1489 1525 31 0.7 1489.3 0.2X -6 units w/o interval 1496 1500 6 0.7 1495.8 0.2X -7 units w/ interval 1326 1330 4 0.8 1325.5 0.3X -7 units w/o interval 1324 1332 11 0.8 1324.1 0.3X -8 units w/ interval 1535 1547 11 0.7 1535.4 0.2X -8 units w/o interval 1542 1547 5 0.6 1542.3 0.2X -9 units w/ interval 1623 1641 18 0.6 1623.0 0.2X -9 units w/o interval 1615 1619 3 0.6 1615.3 0.2X -10 units w/ interval 1845 1861 16 0.5 1844.7 0.2X -10 units w/o interval 1858 1868 9 0.5 1857.8 0.2X -11 units w/ interval 1919 1925 11 0.5 1918.7 0.2X -11 units w/o interval 1973 1995 23 0.5 1972.8 0.2X +prepare string w/ interval 675 735 68 1.5 675.2 1.0X +prepare string w/o interval 569 630 60 1.8 569.2 1.2X +1 units w/ interval 519 565 68 1.9 519.1 1.3X +1 units w/o interval 450 468 21 2.2 450.1 1.5X +2 units w/ interval 637 645 11 1.6 636.6 1.1X +2 units w/o interval 601 616 14 1.7 601.5 1.1X +4 units w/ interval 1403 1418 26 0.7 1403.2 0.5X +4 units w/o interval 1404 1408 5 0.7 1403.6 0.5X +6 units w/ interval 1720 1728 12 0.6 1720.2 0.4X +6 units w/o interval 1679 1686 6 0.6 1678.7 0.4X +8 units w/ interval 1998 2022 21 0.5 1997.6 0.3X +8 units w/o interval 2012 2021 13 0.5 2011.6 0.3X +10 units w/ interval 2362 2385 22 0.4 2362.0 0.3X +10 units w/o interval 2378 2401 22 0.4 2377.6 0.3X +12 units w/ interval 2835 2851 17 0.4 2835.0 0.2X +12 units w/o interval 2829 2832 4 0.4 2829.4 0.2X +14 units w/ interval 3325 3376 47 0.3 3325.2 0.2X +14 units w/o interval 3323 3336 13 0.3 3323.2 0.2X diff --git a/sql/core/src/test/resources/sql-tests/inputs/interval.sql b/sql/core/src/test/resources/sql-tests/inputs/interval.sql index 5806d9288572..b3a410b847e0 100644 --- a/sql/core/src/test/resources/sql-tests/inputs/interval.sql +++ b/sql/core/src/test/resources/sql-tests/inputs/interval.sql @@ -264,3 +264,16 @@ select interval 'interval \t 1\tday'; select interval 'interval\t1\tday'; select interval '1\t' day; select interval '1 ' day; + +select interval '1.41666666666666 year'; +select interval '1.41666666666667 year'; +select interval '1.1333333333301 months'; +select interval '1.133333333330 months'; +select interval '2.13333333 week'; +select interval '2.13333334 week'; +select interval '0.1 seconds'; +select interval '0.49 microseconds'; +select interval '0.50 microseconds'; +select interval '87649415 hours 59 minutes 59 seconds 999 milliseconds 999 microseconds'; +select interval '-0.51 year'; +select interval '-0.41 year'; diff --git a/sql/core/src/test/resources/sql-tests/results/ansi/interval.sql.out b/sql/core/src/test/resources/sql-tests/results/ansi/interval.sql.out index a2d03064afdd..4ade4239fbfb 100644 --- a/sql/core/src/test/resources/sql-tests/results/ansi/interval.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/ansi/interval.sql.out @@ -1,5 +1,5 @@ -- Automatically generated by SQLQueryTestSuite --- Number of queries: 135 +-- Number of queries: 147 -- !query 0 @@ -479,9 +479,9 @@ struct -- !query 59 select interval 13.123456789 seconds, interval -13.123456789 second -- !query 59 schema -struct +struct -- !query 59 output -13.123456 seconds -13.123456 seconds +13.123457 seconds -13.123457 seconds -- !query 60 @@ -1156,34 +1156,130 @@ struct -- !query 123 -select 1 year 2 days +select interval '1.41666666666666 year' -- !query 123 schema -struct +struct -- !query 123 output -1 years 2 days +1 years 4 months -- !query 124 -select '10-9' year to month +select interval '1.41666666666667 year' -- !query 124 schema -struct +struct -- !query 124 output -10 years 9 months +1 years 5 months -- !query 125 -select '20 15:40:32.99899999' day to second +select interval '1.1333333333301 months' -- !query 125 schema -struct +struct -- !query 125 output -20 days 15 hours 40 minutes 32.998999 seconds +1 months 3 days 23 hours 59 minutes 59.999992 seconds -- !query 126 -select 30 day day +select interval '1.133333333330 months' -- !query 126 schema -struct<> +struct -- !query 126 output +1 months 3 days 23 hours 59 minutes 59.999991 seconds + + +-- !query 127 +select interval '2.13333333 week' +-- !query 127 schema +struct +-- !query 127 output +14 days 22 hours 23 minutes 59.997984 seconds + + +-- !query 128 +select interval '2.13333334 week' +-- !query 128 schema +struct +-- !query 128 output +14 days 22 hours 24 minutes 0.004032 seconds + + +-- !query 129 +select interval '0.1 seconds' +-- !query 129 schema +struct +-- !query 129 output +0.1 seconds + + +-- !query 130 +select interval '0.49 microseconds' +-- !query 130 schema +struct +-- !query 130 output +0 seconds + + +-- !query 131 +select interval '0.50 microseconds' +-- !query 131 schema +struct +-- !query 131 output +0.000001 seconds + + +-- !query 132 +select interval '87649415 hours 59 minutes 59 seconds 999 milliseconds 999 microseconds' +-- !query 132 schema +struct +-- !query 132 output +87649415 hours 59 minutes 59.999999 seconds + + +-- !query 133 +select interval '-0.51 year' +-- !query 133 schema +struct +-- !query 133 output +-6 months + + +-- !query 134 +select interval '-0.41 year' +-- !query 134 schema +struct +-- !query 134 output +-4 months + + +-- !query 135 +select 1 year 2 days +-- !query 135 schema +struct +-- !query 135 output +1 years 2 days + + +-- !query 136 +select '10-9' year to month +-- !query 136 schema +struct +-- !query 136 output +10 years 9 months + + +-- !query 137 +select '20 15:40:32.99899999' day to second +-- !query 137 schema +struct +-- !query 137 output +20 days 15 hours 40 minutes 32.998999 seconds + + +-- !query 138 +select 30 day day +-- !query 138 schema +struct<> +-- !query 138 output org.apache.spark.sql.catalyst.parser.ParseException no viable alternative at input 'day'(line 1, pos 14) @@ -1193,27 +1289,27 @@ select 30 day day --------------^^^ --- !query 127 +-- !query 139 select date'2012-01-01' - '2-2' year to month --- !query 127 schema +-- !query 139 schema struct --- !query 127 output +-- !query 139 output 2009-11-01 --- !query 128 +-- !query 140 select 1 month - 1 day --- !query 128 schema +-- !query 140 schema struct --- !query 128 output +-- !query 140 output 1 months -1 days --- !query 129 +-- !query 141 select 1 year to month --- !query 129 schema +-- !query 141 schema struct<> --- !query 129 output +-- !query 141 output org.apache.spark.sql.catalyst.parser.ParseException The value of from-to unit must be a string(line 1, pos 7) @@ -1223,11 +1319,11 @@ select 1 year to month -------^^^ --- !query 130 +-- !query 142 select '1' year to second --- !query 130 schema +-- !query 142 schema struct<> --- !query 130 output +-- !query 142 output org.apache.spark.sql.catalyst.parser.ParseException Intervals FROM year TO second are not supported.(line 1, pos 7) @@ -1237,11 +1333,11 @@ select '1' year to second -------^^^ --- !query 131 +-- !query 143 select 1 year '2-1' year to month --- !query 131 schema +-- !query 143 schema struct<> --- !query 131 output +-- !query 143 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 14) @@ -1251,11 +1347,11 @@ select 1 year '2-1' year to month --------------^^^ --- !query 132 +-- !query 144 select (-30) day --- !query 132 schema +-- !query 144 schema struct<> --- !query 132 output +-- !query 144 output org.apache.spark.sql.catalyst.parser.ParseException no viable alternative at input 'day'(line 1, pos 13) @@ -1265,11 +1361,11 @@ select (-30) day -------------^^^ --- !query 133 +-- !query 145 select (a + 1) day --- !query 133 schema +-- !query 145 schema struct<> --- !query 133 output +-- !query 145 output org.apache.spark.sql.catalyst.parser.ParseException no viable alternative at input 'day'(line 1, pos 15) @@ -1279,11 +1375,11 @@ select (a + 1) day ---------------^^^ --- !query 134 +-- !query 146 select 30 day day day --- !query 134 schema +-- !query 146 schema struct<> --- !query 134 output +-- !query 146 output org.apache.spark.sql.catalyst.parser.ParseException no viable alternative at input 'day'(line 1, pos 14) diff --git a/sql/core/src/test/resources/sql-tests/results/interval.sql.out b/sql/core/src/test/resources/sql-tests/results/interval.sql.out index 69a23bb9f183..0a146ba74f5b 100644 --- a/sql/core/src/test/resources/sql-tests/results/interval.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/interval.sql.out @@ -1,5 +1,5 @@ -- Automatically generated by SQLQueryTestSuite --- Number of queries: 123 +-- Number of queries: 135 -- !query 0 @@ -479,9 +479,9 @@ struct -- !query 59 select interval 13.123456789 seconds, interval -13.123456789 second -- !query 59 schema -struct +struct -- !query 59 output -13.123456 seconds -13.123456 seconds +13.123457 seconds -13.123457 seconds -- !query 60 @@ -1137,3 +1137,99 @@ select interval '1 ' day struct -- !query 122 output 1 days + + +-- !query 123 +select interval '1.41666666666666 year' +-- !query 123 schema +struct +-- !query 123 output +1 years 4 months + + +-- !query 124 +select interval '1.41666666666667 year' +-- !query 124 schema +struct +-- !query 124 output +1 years 5 months + + +-- !query 125 +select interval '1.1333333333301 months' +-- !query 125 schema +struct +-- !query 125 output +1 months 3 days 23 hours 59 minutes 59.999992 seconds + + +-- !query 126 +select interval '1.133333333330 months' +-- !query 126 schema +struct +-- !query 126 output +1 months 3 days 23 hours 59 minutes 59.999991 seconds + + +-- !query 127 +select interval '2.13333333 week' +-- !query 127 schema +struct +-- !query 127 output +14 days 22 hours 23 minutes 59.997984 seconds + + +-- !query 128 +select interval '2.13333334 week' +-- !query 128 schema +struct +-- !query 128 output +14 days 22 hours 24 minutes 0.004032 seconds + + +-- !query 129 +select interval '0.1 seconds' +-- !query 129 schema +struct +-- !query 129 output +0.1 seconds + + +-- !query 130 +select interval '0.49 microseconds' +-- !query 130 schema +struct +-- !query 130 output +0 seconds + + +-- !query 131 +select interval '0.50 microseconds' +-- !query 131 schema +struct +-- !query 131 output +0.000001 seconds + + +-- !query 132 +select interval '87649415 hours 59 minutes 59 seconds 999 milliseconds 999 microseconds' +-- !query 132 schema +struct +-- !query 132 output +87649415 hours 59 minutes 59.999999 seconds + + +-- !query 133 +select interval '-0.51 year' +-- !query 133 schema +struct +-- !query 133 output +-6 months + + +-- !query 134 +select interval '-0.41 year' +-- !query 134 schema +struct +-- !query 134 output +-4 months diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/benchmark/IntervalBenchmark.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/benchmark/IntervalBenchmark.scala index b9bb6f5febd7..9783453fd7ff 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/benchmark/IntervalBenchmark.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/benchmark/IntervalBenchmark.scala @@ -85,7 +85,8 @@ object IntervalBenchmark extends SqlBasedBenchmark { val timeUnits = Seq( "13 months", " 1 months", "100 weeks", "9 days", "12 hours", "- 3 hours", - "5 minutes", "45 seconds", "123 milliseconds", "567 microseconds") + "5 minutes", "45.123456 seconds", "123 milliseconds", "567 microseconds", + "98.76543210 seconds", "12.34567890 seconds", "99.999999999 seconds") val intervalToTest = ListBuffer[String]() val benchmark = new Benchmark("cast strings to intervals", N, output = output) @@ -94,9 +95,11 @@ object IntervalBenchmark extends SqlBasedBenchmark { addCase(benchmark, N, "prepare string w/o interval", buildString(false, timeUnits)) addCase(benchmark, N, intervalToTest) // Only years - for (unit <- timeUnits) { + timeUnits.zipWithIndex.foreach { case (unit, i) => intervalToTest.append(unit) - addCase(benchmark, N, intervalToTest) + if (i % 2 == 0) { + addCase(benchmark, N, intervalToTest) + } } benchmark.run() diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/DDLParserSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/DDLParserSuite.scala index 813cae29d268..321fea9a77d6 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/DDLParserSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/DDLParserSuite.scala @@ -715,8 +715,6 @@ class DDLParserSuite extends AnalysisTest with SharedSparkSession { "hour 49 outside range [0, 23]") assertError("select interval '23:61:15' hour to second", "minute 61 outside range [0, 59]") - assertError("select interval '.1111111111' second", - "'.1111111111' is out of range") } test("use native json_tuple instead of hive's UDTF in LATERAL VIEW") {