diff --git a/docs/sql-migration-guide.md b/docs/sql-migration-guide.md index 9bcd36ce41271..ca78f3ca46ea5 100644 --- a/docs/sql-migration-guide.md +++ b/docs/sql-migration-guide.md @@ -256,6 +256,8 @@ license: | - Since Spark 3.0, the unary arithmetic operator plus(`+`) only accepts string, numeric and interval type values as inputs. Besides, `+` with a integral string representation will be coerced to double value, e.g. `+'1'` results `1.0`. In Spark version 2.4 and earlier, this operator is ignored. There is no type checking for it, thus, all type values with a `+` prefix are valid, e.g. `+ array(1, 2)` is valid and results `[1, 2]`. Besides, there is no type coercion for it at all, e.g. in Spark 2.4, the result of `+'1'` is string `1`. + - Since Spark 3.0, day-time interval strings are converted to intervals with respect to the `from` and `to` bounds. If an input string does not match to the pattern defined by specified bounds, the `ParseException` exception is thrown. For example, `interval '2 10:20' hour to minute` raises the exception because the expected format is `[+|-]h[h]:[m]m`. In Spark version 2.4, the `from` bound was not taken into account, and the `to` bound was used to truncate the resulted interval. For instance, the day-time interval string from the showed example is converted to `interval 10 hours 20 minutes`. To restore the behavior before Spark 3.0, you can set `spark.sql.legacy.fromDayTimeString.enabled` to `true`. + ## Upgrading from Spark SQL 2.4 to 2.4.1 - The value of `spark.executor.heartbeatInterval`, when specified without units like "30" rather than "30s", was 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 6e33c5b24f478..2a60cfd52ca99 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 @@ -23,6 +23,7 @@ import java.util.concurrent.TimeUnit import scala.util.control.NonFatal import org.apache.spark.sql.catalyst.util.DateTimeConstants._ +import org.apache.spark.sql.internal.SQLConf import org.apache.spark.sql.types.Decimal import org.apache.spark.unsafe.types.{CalendarInterval, UTF8String} @@ -155,9 +156,6 @@ object IntervalUtils { fromDayTimeString(s, DAY, SECOND) } - private val dayTimePattern = - "^([+|-])?((\\d+) )?((\\d+):)?(\\d+):(\\d+)(\\.(\\d+))?$".r - /** * Parse dayTime string in form: [-]d HH:mm:ss.nnnnnnnnn and [-]HH:mm:ss.nnnnnnnnn * @@ -168,9 +166,35 @@ object IntervalUtils { * - MINUTE TO SECOND */ def fromDayTimeString(input: String, from: IntervalUnit, to: IntervalUnit): CalendarInterval = { + if (SQLConf.get.getConf(SQLConf.LEGACY_FROM_DAYTIME_STRING)) { + parseDayTimeLegacy(input, from, to) + } else { + parseDayTime(input, from, to) + } + } + + private val dayTimePatternLegacy = + "^([+|-])?((\\d+) )?((\\d+):)?(\\d+):(\\d+)(\\.(\\d+))?$".r + + /** + * Legacy method of parsing a string in a day-time format. It ignores the `from` bound, + * and takes into account only the `to` bound by truncating the result. For example, + * if the input string is "2 12:30:15", `from` is "hour" and `to` is "second", the result + * is "2 days 12 hours 30 minutes". + * + * @param input The day-time string + * @param from The interval units from which the input strings begins + * @param to The interval units at which the input string ends + * @return an instance of `CalendarInterval` if parsing completes successfully otherwise + * the exception `IllegalArgumentException` is raised. + */ + private def parseDayTimeLegacy( + input: String, + from: IntervalUnit, + to: IntervalUnit): CalendarInterval = { require(input != null, "Interval day-time string must be not null") assert(input.length == input.trim.length) - val m = dayTimePattern.pattern.matcher(input) + val m = dayTimePatternLegacy.pattern.matcher(input) require(m.matches, s"Interval string must match day-time format of 'd h:m:s.n': $input") try { @@ -222,6 +246,78 @@ object IntervalUtils { } } + private val signRe = "(?[+|-])" + private val dayRe = "(?\\d+)" + private val hourRe = "(?\\d{1,2})" + private val minuteRe = "(?\\d{1,2})" + private val secondRe = "(?(\\d{1,2})(\\.(\\d{1,9}))?)" + + private val dayTimePattern = Map( + (MINUTE, SECOND) -> s"^$signRe?$minuteRe:$secondRe$$".r, + (HOUR, MINUTE) -> s"^$signRe?$hourRe:$minuteRe$$".r, + (HOUR, SECOND) -> s"^$signRe?$hourRe:$minuteRe:$secondRe$$".r, + (DAY, HOUR) -> s"^$signRe?$dayRe $hourRe$$".r, + (DAY, MINUTE) -> s"^$signRe?$dayRe $hourRe:$minuteRe$$".r, + (DAY, SECOND) -> s"^$signRe?$dayRe $hourRe:$minuteRe:$secondRe$$".r + ) + + private def unitsRange(start: IntervalUnit, end: IntervalUnit): Seq[IntervalUnit] = { + (start.id to end.id).map(IntervalUnit(_)) + } + + /** + * Parses an input string in the day-time format defined by the `from` and `to` bounds. + * It supports the following formats: + * - [+|-]D+ H[H]:m[m]:s[s][.SSSSSSSSS] for DAY TO SECOND + * - [+|-]D+ H[H]:m[m] for DAY TO MINUTE + * - [+|-]D+ H[H] for DAY TO HOUR + * - [+|-]H[H]:m[m]s[s][.SSSSSSSSS] for HOUR TO SECOND + * - [+|-]H[H]:m[m] for HOUR TO MINUTE + * - [+|-]m[m]:s[s][.SSSSSSSSS] for MINUTE TO SECOND + * + * Note: the seconds fraction is truncated to microseconds. + * + * @param input The input string to parse. + * @param from The interval unit from which the input string begins. + * @param to The interval unit at where the input string ends. + * @return an instance of `CalendarInterval` if the input string was parsed successfully + * otherwise throws an exception. + * @throws IllegalArgumentException The input string has incorrect format and cannot be parsed. + * @throws ArithmeticException An interval unit value is out of valid range or the resulted + * interval fields `days` or `microseconds` are out of the valid + * ranges. + */ + private def parseDayTime( + input: String, + from: IntervalUnit, + to: IntervalUnit): CalendarInterval = { + require(input != null, "Interval day-time string must be not null") + val regexp = dayTimePattern.get(from -> to) + require(regexp.isDefined, s"Cannot support (interval '$input' $from to $to) expression") + val pattern = regexp.get.pattern + val m = pattern.matcher(input) + require(m.matches, s"Interval string must match day-time format of '$pattern': $input") + var micros: Long = 0L + var days: Int = 0 + unitsRange(to, from).foreach { + case unit @ DAY => + days = toLongWithRange(unit, m.group(unit.toString), 0, Int.MaxValue).toInt + case unit @ HOUR => + val parsed = toLongWithRange(unit, m.group(unit.toString), 0, 23) + micros = Math.addExact(micros, parsed * MICROS_PER_HOUR) + case unit @ MINUTE => + val parsed = toLongWithRange(unit, m.group(unit.toString), 0, 59) + micros = Math.addExact(micros, parsed * MICROS_PER_MINUTE) + case unit @ SECOND => + micros = Math.addExact(micros, parseSecondNano(m.group(unit.toString))) + case _ => + throw new IllegalArgumentException( + s"Cannot support (interval '$input' $from to $to) expression") + } + val sign = if (m.group("sign") != null && m.group("sign") == "-") -1 else 1 + new CalendarInterval(0, sign * days, sign * micros) + } + // Parses a string with nanoseconds, truncates the result and returns microseconds private def parseNanos(nanosStr: String, isNegative: Boolean): Long = { if (nanosStr != null) { @@ -237,6 +333,30 @@ object IntervalUtils { } } + /** + * Parse second_nano string in ss.nnnnnnnnn format to microseconds + */ + private def parseSecondNano(secondNano: String): Long = { + def parseSeconds(secondsStr: String): Long = { + toLongWithRange( + SECOND, + secondsStr, + Long.MinValue / MICROS_PER_SECOND, + Long.MaxValue / MICROS_PER_SECOND) * MICROS_PER_SECOND + } + + secondNano.split("\\.") match { + case Array(secondsStr) => parseSeconds(secondsStr) + case Array("", nanosStr) => parseNanos(nanosStr, false) + case Array(secondsStr, nanosStr) => + val seconds = parseSeconds(secondsStr) + Math.addExact(seconds, parseNanos(nanosStr, seconds < 0)) + case _ => + throw new IllegalArgumentException( + "Interval string does not match second-nano format of ss.nnnnnnnnn") + } + } + /** * Gets interval duration * diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala index f7c1d4a798ecb..c54008cf91942 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala @@ -2087,6 +2087,17 @@ object SQLConf { .stringConf .createWithDefault( "https://maven-central.storage-download.googleapis.com/repos/central/data/") + + val LEGACY_FROM_DAYTIME_STRING = + buildConf("spark.sql.legacy.fromDayTimeString.enabled") + .internal() + .doc("When true, the `from` bound is not taken into account in conversion of " + + "a day-time string to an interval, and the `to` bound is used to skip" + + "all interval units out of the specified range. If it is set to `false`, " + + "`ParseException` is thrown if the input does not match to the pattern " + + "defined by `from` and `to`.") + .booleanConf + .createWithDefault(false) } /** 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 90bb487ec6168..4dccada3d5546 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 @@ -716,7 +716,7 @@ class ExpressionParserSuite extends AnalysisTest { "0:0:0", "0:0:1") hourTimeValues.foreach { value => - val result = Literal(IntervalUtils.fromDayTimeString(value)) + val result = Literal(IntervalUtils.fromDayTimeString(value, HOUR, SECOND)) checkIntervals(s"'$value' hour to second", result) } 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 c98bb61b6ee7b..15ba5f03d0505 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 @@ -20,12 +20,14 @@ package org.apache.spark.sql.catalyst.util import java.util.concurrent.TimeUnit import org.apache.spark.SparkFunSuite +import org.apache.spark.sql.catalyst.plans.SQLHelper import org.apache.spark.sql.catalyst.util.DateTimeConstants._ import org.apache.spark.sql.catalyst.util.IntervalUtils._ import org.apache.spark.sql.catalyst.util.IntervalUtils.IntervalUnit._ +import org.apache.spark.sql.internal.SQLConf import org.apache.spark.unsafe.types.{CalendarInterval, UTF8String} -class IntervalUtilsSuite extends SparkFunSuite { +class IntervalUtilsSuite extends SparkFunSuite with SQLHelper { private def checkFromString(input: String, expected: CalendarInterval): Unit = { assert(stringToInterval(UTF8String.fromString(input)) === expected) @@ -160,43 +162,45 @@ class IntervalUtilsSuite extends SparkFunSuite { } } - test("from day-time string") { - assert(fromDayTimeString("5 12:40:30.999999999") === - new CalendarInterval( - 0, - 5, - 12 * MICROS_PER_HOUR + - 40 * MICROS_PER_MINUTE + - 30 * MICROS_PER_SECOND + 999999L)) - assert(fromDayTimeString("10 0:12:0.888") === - new CalendarInterval( - 0, - 10, - 12 * MICROS_PER_MINUTE + 888 * MICROS_PER_MILLIS)) - assert(fromDayTimeString("-3 0:0:0") === new CalendarInterval(0, -3, 0L)) - - try { - fromDayTimeString("5 30:12:20") - fail("Expected to throw an exception for the invalid input") - } catch { - case e: IllegalArgumentException => - assert(e.getMessage.contains("hour 30 outside range")) - } - - try { - fromDayTimeString("5 30-12") - fail("Expected to throw an exception for the invalid input") - } catch { - case e: IllegalArgumentException => - assert(e.getMessage.contains("must match day-time format")) - } - - try { - fromDayTimeString("5 1:12:20", HOUR, MICROSECOND) - fail("Expected to throw an exception for the invalid convention type") - } catch { - case e: IllegalArgumentException => - assert(e.getMessage.contains("Cannot support (interval")) + test("from day-time string - legacy") { + withSQLConf(SQLConf.LEGACY_FROM_DAYTIME_STRING.key -> "true") { + assert(fromDayTimeString("5 12:40:30.999999999") === + new CalendarInterval( + 0, + 5, + 12 * MICROS_PER_HOUR + + 40 * MICROS_PER_MINUTE + + 30 * MICROS_PER_SECOND + 999999L)) + assert(fromDayTimeString("10 0:12:0.888") === + new CalendarInterval( + 0, + 10, + 12 * MICROS_PER_MINUTE + 888 * MICROS_PER_MILLIS)) + assert(fromDayTimeString("-3 0:0:0") === new CalendarInterval(0, -3, 0L)) + + try { + fromDayTimeString("5 30:12:20") + fail("Expected to throw an exception for the invalid input") + } catch { + case e: IllegalArgumentException => + assert(e.getMessage.contains("hour 30 outside range")) + } + + try { + fromDayTimeString("5 30-12") + fail("Expected to throw an exception for the invalid input") + } catch { + case e: IllegalArgumentException => + assert(e.getMessage.contains("must match day-time format")) + } + + try { + fromDayTimeString("5 1:12:20", HOUR, MICROSECOND) + fail("Expected to throw an exception for the invalid convention type") + } catch { + case e: IllegalArgumentException => + assert(e.getMessage.contains("Cannot support (interval")) + } } } @@ -384,4 +388,61 @@ class IntervalUtilsSuite extends SparkFunSuite { val i9 = new CalendarInterval(0, 0, -3000 * MICROS_PER_HOUR) assert(IntervalUtils.toMultiUnitsString(i9) === "-3000 hours") } + + test("from day-time string") { + def check(input: String, from: IntervalUnit, to: IntervalUnit, expected: String): Unit = { + withClue(s"from = $from, to = $to") { + val expectedUtf8 = UTF8String.fromString(expected) + assert(fromDayTimeString(input, from, to) === safeStringToInterval(expectedUtf8)) + } + } + def checkFail( + input: String, + from: IntervalUnit, + to: IntervalUnit, + errMsg: String): Unit = { + try { + fromDayTimeString(input, from, to) + fail("Expected to throw an exception for the invalid input") + } catch { + case e: IllegalArgumentException => + assert(e.getMessage.contains(errMsg)) + } + } + + check("12:40", HOUR, MINUTE, "12 hours 40 minutes") + check("+12:40", HOUR, MINUTE, "12 hours 40 minutes") + check("-12:40", HOUR, MINUTE, "-12 hours -40 minutes") + checkFail("5 12:40", HOUR, MINUTE, "must match day-time format") + + check("12:40:30.999999999", HOUR, SECOND, "12 hours 40 minutes 30.999999 seconds") + check("+12:40:30.123456789", HOUR, SECOND, "12 hours 40 minutes 30.123456 seconds") + check("-12:40:30.123456789", HOUR, SECOND, "-12 hours -40 minutes -30.123456 seconds") + checkFail("5 12:40:30", HOUR, SECOND, "must match day-time format") + checkFail("12:40:30.0123456789", HOUR, SECOND, "must match day-time format") + + check("40:30.123456789", MINUTE, SECOND, "40 minutes 30.123456 seconds") + check("+40:30.123456789", MINUTE, SECOND, "40 minutes 30.123456 seconds") + check("-40:30.123456789", MINUTE, SECOND, "-40 minutes -30.123456 seconds") + checkFail("12:40:30", MINUTE, SECOND, "must match day-time format") + + check("5 12", DAY, HOUR, "5 days 12 hours") + check("+5 12", DAY, HOUR, "5 days 12 hours") + check("-5 12", DAY, HOUR, "-5 days -12 hours") + checkFail("5 12:30", DAY, HOUR, "must match day-time format") + + check("5 12:40", DAY, MINUTE, "5 days 12 hours 40 minutes") + check("+5 12:40", DAY, MINUTE, "5 days 12 hours 40 minutes") + check("-5 12:40", DAY, MINUTE, "-5 days -12 hours -40 minutes") + checkFail("5 12", DAY, MINUTE, "must match day-time format") + + check("5 12:40:30.123", DAY, SECOND, "5 days 12 hours 40 minutes 30.123 seconds") + check("+5 12:40:30.123456", DAY, SECOND, "5 days 12 hours 40 minutes 30.123456 seconds") + check("-5 12:40:30.123456789", DAY, SECOND, "-5 days -12 hours -40 minutes -30.123456 seconds") + checkFail("5 12", DAY, SECOND, "must match day-time format") + + checkFail("5 30:12:20", DAY, SECOND, "hour 30 outside range") + checkFail("5 30-12", DAY, SECOND, "must match day-time format") + checkFail("5 1:12:20", HOUR, MICROSECOND, "Cannot support (interval") + } } 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 5806d9288572f..5b5eaab225d28 100644 --- a/sql/core/src/test/resources/sql-tests/inputs/interval.sql +++ b/sql/core/src/test/resources/sql-tests/inputs/interval.sql @@ -97,17 +97,22 @@ select interval 1 year 2 month 3 week 4 day 5 hour 6 minute 7 seconds 8 millisec select interval '30' year '25' month '-100' day '40' hour '80' minute '299.889987299' second; select interval '0 0:0:0.1' day to second; select interval '10-9' year to month; +select interval '20 15' day to hour; +select interval '20 15:40' day to minute; +select interval '20 15:40:32.99899999' day to second; +select interval '15:40' hour to minute; +select interval '15:40:32.99899999' hour to second; +select interval '40:32.99899999' minute to second; +select interval '40:32' minute to second; +select interval 30 day day; + +-- invalid day-time string intervals select interval '20 15:40:32.99899999' day to hour; select interval '20 15:40:32.99899999' day to minute; -select interval '20 15:40:32.99899999' day to second; select interval '15:40:32.99899999' hour to minute; select interval '15:40.99899999' hour to second; select interval '15:40' hour to second; -select interval '15:40:32.99899999' hour to second; select interval '20 40:32.99899999' minute to second; -select interval '40:32.99899999' minute to second; -select interval '40:32' minute to second; -select interval 30 day day; -- ns is not supported select interval 10 nanoseconds; 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 2709fb42488cc..8c65c5ece7e54 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: 138 -- !query 0 @@ -517,7 +517,7 @@ struct -- !query 64 -select interval '20 15:40:32.99899999' day to hour +select interval '20 15' day to hour -- !query 64 schema struct -- !query 64 output @@ -525,7 +525,7 @@ struct -- !query 65 -select interval '20 15:40:32.99899999' day to minute +select interval '20 15:40' day to minute -- !query 65 schema struct -- !query 65 output @@ -541,7 +541,7 @@ struct -- !query 67 -select interval '15:40:32.99899999' hour to minute +select interval '15:40' hour to minute -- !query 67 schema struct -- !query 67 output @@ -549,74 +549,134 @@ struct -- !query 68 -select interval '15:40.99899999' hour to second +select interval '15:40:32.99899999' hour to second -- !query 68 schema -struct +struct -- !query 68 output -15 minutes 40.998999 seconds +15 hours 40 minutes 32.998999 seconds -- !query 69 -select interval '15:40' hour to second +select interval '40:32.99899999' minute to second -- !query 69 schema -struct +struct -- !query 69 output -15 hours 40 minutes +40 minutes 32.998999 seconds -- !query 70 -select interval '15:40:32.99899999' hour to second +select interval '40:32' minute to second -- !query 70 schema -struct +struct -- !query 70 output -15 hours 40 minutes 32.998999 seconds +40 minutes 32 seconds -- !query 71 -select interval '20 40:32.99899999' minute to second +select interval 30 day day -- !query 71 schema -struct +struct<> -- !query 71 output -20 days 40 minutes 32.998999 seconds +org.apache.spark.sql.catalyst.parser.ParseException + +no viable alternative at input 'day'(line 1, pos 23) + +== SQL == +select interval 30 day day +-----------------------^^^ -- !query 72 -select interval '40:32.99899999' minute to second +select interval '20 15:40:32.99899999' day to hour -- !query 72 schema -struct +struct<> -- !query 72 output -40 minutes 32.998999 seconds +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d+) (?\d{1,2})$': 20 15:40:32.99899999(line 1, pos 16) + +== SQL == +select interval '20 15:40:32.99899999' day to hour +----------------^^^ -- !query 73 -select interval '40:32' minute to second +select interval '20 15:40:32.99899999' day to minute -- !query 73 schema -struct +struct<> -- !query 73 output -40 minutes 32 seconds +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d+) (?\d{1,2}):(?\d{1,2})$': 20 15:40:32.99899999(line 1, pos 16) + +== SQL == +select interval '20 15:40:32.99899999' day to minute +----------------^^^ -- !query 74 -select interval 30 day day +select interval '15:40:32.99899999' hour to minute -- !query 74 schema struct<> -- !query 74 output org.apache.spark.sql.catalyst.parser.ParseException -no viable alternative at input 'day'(line 1, pos 23) +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?\d{1,2})$': 15:40:32.99899999(line 1, pos 16) == SQL == -select interval 30 day day ------------------------^^^ +select interval '15:40:32.99899999' hour to minute +----------------^^^ -- !query 75 -select interval 10 nanoseconds +select interval '15:40.99899999' hour to second -- !query 75 schema struct<> -- !query 75 output org.apache.spark.sql.catalyst.parser.ParseException +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?\d{1,2}):(?(\d{1,2})(\.(\d{1,9}))?)$': 15:40.99899999(line 1, pos 16) + +== SQL == +select interval '15:40.99899999' hour to second +----------------^^^ + + +-- !query 76 +select interval '15:40' hour to second +-- !query 76 schema +struct<> +-- !query 76 output +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?\d{1,2}):(?(\d{1,2})(\.(\d{1,9}))?)$': 15:40(line 1, pos 16) + +== SQL == +select interval '15:40' hour to second +----------------^^^ + + +-- !query 77 +select interval '20 40:32.99899999' minute to second +-- !query 77 schema +struct<> +-- !query 77 output +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?(\d{1,2})(\.(\d{1,9}))?)$': 20 40:32.99899999(line 1, pos 16) + +== SQL == +select interval '20 40:32.99899999' minute to second +----------------^^^ + + +-- !query 78 +select interval 10 nanoseconds +-- !query 78 schema +struct<> +-- !query 78 output +org.apache.spark.sql.catalyst.parser.ParseException + no viable alternative at input '10 nanoseconds'(line 1, pos 19) == SQL == @@ -624,35 +684,35 @@ select interval 10 nanoseconds -------------------^^^ --- !query 76 +-- !query 79 select map(1, interval 1 day, 2, interval 3 week) --- !query 76 schema +-- !query 79 schema struct> --- !query 76 output +-- !query 79 output {1:1 days,2:21 days} --- !query 77 +-- !query 80 select interval 'interval 3 year 1 hour' --- !query 77 schema +-- !query 80 schema struct --- !query 77 output +-- !query 80 output 3 years 1 hours --- !query 78 +-- !query 81 select interval '3 year 1 hour' --- !query 78 schema +-- !query 81 schema struct --- !query 78 output +-- !query 81 output 3 years 1 hours --- !query 79 +-- !query 82 select interval --- !query 79 schema +-- !query 82 schema struct<> --- !query 79 output +-- !query 82 output org.apache.spark.sql.catalyst.parser.ParseException at least one time unit should be given for interval literal(line 1, pos 7) @@ -662,11 +722,11 @@ select interval -------^^^ --- !query 80 +-- !query 83 select interval 1 fake_unit --- !query 80 schema +-- !query 83 schema struct<> --- !query 80 output +-- !query 83 output org.apache.spark.sql.catalyst.parser.ParseException no viable alternative at input '1 fake_unit'(line 1, pos 18) @@ -676,11 +736,11 @@ select interval 1 fake_unit ------------------^^^ --- !query 81 +-- !query 84 select interval 1 year to month --- !query 81 schema +-- !query 84 schema struct<> --- !query 81 output +-- !query 84 output org.apache.spark.sql.catalyst.parser.ParseException The value of from-to unit must be a string(line 1, pos 16) @@ -690,11 +750,11 @@ select interval 1 year to month ----------------^^^ --- !query 82 +-- !query 85 select interval '1' year to second --- !query 82 schema +-- !query 85 schema struct<> --- !query 82 output +-- !query 85 output org.apache.spark.sql.catalyst.parser.ParseException Intervals FROM year TO second are not supported.(line 1, pos 16) @@ -704,11 +764,11 @@ select interval '1' year to second ----------------^^^ --- !query 83 +-- !query 86 select interval '10-9' year to month '2-1' year to month --- !query 83 schema +-- !query 86 schema struct<> --- !query 83 output +-- !query 86 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 37) @@ -718,11 +778,11 @@ select interval '10-9' year to month '2-1' year to month -------------------------------------^^^ --- !query 84 +-- !query 87 select interval '10-9' year to month '12:11:10' hour to second --- !query 84 schema +-- !query 87 schema struct<> --- !query 84 output +-- !query 87 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 37) @@ -732,11 +792,11 @@ select interval '10-9' year to month '12:11:10' hour to second -------------------------------------^^^ --- !query 85 +-- !query 88 select interval '1 15:11' day to minute '12:11:10' hour to second --- !query 85 schema +-- !query 88 schema struct<> --- !query 85 output +-- !query 88 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 40) @@ -746,11 +806,11 @@ select interval '1 15:11' day to minute '12:11:10' hour to second ----------------------------------------^^^ --- !query 86 +-- !query 89 select interval 1 year '2-1' year to month --- !query 86 schema +-- !query 89 schema struct<> --- !query 86 output +-- !query 89 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 23) @@ -760,11 +820,11 @@ select interval 1 year '2-1' year to month -----------------------^^^ --- !query 87 +-- !query 90 select interval 1 year '12:11:10' hour to second --- !query 87 schema +-- !query 90 schema struct<> --- !query 87 output +-- !query 90 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 23) @@ -774,11 +834,11 @@ select interval 1 year '12:11:10' hour to second -----------------------^^^ --- !query 88 +-- !query 91 select interval '10-9' year to month '1' year --- !query 88 schema +-- !query 91 schema struct<> --- !query 88 output +-- !query 91 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 37) @@ -788,11 +848,11 @@ select interval '10-9' year to month '1' year -------------------------------------^^^ --- !query 89 +-- !query 92 select interval '12:11:10' hour to second '1' year --- !query 89 schema +-- !query 92 schema struct<> --- !query 89 output +-- !query 92 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 42) @@ -802,11 +862,11 @@ select interval '12:11:10' hour to second '1' year ------------------------------------------^^^ --- !query 90 +-- !query 93 select interval (-30) day --- !query 90 schema +-- !query 93 schema struct<> --- !query 90 output +-- !query 93 output org.apache.spark.sql.catalyst.parser.ParseException no viable alternative at input 'day'(line 1, pos 22) @@ -816,11 +876,11 @@ select interval (-30) day ----------------------^^^ --- !query 91 +-- !query 94 select interval (a + 1) day --- !query 91 schema +-- !query 94 schema struct<> --- !query 91 output +-- !query 94 output org.apache.spark.sql.catalyst.parser.ParseException no viable alternative at input 'day'(line 1, pos 24) @@ -830,11 +890,11 @@ select interval (a + 1) day ------------------------^^^ --- !query 92 +-- !query 95 select interval 30 day day day --- !query 92 schema +-- !query 95 schema struct<> --- !query 92 output +-- !query 95 output org.apache.spark.sql.catalyst.parser.ParseException no viable alternative at input 'day'(line 1, pos 23) @@ -844,192 +904,192 @@ select interval 30 day day day -----------------------^^^ --- !query 93 +-- !query 96 select sum(cast(null as interval)) --- !query 93 schema +-- !query 96 schema struct --- !query 93 output +-- !query 96 output NULL --- !query 94 +-- !query 97 select sum(cast(v as interval)) from VALUES ('1 seconds') t(v) where 1=0 --- !query 94 schema +-- !query 97 schema struct --- !query 94 output +-- !query 97 output NULL --- !query 95 +-- !query 98 select sum(cast(v as interval)) from VALUES ('1 seconds'), ('2 seconds'), (null) t(v) --- !query 95 schema +-- !query 98 schema struct --- !query 95 output +-- !query 98 output 3 seconds --- !query 96 +-- !query 99 select sum(cast(v as interval)) from VALUES ('-1 seconds'), ('2 seconds'), (null) t(v) --- !query 96 schema +-- !query 99 schema struct --- !query 96 output +-- !query 99 output 1 seconds --- !query 97 +-- !query 100 select sum(cast(v as interval)) from VALUES ('-1 seconds'), ('-2 seconds'), (null) t(v) --- !query 97 schema +-- !query 100 schema struct --- !query 97 output +-- !query 100 output -3 seconds --- !query 98 +-- !query 101 select sum(cast(v as interval)) from VALUES ('-1 weeks'), ('2 seconds'), (null) t(v) --- !query 98 schema +-- !query 101 schema struct --- !query 98 output +-- !query 101 output -7 days 2 seconds --- !query 99 +-- !query 102 select i, sum(cast(v as interval)) from VALUES (1, '-1 weeks'), (2, '2 seconds'), (3, null), (1, '5 days') t(i, v) group by i --- !query 99 schema +-- !query 102 schema struct --- !query 99 output +-- !query 102 output 1 -2 days 2 2 seconds 3 NULL --- !query 100 +-- !query 103 select sum(cast(v as interval)) as sv from VALUES (1, '-1 weeks'), (2, '2 seconds'), (3, null), (1, '5 days') t(i, v) having sv is not null --- !query 100 schema +-- !query 103 schema struct --- !query 100 output +-- !query 103 output -2 days 2 seconds --- !query 101 +-- !query 104 SELECT i, sum(cast(v as interval)) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM VALUES(1, '1 seconds'), (1, '2 seconds'), (2, NULL), (2, NULL) t(i,v) --- !query 101 schema +-- !query 104 schema struct --- !query 101 output +-- !query 104 output 1 2 seconds 1 3 seconds 2 NULL 2 NULL --- !query 102 +-- !query 105 select avg(cast(v as interval)) from VALUES (null) t(v) --- !query 102 schema +-- !query 105 schema struct --- !query 102 output +-- !query 105 output NULL --- !query 103 +-- !query 106 select avg(cast(v as interval)) from VALUES ('1 seconds'), ('2 seconds'), (null) t(v) where 1=0 --- !query 103 schema +-- !query 106 schema struct --- !query 103 output +-- !query 106 output NULL --- !query 104 +-- !query 107 select avg(cast(v as interval)) from VALUES ('1 seconds'), ('2 seconds'), (null) t(v) --- !query 104 schema +-- !query 107 schema struct --- !query 104 output +-- !query 107 output 1.5 seconds --- !query 105 +-- !query 108 select avg(cast(v as interval)) from VALUES ('-1 seconds'), ('2 seconds'), (null) t(v) --- !query 105 schema +-- !query 108 schema struct --- !query 105 output +-- !query 108 output 0.5 seconds --- !query 106 +-- !query 109 select avg(cast(v as interval)) from VALUES ('-1 seconds'), ('-2 seconds'), (null) t(v) --- !query 106 schema +-- !query 109 schema struct --- !query 106 output +-- !query 109 output -1.5 seconds --- !query 107 +-- !query 110 select avg(cast(v as interval)) from VALUES ('-1 weeks'), ('2 seconds'), (null) t(v) --- !query 107 schema +-- !query 110 schema struct --- !query 107 output +-- !query 110 output -3 days -11 hours -59 minutes -59 seconds --- !query 108 +-- !query 111 select i, avg(cast(v as interval)) from VALUES (1, '-1 weeks'), (2, '2 seconds'), (3, null), (1, '5 days') t(i, v) group by i --- !query 108 schema +-- !query 111 schema struct --- !query 108 output +-- !query 111 output 1 -1 days 2 2 seconds 3 NULL --- !query 109 +-- !query 112 select avg(cast(v as interval)) as sv from VALUES (1, '-1 weeks'), (2, '2 seconds'), (3, null), (1, '5 days') t(i, v) having sv is not null --- !query 109 schema +-- !query 112 schema struct --- !query 109 output +-- !query 112 output -15 hours -59 minutes -59.333333 seconds --- !query 110 +-- !query 113 SELECT i, avg(cast(v as interval)) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM VALUES (1,'1 seconds'), (1,'2 seconds'), (2,NULL), (2,NULL) t(i,v) --- !query 110 schema +-- !query 113 schema struct --- !query 110 output +-- !query 113 output 1 1.5 seconds 1 2 seconds 2 NULL 2 NULL --- !query 111 +-- !query 114 create temporary view interval_arithmetic as select CAST(dateval AS date), CAST(tsval AS timestamp) from values ('2012-01-01', '2012-01-01') as interval_arithmetic(dateval, tsval) --- !query 111 schema +-- !query 114 schema struct<> --- !query 111 output +-- !query 114 output --- !query 112 +-- !query 115 select dateval, dateval - interval '2-2' year to month, @@ -1039,13 +1099,13 @@ select - interval '2-2' year to month + dateval, interval '2-2' year to month + dateval from interval_arithmetic --- !query 112 schema +-- !query 115 schema struct --- !query 112 output +-- !query 115 output 2012-01-01 2009-11-01 2014-03-01 2014-03-01 2009-11-01 2009-11-01 2014-03-01 --- !query 113 +-- !query 116 select tsval, tsval - interval '2-2' year to month, @@ -1055,24 +1115,24 @@ select - interval '2-2' year to month + tsval, interval '2-2' year to month + tsval from interval_arithmetic --- !query 113 schema +-- !query 116 schema struct --- !query 113 output +-- !query 116 output 2012-01-01 00:00:00 2009-11-01 00:00:00 2014-03-01 00:00:00 2014-03-01 00:00:00 2009-11-01 00:00:00 2009-11-01 00:00:00 2014-03-01 00:00:00 --- !query 114 +-- !query 117 select interval '2-2' year to month + interval '3-3' year to month, interval '2-2' year to month - interval '3-3' year to month from interval_arithmetic --- !query 114 schema +-- !query 117 schema struct<(INTERVAL '2 years 2 months' + INTERVAL '3 years 3 months'):interval,(INTERVAL '2 years 2 months' - INTERVAL '3 years 3 months'):interval> --- !query 114 output +-- !query 117 output 5 years 5 months -1 years -1 months --- !query 115 +-- !query 118 select dateval, dateval - interval '99 11:22:33.123456789' day to second, @@ -1082,13 +1142,13 @@ select -interval '99 11:22:33.123456789' day to second + dateval, interval '99 11:22:33.123456789' day to second + dateval from interval_arithmetic --- !query 115 schema +-- !query 118 schema struct --- !query 115 output +-- !query 118 output 2012-01-01 2011-09-23 2012-04-09 2012-04-09 2011-09-23 2011-09-23 2012-04-09 --- !query 116 +-- !query 119 select tsval, tsval - interval '99 11:22:33.123456789' day to second, @@ -1098,92 +1158,92 @@ select -interval '99 11:22:33.123456789' day to second + tsval, interval '99 11:22:33.123456789' day to second + tsval from interval_arithmetic --- !query 116 schema +-- !query 119 schema struct --- !query 116 output +-- !query 119 output 2012-01-01 00:00:00 2011-09-23 12:37:26.876544 2012-04-09 11:22:33.123456 2012-04-09 11:22:33.123456 2011-09-23 12:37:26.876544 2011-09-23 12:37:26.876544 2012-04-09 11:22:33.123456 --- !query 117 +-- !query 120 select interval '99 11:22:33.123456789' day to second + interval '10 9:8:7.123456789' day to second, interval '99 11:22:33.123456789' day to second - interval '10 9:8:7.123456789' day to second from interval_arithmetic --- !query 117 schema +-- !query 120 schema struct<(INTERVAL '99 days 11 hours 22 minutes 33.123456 seconds' + INTERVAL '10 days 9 hours 8 minutes 7.123456 seconds'):interval,(INTERVAL '99 days 11 hours 22 minutes 33.123456 seconds' - INTERVAL '10 days 9 hours 8 minutes 7.123456 seconds'):interval> --- !query 117 output +-- !query 120 output 109 days 20 hours 30 minutes 40.246912 seconds 89 days 2 hours 14 minutes 26 seconds --- !query 118 +-- !query 121 select interval '\t interval 1 day' --- !query 118 schema +-- !query 121 schema struct --- !query 118 output +-- !query 121 output 1 days --- !query 119 +-- !query 122 select interval 'interval \t 1\tday' --- !query 119 schema +-- !query 122 schema struct --- !query 119 output +-- !query 122 output 1 days --- !query 120 +-- !query 123 select interval 'interval\t1\tday' --- !query 120 schema +-- !query 123 schema struct --- !query 120 output +-- !query 123 output 1 days --- !query 121 +-- !query 124 select interval '1\t' day --- !query 121 schema +-- !query 124 schema struct --- !query 121 output +-- !query 124 output 1 days --- !query 122 +-- !query 125 select interval '1 ' day --- !query 122 schema +-- !query 125 schema struct --- !query 122 output +-- !query 125 output 1 days --- !query 123 +-- !query 126 select 1 year 2 days --- !query 123 schema +-- !query 126 schema struct --- !query 123 output +-- !query 126 output 1 years 2 days --- !query 124 +-- !query 127 select '10-9' year to month --- !query 124 schema +-- !query 127 schema struct --- !query 124 output +-- !query 127 output 10 years 9 months --- !query 125 +-- !query 128 select '20 15:40:32.99899999' day to second --- !query 125 schema +-- !query 128 schema struct --- !query 125 output +-- !query 128 output 20 days 15 hours 40 minutes 32.998999 seconds --- !query 126 +-- !query 129 select 30 day day --- !query 126 schema +-- !query 129 schema struct<> --- !query 126 output +-- !query 129 output org.apache.spark.sql.catalyst.parser.ParseException no viable alternative at input 'day'(line 1, pos 14) @@ -1193,27 +1253,27 @@ select 30 day day --------------^^^ --- !query 127 +-- !query 130 select date'2012-01-01' - '2-2' year to month --- !query 127 schema +-- !query 130 schema struct --- !query 127 output +-- !query 130 output 2009-11-01 --- !query 128 +-- !query 131 select 1 month - 1 day --- !query 128 schema +-- !query 131 schema struct --- !query 128 output +-- !query 131 output 1 months -1 days --- !query 129 +-- !query 132 select 1 year to month --- !query 129 schema +-- !query 132 schema struct<> --- !query 129 output +-- !query 132 output org.apache.spark.sql.catalyst.parser.ParseException The value of from-to unit must be a string(line 1, pos 7) @@ -1223,11 +1283,11 @@ select 1 year to month -------^^^ --- !query 130 +-- !query 133 select '1' year to second --- !query 130 schema +-- !query 133 schema struct<> --- !query 130 output +-- !query 133 output org.apache.spark.sql.catalyst.parser.ParseException Intervals FROM year TO second are not supported.(line 1, pos 7) @@ -1237,11 +1297,11 @@ select '1' year to second -------^^^ --- !query 131 +-- !query 134 select 1 year '2-1' year to month --- !query 131 schema +-- !query 134 schema struct<> --- !query 131 output +-- !query 134 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 +1311,11 @@ select 1 year '2-1' year to month --------------^^^ --- !query 132 +-- !query 135 select (-30) day --- !query 132 schema +-- !query 135 schema struct<> --- !query 132 output +-- !query 135 output org.apache.spark.sql.catalyst.parser.ParseException no viable alternative at input 'day'(line 1, pos 13) @@ -1265,11 +1325,11 @@ select (-30) day -------------^^^ --- !query 133 +-- !query 136 select (a + 1) day --- !query 133 schema +-- !query 136 schema struct<> --- !query 133 output +-- !query 136 output org.apache.spark.sql.catalyst.parser.ParseException no viable alternative at input 'day'(line 1, pos 15) @@ -1279,11 +1339,11 @@ select (a + 1) day ---------------^^^ --- !query 134 +-- !query 137 select 30 day day day --- !query 134 schema +-- !query 137 schema struct<> --- !query 134 output +-- !query 137 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 601521ba43227..ff0a3ff74f1ec 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: 126 -- !query 0 @@ -517,7 +517,7 @@ struct -- !query 64 -select interval '20 15:40:32.99899999' day to hour +select interval '20 15' day to hour -- !query 64 schema struct -- !query 64 output @@ -525,7 +525,7 @@ struct -- !query 65 -select interval '20 15:40:32.99899999' day to minute +select interval '20 15:40' day to minute -- !query 65 schema struct -- !query 65 output @@ -541,7 +541,7 @@ struct -- !query 67 -select interval '15:40:32.99899999' hour to minute +select interval '15:40' hour to minute -- !query 67 schema struct -- !query 67 output @@ -549,68 +549,128 @@ struct -- !query 68 -select interval '15:40.99899999' hour to second +select interval '15:40:32.99899999' hour to second -- !query 68 schema -struct +struct -- !query 68 output -15 minutes 40.998999 seconds +15 hours 40 minutes 32.998999 seconds -- !query 69 -select interval '15:40' hour to second +select interval '40:32.99899999' minute to second -- !query 69 schema -struct +struct -- !query 69 output -15 hours 40 minutes +40 minutes 32.998999 seconds -- !query 70 -select interval '15:40:32.99899999' hour to second +select interval '40:32' minute to second -- !query 70 schema -struct +struct -- !query 70 output -15 hours 40 minutes 32.998999 seconds +40 minutes 32 seconds -- !query 71 -select interval '20 40:32.99899999' minute to second +select interval 30 day day -- !query 71 schema -struct +struct -- !query 71 output -20 days 40 minutes 32.998999 seconds +30 days -- !query 72 -select interval '40:32.99899999' minute to second +select interval '20 15:40:32.99899999' day to hour -- !query 72 schema -struct +struct<> -- !query 72 output -40 minutes 32.998999 seconds +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d+) (?\d{1,2})$': 20 15:40:32.99899999(line 1, pos 16) + +== SQL == +select interval '20 15:40:32.99899999' day to hour +----------------^^^ -- !query 73 -select interval '40:32' minute to second +select interval '20 15:40:32.99899999' day to minute -- !query 73 schema -struct +struct<> -- !query 73 output -40 minutes 32 seconds +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d+) (?\d{1,2}):(?\d{1,2})$': 20 15:40:32.99899999(line 1, pos 16) + +== SQL == +select interval '20 15:40:32.99899999' day to minute +----------------^^^ -- !query 74 -select interval 30 day day +select interval '15:40:32.99899999' hour to minute -- !query 74 schema -struct +struct<> -- !query 74 output -30 days +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?\d{1,2})$': 15:40:32.99899999(line 1, pos 16) + +== SQL == +select interval '15:40:32.99899999' hour to minute +----------------^^^ -- !query 75 -select interval 10 nanoseconds +select interval '15:40.99899999' hour to second -- !query 75 schema struct<> -- !query 75 output org.apache.spark.sql.catalyst.parser.ParseException +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?\d{1,2}):(?(\d{1,2})(\.(\d{1,9}))?)$': 15:40.99899999(line 1, pos 16) + +== SQL == +select interval '15:40.99899999' hour to second +----------------^^^ + + +-- !query 76 +select interval '15:40' hour to second +-- !query 76 schema +struct<> +-- !query 76 output +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?\d{1,2}):(?(\d{1,2})(\.(\d{1,9}))?)$': 15:40(line 1, pos 16) + +== SQL == +select interval '15:40' hour to second +----------------^^^ + + +-- !query 77 +select interval '20 40:32.99899999' minute to second +-- !query 77 schema +struct<> +-- !query 77 output +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?(\d{1,2})(\.(\d{1,9}))?)$': 20 40:32.99899999(line 1, pos 16) + +== SQL == +select interval '20 40:32.99899999' minute to second +----------------^^^ + + +-- !query 78 +select interval 10 nanoseconds +-- !query 78 schema +struct<> +-- !query 78 output +org.apache.spark.sql.catalyst.parser.ParseException + no viable alternative at input '10 nanoseconds'(line 1, pos 19) == SQL == @@ -618,35 +678,35 @@ select interval 10 nanoseconds -------------------^^^ --- !query 76 +-- !query 79 select map(1, interval 1 day, 2, interval 3 week) --- !query 76 schema +-- !query 79 schema struct> --- !query 76 output +-- !query 79 output {1:1 days,2:21 days} --- !query 77 +-- !query 80 select interval 'interval 3 year 1 hour' --- !query 77 schema +-- !query 80 schema struct --- !query 77 output +-- !query 80 output 3 years 1 hours --- !query 78 +-- !query 81 select interval '3 year 1 hour' --- !query 78 schema +-- !query 81 schema struct --- !query 78 output +-- !query 81 output 3 years 1 hours --- !query 79 +-- !query 82 select interval --- !query 79 schema +-- !query 82 schema struct<> --- !query 79 output +-- !query 82 output org.apache.spark.sql.catalyst.parser.ParseException at least one time unit should be given for interval literal(line 1, pos 7) @@ -656,11 +716,11 @@ select interval -------^^^ --- !query 80 +-- !query 83 select interval 1 fake_unit --- !query 80 schema +-- !query 83 schema struct<> --- !query 80 output +-- !query 83 output org.apache.spark.sql.catalyst.parser.ParseException no viable alternative at input '1 fake_unit'(line 1, pos 18) @@ -670,11 +730,11 @@ select interval 1 fake_unit ------------------^^^ --- !query 81 +-- !query 84 select interval 1 year to month --- !query 81 schema +-- !query 84 schema struct<> --- !query 81 output +-- !query 84 output org.apache.spark.sql.catalyst.parser.ParseException The value of from-to unit must be a string(line 1, pos 16) @@ -684,11 +744,11 @@ select interval 1 year to month ----------------^^^ --- !query 82 +-- !query 85 select interval '1' year to second --- !query 82 schema +-- !query 85 schema struct<> --- !query 82 output +-- !query 85 output org.apache.spark.sql.catalyst.parser.ParseException Intervals FROM year TO second are not supported.(line 1, pos 16) @@ -698,11 +758,11 @@ select interval '1' year to second ----------------^^^ --- !query 83 +-- !query 86 select interval '10-9' year to month '2-1' year to month --- !query 83 schema +-- !query 86 schema struct<> --- !query 83 output +-- !query 86 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 37) @@ -712,11 +772,11 @@ select interval '10-9' year to month '2-1' year to month -------------------------------------^^^ --- !query 84 +-- !query 87 select interval '10-9' year to month '12:11:10' hour to second --- !query 84 schema +-- !query 87 schema struct<> --- !query 84 output +-- !query 87 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 37) @@ -726,11 +786,11 @@ select interval '10-9' year to month '12:11:10' hour to second -------------------------------------^^^ --- !query 85 +-- !query 88 select interval '1 15:11' day to minute '12:11:10' hour to second --- !query 85 schema +-- !query 88 schema struct<> --- !query 85 output +-- !query 88 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 40) @@ -740,11 +800,11 @@ select interval '1 15:11' day to minute '12:11:10' hour to second ----------------------------------------^^^ --- !query 86 +-- !query 89 select interval 1 year '2-1' year to month --- !query 86 schema +-- !query 89 schema struct<> --- !query 86 output +-- !query 89 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 23) @@ -754,11 +814,11 @@ select interval 1 year '2-1' year to month -----------------------^^^ --- !query 87 +-- !query 90 select interval 1 year '12:11:10' hour to second --- !query 87 schema +-- !query 90 schema struct<> --- !query 87 output +-- !query 90 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 23) @@ -768,11 +828,11 @@ select interval 1 year '12:11:10' hour to second -----------------------^^^ --- !query 88 +-- !query 91 select interval '10-9' year to month '1' year --- !query 88 schema +-- !query 91 schema struct<> --- !query 88 output +-- !query 91 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 37) @@ -782,11 +842,11 @@ select interval '10-9' year to month '1' year -------------------------------------^^^ --- !query 89 +-- !query 92 select interval '12:11:10' hour to second '1' year --- !query 89 schema +-- !query 92 schema struct<> --- !query 89 output +-- !query 92 output org.apache.spark.sql.catalyst.parser.ParseException Can only have a single from-to unit in the interval literal syntax(line 1, pos 42) @@ -796,29 +856,29 @@ select interval '12:11:10' hour to second '1' year ------------------------------------------^^^ --- !query 90 +-- !query 93 select interval (-30) day --- !query 90 schema +-- !query 93 schema struct<> --- !query 90 output +-- !query 93 output org.apache.spark.sql.AnalysisException Undefined function: 'interval'. This function is neither a registered temporary function nor a permanent function registered in the database 'default'.; line 1 pos 7 --- !query 91 +-- !query 94 select interval (a + 1) day --- !query 91 schema +-- !query 94 schema struct<> --- !query 91 output +-- !query 94 output org.apache.spark.sql.AnalysisException Undefined function: 'interval'. This function is neither a registered temporary function nor a permanent function registered in the database 'default'.; line 1 pos 7 --- !query 92 +-- !query 95 select interval 30 day day day --- !query 92 schema +-- !query 95 schema struct<> --- !query 92 output +-- !query 95 output org.apache.spark.sql.catalyst.parser.ParseException extraneous input 'day' expecting (line 1, pos 27) @@ -828,192 +888,192 @@ select interval 30 day day day ---------------------------^^^ --- !query 93 +-- !query 96 select sum(cast(null as interval)) --- !query 93 schema +-- !query 96 schema struct --- !query 93 output +-- !query 96 output NULL --- !query 94 +-- !query 97 select sum(cast(v as interval)) from VALUES ('1 seconds') t(v) where 1=0 --- !query 94 schema +-- !query 97 schema struct --- !query 94 output +-- !query 97 output NULL --- !query 95 +-- !query 98 select sum(cast(v as interval)) from VALUES ('1 seconds'), ('2 seconds'), (null) t(v) --- !query 95 schema +-- !query 98 schema struct --- !query 95 output +-- !query 98 output 3 seconds --- !query 96 +-- !query 99 select sum(cast(v as interval)) from VALUES ('-1 seconds'), ('2 seconds'), (null) t(v) --- !query 96 schema +-- !query 99 schema struct --- !query 96 output +-- !query 99 output 1 seconds --- !query 97 +-- !query 100 select sum(cast(v as interval)) from VALUES ('-1 seconds'), ('-2 seconds'), (null) t(v) --- !query 97 schema +-- !query 100 schema struct --- !query 97 output +-- !query 100 output -3 seconds --- !query 98 +-- !query 101 select sum(cast(v as interval)) from VALUES ('-1 weeks'), ('2 seconds'), (null) t(v) --- !query 98 schema +-- !query 101 schema struct --- !query 98 output +-- !query 101 output -7 days 2 seconds --- !query 99 +-- !query 102 select i, sum(cast(v as interval)) from VALUES (1, '-1 weeks'), (2, '2 seconds'), (3, null), (1, '5 days') t(i, v) group by i --- !query 99 schema +-- !query 102 schema struct --- !query 99 output +-- !query 102 output 1 -2 days 2 2 seconds 3 NULL --- !query 100 +-- !query 103 select sum(cast(v as interval)) as sv from VALUES (1, '-1 weeks'), (2, '2 seconds'), (3, null), (1, '5 days') t(i, v) having sv is not null --- !query 100 schema +-- !query 103 schema struct --- !query 100 output +-- !query 103 output -2 days 2 seconds --- !query 101 +-- !query 104 SELECT i, sum(cast(v as interval)) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM VALUES(1, '1 seconds'), (1, '2 seconds'), (2, NULL), (2, NULL) t(i,v) --- !query 101 schema +-- !query 104 schema struct --- !query 101 output +-- !query 104 output 1 2 seconds 1 3 seconds 2 NULL 2 NULL --- !query 102 +-- !query 105 select avg(cast(v as interval)) from VALUES (null) t(v) --- !query 102 schema +-- !query 105 schema struct --- !query 102 output +-- !query 105 output NULL --- !query 103 +-- !query 106 select avg(cast(v as interval)) from VALUES ('1 seconds'), ('2 seconds'), (null) t(v) where 1=0 --- !query 103 schema +-- !query 106 schema struct --- !query 103 output +-- !query 106 output NULL --- !query 104 +-- !query 107 select avg(cast(v as interval)) from VALUES ('1 seconds'), ('2 seconds'), (null) t(v) --- !query 104 schema +-- !query 107 schema struct --- !query 104 output +-- !query 107 output 1.5 seconds --- !query 105 +-- !query 108 select avg(cast(v as interval)) from VALUES ('-1 seconds'), ('2 seconds'), (null) t(v) --- !query 105 schema +-- !query 108 schema struct --- !query 105 output +-- !query 108 output 0.5 seconds --- !query 106 +-- !query 109 select avg(cast(v as interval)) from VALUES ('-1 seconds'), ('-2 seconds'), (null) t(v) --- !query 106 schema +-- !query 109 schema struct --- !query 106 output +-- !query 109 output -1.5 seconds --- !query 107 +-- !query 110 select avg(cast(v as interval)) from VALUES ('-1 weeks'), ('2 seconds'), (null) t(v) --- !query 107 schema +-- !query 110 schema struct --- !query 107 output +-- !query 110 output -3 days -11 hours -59 minutes -59 seconds --- !query 108 +-- !query 111 select i, avg(cast(v as interval)) from VALUES (1, '-1 weeks'), (2, '2 seconds'), (3, null), (1, '5 days') t(i, v) group by i --- !query 108 schema +-- !query 111 schema struct --- !query 108 output +-- !query 111 output 1 -1 days 2 2 seconds 3 NULL --- !query 109 +-- !query 112 select avg(cast(v as interval)) as sv from VALUES (1, '-1 weeks'), (2, '2 seconds'), (3, null), (1, '5 days') t(i, v) having sv is not null --- !query 109 schema +-- !query 112 schema struct --- !query 109 output +-- !query 112 output -15 hours -59 minutes -59.333333 seconds --- !query 110 +-- !query 113 SELECT i, avg(cast(v as interval)) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM VALUES (1,'1 seconds'), (1,'2 seconds'), (2,NULL), (2,NULL) t(i,v) --- !query 110 schema +-- !query 113 schema struct --- !query 110 output +-- !query 113 output 1 1.5 seconds 1 2 seconds 2 NULL 2 NULL --- !query 111 +-- !query 114 create temporary view interval_arithmetic as select CAST(dateval AS date), CAST(tsval AS timestamp) from values ('2012-01-01', '2012-01-01') as interval_arithmetic(dateval, tsval) --- !query 111 schema +-- !query 114 schema struct<> --- !query 111 output +-- !query 114 output --- !query 112 +-- !query 115 select dateval, dateval - interval '2-2' year to month, @@ -1023,13 +1083,13 @@ select - interval '2-2' year to month + dateval, interval '2-2' year to month + dateval from interval_arithmetic --- !query 112 schema +-- !query 115 schema struct --- !query 112 output +-- !query 115 output 2012-01-01 2009-11-01 2014-03-01 2014-03-01 2009-11-01 2009-11-01 2014-03-01 --- !query 113 +-- !query 116 select tsval, tsval - interval '2-2' year to month, @@ -1039,24 +1099,24 @@ select - interval '2-2' year to month + tsval, interval '2-2' year to month + tsval from interval_arithmetic --- !query 113 schema +-- !query 116 schema struct --- !query 113 output +-- !query 116 output 2012-01-01 00:00:00 2009-11-01 00:00:00 2014-03-01 00:00:00 2014-03-01 00:00:00 2009-11-01 00:00:00 2009-11-01 00:00:00 2014-03-01 00:00:00 --- !query 114 +-- !query 117 select interval '2-2' year to month + interval '3-3' year to month, interval '2-2' year to month - interval '3-3' year to month from interval_arithmetic --- !query 114 schema +-- !query 117 schema struct<(INTERVAL '2 years 2 months' + INTERVAL '3 years 3 months'):interval,(INTERVAL '2 years 2 months' - INTERVAL '3 years 3 months'):interval> --- !query 114 output +-- !query 117 output 5 years 5 months -1 years -1 months --- !query 115 +-- !query 118 select dateval, dateval - interval '99 11:22:33.123456789' day to second, @@ -1066,13 +1126,13 @@ select -interval '99 11:22:33.123456789' day to second + dateval, interval '99 11:22:33.123456789' day to second + dateval from interval_arithmetic --- !query 115 schema +-- !query 118 schema struct --- !query 115 output +-- !query 118 output 2012-01-01 2011-09-23 2012-04-09 2012-04-09 2011-09-23 2011-09-23 2012-04-09 --- !query 116 +-- !query 119 select tsval, tsval - interval '99 11:22:33.123456789' day to second, @@ -1082,58 +1142,58 @@ select -interval '99 11:22:33.123456789' day to second + tsval, interval '99 11:22:33.123456789' day to second + tsval from interval_arithmetic --- !query 116 schema +-- !query 119 schema struct --- !query 116 output +-- !query 119 output 2012-01-01 00:00:00 2011-09-23 12:37:26.876544 2012-04-09 11:22:33.123456 2012-04-09 11:22:33.123456 2011-09-23 12:37:26.876544 2011-09-23 12:37:26.876544 2012-04-09 11:22:33.123456 --- !query 117 +-- !query 120 select interval '99 11:22:33.123456789' day to second + interval '10 9:8:7.123456789' day to second, interval '99 11:22:33.123456789' day to second - interval '10 9:8:7.123456789' day to second from interval_arithmetic --- !query 117 schema +-- !query 120 schema struct<(INTERVAL '99 days 11 hours 22 minutes 33.123456 seconds' + INTERVAL '10 days 9 hours 8 minutes 7.123456 seconds'):interval,(INTERVAL '99 days 11 hours 22 minutes 33.123456 seconds' - INTERVAL '10 days 9 hours 8 minutes 7.123456 seconds'):interval> --- !query 117 output +-- !query 120 output 109 days 20 hours 30 minutes 40.246912 seconds 89 days 2 hours 14 minutes 26 seconds --- !query 118 +-- !query 121 select interval '\t interval 1 day' --- !query 118 schema +-- !query 121 schema struct --- !query 118 output +-- !query 121 output 1 days --- !query 119 +-- !query 122 select interval 'interval \t 1\tday' --- !query 119 schema +-- !query 122 schema struct --- !query 119 output +-- !query 122 output 1 days --- !query 120 +-- !query 123 select interval 'interval\t1\tday' --- !query 120 schema +-- !query 123 schema struct --- !query 120 output +-- !query 123 output 1 days --- !query 121 +-- !query 124 select interval '1\t' day --- !query 121 schema +-- !query 124 schema struct --- !query 121 output +-- !query 124 output 1 days --- !query 122 +-- !query 125 select interval '1 ' day --- !query 122 schema +-- !query 125 schema struct --- !query 122 output +-- !query 125 output 1 days diff --git a/sql/core/src/test/resources/sql-tests/results/postgreSQL/interval.sql.out b/sql/core/src/test/resources/sql-tests/results/postgreSQL/interval.sql.out index f23415a108ff0..bf911dd3fbe6b 100644 --- a/sql/core/src/test/resources/sql-tests/results/postgreSQL/interval.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/postgreSQL/interval.sql.out @@ -125,17 +125,29 @@ struct -- !query 15 SELECT interval '1 2:03' day to hour -- !query 15 schema -struct +struct<> -- !query 15 output -1 days 2 hours +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d+) (?\d{1,2})$': 1 2:03(line 1, pos 16) + +== SQL == +SELECT interval '1 2:03' day to hour +----------------^^^ -- !query 16 SELECT interval '1 2:03:04' day to hour -- !query 16 schema -struct +struct<> -- !query 16 output -1 days 2 hours +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d+) (?\d{1,2})$': 1 2:03:04(line 1, pos 16) + +== SQL == +SELECT interval '1 2:03:04' day to hour +----------------^^^ -- !query 17 @@ -149,17 +161,29 @@ struct -- !query 18 SELECT interval '1 2:03:04' day to minute -- !query 18 schema -struct +struct<> -- !query 18 output -1 days 2 hours 3 minutes +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d+) (?\d{1,2}):(?\d{1,2})$': 1 2:03:04(line 1, pos 16) + +== SQL == +SELECT interval '1 2:03:04' day to minute +----------------^^^ -- !query 19 SELECT interval '1 2:03' day to second -- !query 19 schema -struct +struct<> -- !query 19 output -1 days 2 hours 3 minutes +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d+) (?\d{1,2}):(?\d{1,2}):(?(\d{1,2})(\.(\d{1,9}))?)$': 1 2:03(line 1, pos 16) + +== SQL == +SELECT interval '1 2:03' day to second +----------------^^^ -- !query 20 @@ -173,49 +197,85 @@ struct -- !query 21 SELECT interval '1 2:03' hour to minute -- !query 21 schema -struct +struct<> -- !query 21 output -1 days 2 hours 3 minutes +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?\d{1,2})$': 1 2:03(line 1, pos 16) + +== SQL == +SELECT interval '1 2:03' hour to minute +----------------^^^ -- !query 22 SELECT interval '1 2:03:04' hour to minute -- !query 22 schema -struct +struct<> -- !query 22 output -1 days 2 hours 3 minutes +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?\d{1,2})$': 1 2:03:04(line 1, pos 16) + +== SQL == +SELECT interval '1 2:03:04' hour to minute +----------------^^^ -- !query 23 SELECT interval '1 2:03' hour to second -- !query 23 schema -struct +struct<> -- !query 23 output -1 days 2 hours 3 minutes +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?\d{1,2}):(?(\d{1,2})(\.(\d{1,9}))?)$': 1 2:03(line 1, pos 16) + +== SQL == +SELECT interval '1 2:03' hour to second +----------------^^^ -- !query 24 SELECT interval '1 2:03:04' hour to second -- !query 24 schema -struct +struct<> -- !query 24 output -1 days 2 hours 3 minutes 4 seconds +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?\d{1,2}):(?(\d{1,2})(\.(\d{1,9}))?)$': 1 2:03:04(line 1, pos 16) + +== SQL == +SELECT interval '1 2:03:04' hour to second +----------------^^^ -- !query 25 SELECT interval '1 2:03' minute to second -- !query 25 schema -struct +struct<> -- !query 25 output -1 days 2 minutes 3 seconds +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?(\d{1,2})(\.(\d{1,9}))?)$': 1 2:03(line 1, pos 16) + +== SQL == +SELECT interval '1 2:03' minute to second +----------------^^^ -- !query 26 SELECT interval '1 2:03:04' minute to second -- !query 26 schema -struct +struct<> -- !query 26 output -1 days 2 hours 3 minutes 4 seconds +org.apache.spark.sql.catalyst.parser.ParseException + +requirement failed: Interval string must match day-time format of '^(?[+|-])?(?\d{1,2}):(?(\d{1,2})(\.(\d{1,9}))?)$': 1 2:03:04(line 1, pos 16) + +== SQL == +SELECT interval '1 2:03:04' minute to second +----------------^^^ -- !query 27