This is an automated email from the ASF dual-hosted git repository.

wenchen pushed a commit to branch branch-3.0
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/branch-3.0 by this push:
     new fcfac8f  [SPARK-31527][SQL] date add/subtract interval only allow 
those day precision in ansi mode
fcfac8f is described below

commit fcfac8f672ba6c8e49350f2c5fdd957584255327
Author: Kent Yao <[email protected]>
AuthorDate: Mon Apr 27 05:28:46 2020 +0000

    [SPARK-31527][SQL] date add/subtract interval only allow those day 
precision in ansi mode
    
    To follow ANSI,the expressions - `date + interval`, `interval + date` and 
`date - interval` should only accept intervals which the `microseconds` part is 
0.
    
    Better ANSI compliance
    
    No, this PR should target 3.0.0 in which this feature is newly added.
    
    add more unit tests
    
    Closes #28310 from yaooqinn/SPARK-31527.
    
    Authored-by: Kent Yao <[email protected]>
    Signed-off-by: Wenchen Fan <[email protected]>
    (cherry picked from commit ebc8fa50d0422f3db47b2c45025c7f2efe6ee39a)
    Signed-off-by: Wenchen Fan <[email protected]>
---
 .../spark/sql/catalyst/analysis/Analyzer.scala     | 27 ++++++----
 .../catalyst/expressions/datetimeExpressions.scala | 63 ++++++++++++++++++++++
 .../spark/sql/catalyst/util/DateTimeUtils.scala    | 16 ++++++
 .../expressions/DateExpressionsSuite.scala         | 36 ++++++++++++-
 .../expressions/ExpressionSQLBuilderSuite.scala    |  4 ++
 .../sql/catalyst/util/DateTimeUtilsSuite.scala     | 10 +++-
 .../resources/sql-tests/inputs/ansi/datetime.sql   |  1 +
 .../sql-tests/results/{ => ansi}/datetime.sql.out  | 56 ++++++++++++++-----
 .../sql-tests/results/ansi/interval.sql.out        |  7 +--
 .../resources/sql-tests/results/datetime.sql.out   |  4 +-
 .../resources/sql-tests/results/interval.sql.out   |  4 +-
 .../typeCoercion/native/dateTimeOperations.sql.out |  6 +--
 12 files changed, 198 insertions(+), 36 deletions(-)

diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala
index e4be634..6de3189 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala
@@ -246,7 +246,7 @@ class Analyzer(
       ResolveLambdaVariables(conf) ::
       ResolveTimeZone(conf) ::
       ResolveRandomSeed ::
-      ResolveBinaryArithmetic(conf) ::
+      ResolveBinaryArithmetic ::
       TypeCoercion.typeCoercionRules(conf) ++
       extendedResolutionRules : _*),
     Batch("Post-Hoc Resolution", Once, postHocResolutionRules: _*),
@@ -268,17 +268,21 @@ class Analyzer(
   /**
    * For [[Add]]:
    * 1. if both side are interval, stays the same;
-   * 2. else if one side is interval, turns it to [[TimeAdd]];
-   * 3. else if one side is date, turns it to [[DateAdd]] ;
-   * 4. else stays the same.
+   * 2. else if one side is date and the other is interval,
+   *    turns it to [[DateAddInterval]];
+   * 3. else if one side is interval, turns it to [[TimeAdd]];
+   * 4. else if one side is date, turns it to [[DateAdd]] ;
+   * 5. else stays the same.
    *
    * For [[Subtract]]:
    * 1. if both side are interval, stays the same;
-   * 2. else if the right side is an interval, turns it to [[TimeSub]];
-   * 3. else if one side is timestamp, turns it to [[SubtractTimestamps]];
-   * 4. else if the right side is date, turns it to 
[[DateDiff]]/[[SubtractDates]];
-   * 5. else if the left side is date, turns it to [[DateSub]];
-   * 6. else turns it to stays the same.
+   * 2. else if the left side is date and the right side is interval,
+   *    turns it to [[DateAddInterval(l, -r)]];
+   * 3. else if the right side is an interval, turns it to [[TimeSub]];
+   * 4. else if one side is timestamp, turns it to [[SubtractTimestamps]];
+   * 5. else if the right side is date, turns it to 
[[DateDiff]]/[[SubtractDates]];
+   * 6. else if the left side is date, turns it to [[DateSub]];
+   * 7. else turns it to stays the same.
    *
    * For [[Multiply]]:
    * 1. If one side is interval, turns it to [[MultiplyInterval]];
@@ -288,12 +292,14 @@ class Analyzer(
    * 1. If the left side is interval, turns it to [[DivideInterval]];
    * 2. otherwise, stays the same.
    */
-  case class ResolveBinaryArithmetic(conf: SQLConf) extends Rule[LogicalPlan] {
+  object ResolveBinaryArithmetic extends Rule[LogicalPlan] {
     override def apply(plan: LogicalPlan): LogicalPlan = 
plan.resolveOperatorsUp {
       case p: LogicalPlan => p.transformExpressionsUp {
         case a @ Add(l, r) if a.childrenResolved => (l.dataType, r.dataType) 
match {
           case (CalendarIntervalType, CalendarIntervalType) => a
+          case (DateType, CalendarIntervalType) => DateAddInterval(l, r)
           case (_, CalendarIntervalType) => Cast(TimeAdd(l, r), l.dataType)
+          case (CalendarIntervalType, DateType) => DateAddInterval(r, l)
           case (CalendarIntervalType, _) => Cast(TimeAdd(r, l), r.dataType)
           case (DateType, dt) if dt != StringType => DateAdd(l, r)
           case (dt, DateType) if dt != StringType => DateAdd(r, l)
@@ -301,6 +307,7 @@ class Analyzer(
         }
         case s @ Subtract(l, r) if s.childrenResolved => (l.dataType, 
r.dataType) match {
           case (CalendarIntervalType, CalendarIntervalType) => s
+          case (DateType, CalendarIntervalType) => DateAddInterval(l, 
UnaryMinus(r))
           case (_, CalendarIntervalType) => Cast(TimeSub(l, r), l.dataType)
           case (TimestampType, _) => SubtractTimestamps(l, r)
           case (_, TimestampType) => SubtractTimestamps(l, r)
diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/datetimeExpressions.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/datetimeExpressions.scala
index 8f57421..6e95f64 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/datetimeExpressions.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/datetimeExpressions.scala
@@ -35,6 +35,7 @@ import org.apache.spark.sql.catalyst.util.{DateTimeUtils, 
LegacyDateFormats, Tim
 import org.apache.spark.sql.catalyst.util.DateTimeConstants._
 import org.apache.spark.sql.catalyst.util.DateTimeUtils._
 import org.apache.spark.sql.catalyst.util.LegacyDateFormats.SIMPLE_DATE_FORMAT
+import org.apache.spark.sql.internal.SQLConf
 import org.apache.spark.sql.types._
 import org.apache.spark.unsafe.types.{CalendarInterval, UTF8String}
 
@@ -1196,6 +1197,68 @@ case class TimeAdd(start: Expression, interval: 
Expression, timeZoneId: Option[S
 }
 
 /**
+ * Adds date and an interval.
+ *
+ * When ansi mode is on, the microseconds part of interval needs to be 0, 
otherwise a runtime
+ * [[IllegalArgumentException]] will be raised.
+ * When ansi mode is off, if the microseconds part of interval is 0, we 
perform date + interval
+ * for better performance. if the microseconds part is not 0, then the date 
will be converted to a
+ * timestamp to add with the whole interval parts.
+ */
+case class DateAddInterval(
+    start: Expression,
+    interval: Expression,
+    timeZoneId: Option[String] = None,
+    ansiEnabled: Boolean = SQLConf.get.ansiEnabled)
+  extends BinaryExpression with ExpectsInputTypes with TimeZoneAwareExpression 
{
+
+  override def left: Expression = start
+  override def right: Expression = interval
+
+  override def toString: String = s"$left + $right"
+  override def sql: String = s"${left.sql} + ${right.sql}"
+  override def inputTypes: Seq[AbstractDataType] = Seq(DateType, 
CalendarIntervalType)
+
+  override def dataType: DataType = DateType
+
+  override def nullSafeEval(start: Any, interval: Any): Any = {
+    val itvl = interval.asInstanceOf[CalendarInterval]
+    if (ansiEnabled || itvl.microseconds == 0) {
+      DateTimeUtils.dateAddInterval(start.asInstanceOf[Int], itvl)
+    } else {
+      val startTs = DateTimeUtils.epochDaysToMicros(start.asInstanceOf[Int], 
zoneId)
+      val resultTs = DateTimeUtils.timestampAddInterval(
+        startTs, itvl.months, itvl.days, itvl.microseconds, zoneId)
+      DateTimeUtils.microsToEpochDays(resultTs, zoneId)
+    }
+  }
+
+  override def doGenCode(ctx: CodegenContext, ev: ExprCode): ExprCode = {
+    val dtu = DateTimeUtils.getClass.getName.stripSuffix("$")
+    nullSafeCodeGen(ctx, ev, (sd, i) => if (ansiEnabled) {
+      s"""${ev.value} = $dtu.dateAddInterval($sd, $i);"""
+    } else {
+      val zid = ctx.addReferenceObj("zoneId", zoneId, classOf[ZoneId].getName)
+      val startTs = ctx.freshName("startTs")
+      val resultTs = ctx.freshName("resultTs")
+      s"""
+         |if ($i.microseconds == 0) {
+         |  ${ev.value} = $dtu.dateAddInterval($sd, $i);
+         |} else {
+         |  long $startTs = $dtu.epochDaysToMicros($sd, $zid);
+         |  long $resultTs =
+         |    $dtu.timestampAddInterval($startTs, $i.months, $i.days, 
$i.microseconds, $zid);
+         |  ${ev.value} = $dtu.microsToEpochDays($resultTs, $zid);
+         |}
+         |""".stripMargin
+    })
+  }
+
+  override def withTimeZone(timeZoneId: String): TimeZoneAwareExpression =
+    copy(timeZoneId = Option(timeZoneId))
+}
+
+/**
  * This is a common function for databases supporting TIMESTAMP WITHOUT 
TIMEZONE. This function
  * takes a timestamp which is timezone-agnostic, and interprets it as a 
timestamp in UTC, and
  * renders that timestamp as a timestamp in the given time zone.
diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala
index a2fa87a..fb7875d 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala
@@ -619,6 +619,22 @@ object DateTimeUtils {
   }
 
   /**
+   * Add the date and the interval's months and days.
+   * Returns a date value, expressed in days since 1.1.1970.
+   *
+   * @throws DateTimeException if the result exceeds the supported date range
+   * @throws IllegalArgumentException if the interval has `microseconds` part
+   */
+  def dateAddInterval(
+     start: SQLDate,
+     interval: CalendarInterval): SQLDate = {
+    require(interval.microseconds == 0,
+      "Cannot add hours, minutes or seconds, milliseconds, microseconds to a 
date")
+    val ld = 
LocalDate.ofEpochDay(start).plusMonths(interval.months).plusDays(interval.days)
+    localDateToDays(ld)
+  }
+
+  /**
    * Returns number of months between time1 and time2. time1 and time2 are 
expressed in
    * microseconds since 1.1.1970. If time1 is later than time2, the result is 
positive.
    *
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala
index 1d01f4b..dd5a532 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala
@@ -27,7 +27,7 @@ import org.apache.spark.{SparkFunSuite, SparkUpgradeException}
 import org.apache.spark.sql.catalyst.InternalRow
 import 
org.apache.spark.sql.catalyst.expressions.codegen.GenerateUnsafeProjection
 import org.apache.spark.sql.catalyst.util.{DateTimeUtils, IntervalUtils, 
TimestampFormatter}
-import org.apache.spark.sql.catalyst.util.DateTimeConstants.NANOS_PER_SECOND
+import org.apache.spark.sql.catalyst.util.DateTimeConstants._
 import org.apache.spark.sql.catalyst.util.DateTimeTestUtils._
 import org.apache.spark.sql.internal.SQLConf
 import org.apache.spark.sql.types._
@@ -359,6 +359,40 @@ class DateExpressionsSuite extends SparkFunSuite with 
ExpressionEvalHelper {
     checkConsistencyBetweenInterpretedAndCodegen(DateAdd, DateType, 
IntegerType)
   }
 
+  test("date add interval") {
+    val d = Date.valueOf("2016-02-28")
+    Seq("true", "false") foreach { flag =>
+      withSQLConf((SQLConf.ANSI_ENABLED.key, flag)) {
+        checkEvaluation(
+          DateAddInterval(Literal(d), Literal(new CalendarInterval(0, 1, 0))),
+          DateTimeUtils.fromJavaDate(Date.valueOf("2016-02-29")))
+        checkEvaluation(
+          DateAddInterval(Literal(d), Literal(new CalendarInterval(1, 1, 0))),
+          DateTimeUtils.fromJavaDate(Date.valueOf("2016-03-29")))
+        checkEvaluation(DateAddInterval(Literal(d), Literal.create(null, 
CalendarIntervalType)),
+          null)
+        checkEvaluation(DateAddInterval(Literal.create(null, DateType),
+          Literal(new CalendarInterval(1, 1, 0))),
+          null)
+      }
+    }
+
+    withSQLConf((SQLConf.ANSI_ENABLED.key, "true")) {
+      checkExceptionInExpression[IllegalArgumentException](
+        DateAddInterval(Literal(d), Literal(new CalendarInterval(1, 1, 25 * 
MICROS_PER_HOUR))),
+        "Cannot add hours, minutes or seconds, milliseconds, microseconds to a 
date")
+    }
+
+    withSQLConf((SQLConf.ANSI_ENABLED.key, "false")) {
+      checkEvaluation(
+        DateAddInterval(Literal(d), Literal(new CalendarInterval(1, 1, 25))),
+        DateTimeUtils.fromJavaDate(Date.valueOf("2016-03-29")))
+      checkEvaluation(
+        DateAddInterval(Literal(d), Literal(new CalendarInterval(1, 1, 25 * 
MICROS_PER_HOUR))),
+        DateTimeUtils.fromJavaDate(Date.valueOf("2016-03-30")))
+    }
+  }
+
   test("date_sub") {
     checkEvaluation(
       DateSub(Literal(Date.valueOf("2015-01-01")), Literal(1.toByte)),
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ExpressionSQLBuilderSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ExpressionSQLBuilderSuite.scala
index 492d97b..ab0ef22 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ExpressionSQLBuilderSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ExpressionSQLBuilderSuite.scala
@@ -176,5 +176,9 @@ class ExpressionSQLBuilderSuite extends SparkFunSuite {
       TimeSub('a, interval),
       "`a` - INTERVAL '1 hours'"
     )
+    checkSQL(
+      DateAddInterval('a, interval),
+      "`a` + INTERVAL '1 hours'"
+    )
   }
 }
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala
index 3981792..b547c44 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala
@@ -30,7 +30,7 @@ import org.apache.spark.sql.catalyst.plans.SQLHelper
 import org.apache.spark.sql.catalyst.util.DateTimeConstants._
 import org.apache.spark.sql.catalyst.util.DateTimeTestUtils._
 import org.apache.spark.sql.catalyst.util.DateTimeUtils._
-import org.apache.spark.unsafe.types.UTF8String
+import org.apache.spark.unsafe.types.{CalendarInterval, UTF8String}
 
 class DateTimeUtilsSuite extends SparkFunSuite with Matchers with SQLHelper {
 
@@ -391,6 +391,14 @@ class DateTimeUtilsSuite extends SparkFunSuite with 
Matchers with SQLHelper {
     assert(dateAddMonths(input, -13) === days(1996, 1, 28))
   }
 
+  test("date add interval with day precision") {
+    val input = days(1997, 2, 28, 10, 30)
+    assert(dateAddInterval(input, new CalendarInterval(36, 0, 0)) === 
days(2000, 2, 28))
+    assert(dateAddInterval(input, new CalendarInterval(36, 47, 0)) === 
days(2000, 4, 15))
+    assert(dateAddInterval(input, new CalendarInterval(-13, 0, 0)) === 
days(1996, 1, 28))
+    intercept[IllegalArgumentException](dateAddInterval(input, new 
CalendarInterval(36, 47, 1)))
+  }
+
   test("timestamp add months") {
     val ts1 = date(1997, 2, 28, 10, 30, 0)
     val ts2 = date(2000, 2, 28, 10, 30, 0, 123000)
diff --git a/sql/core/src/test/resources/sql-tests/inputs/ansi/datetime.sql 
b/sql/core/src/test/resources/sql-tests/inputs/ansi/datetime.sql
new file mode 100644
index 0000000..58ecf80
--- /dev/null
+++ b/sql/core/src/test/resources/sql-tests/inputs/ansi/datetime.sql
@@ -0,0 +1 @@
+--IMPORT datetime.sql
diff --git a/sql/core/src/test/resources/sql-tests/results/datetime.sql.out 
b/sql/core/src/test/resources/sql-tests/results/ansi/datetime.sql.out
old mode 100755
new mode 100644
similarity index 93%
copy from sql/core/src/test/resources/sql-tests/results/datetime.sql.out
copy to sql/core/src/test/resources/sql-tests/results/ansi/datetime.sql.out
index aec04da..81a73a6
--- a/sql/core/src/test/resources/sql-tests/results/datetime.sql.out
+++ b/sql/core/src/test/resources/sql-tests/results/ansi/datetime.sql.out
@@ -5,9 +5,15 @@
 -- !query
 select current_date = current_date(), current_timestamp = current_timestamp()
 -- !query schema
-struct<(current_date() = current_date()):boolean,(current_timestamp() = 
current_timestamp()):boolean>
+struct<>
 -- !query output
-true   true
+org.apache.spark.sql.catalyst.parser.ParseException
+
+no viable alternative at input 'current_date'(line 1, pos 22)
+
+== SQL ==
+select current_date = current_date(), current_timestamp = current_timestamp()
+----------------------^^^
 
 
 -- !query
@@ -42,16 +48,25 @@ create temporary view ttf1 as select * from values
 -- !query schema
 struct<>
 -- !query output
+org.apache.spark.sql.catalyst.parser.ParseException
 
+no viable alternative at input 'current_date'(line 4, pos 10)
+
+== SQL ==
+create temporary view ttf1 as select * from values
+  (1, 2),
+  (2, 3)
+  as ttf1(current_date, current_timestamp)
+----------^^^
 
 
 -- !query
 select current_date, current_timestamp from ttf1
 -- !query schema
-struct<current_date:int,current_timestamp:int>
+struct<>
 -- !query output
-1      2
-2      3
+org.apache.spark.sql.AnalysisException
+Table or view not found: ttf1; line 1 pos 44
 
 
 -- !query
@@ -68,10 +83,15 @@ struct<>
 -- !query
 select current_date = current_date(), current_timestamp = current_timestamp(), 
a, b from ttf2
 -- !query schema
-struct<(current_date() = current_date()):boolean,(current_timestamp() = 
current_timestamp()):boolean,a:int,b:int>
+struct<>
 -- !query output
-true   true    1       2
-true   true    2       3
+org.apache.spark.sql.catalyst.parser.ParseException
+
+no viable alternative at input 'current_date'(line 1, pos 22)
+
+== SQL ==
+select current_date = current_date(), current_timestamp = current_timestamp(), 
a, b from ttf2
+----------------------^^^
 
 
 -- !query
@@ -94,9 +114,15 @@ struct<weekday(CAST(2007-02-03 AS 
DATE)):int,weekday(CAST(2009-07-30 AS DATE)):i
 -- !query
 select year('1500-01-01'), month('1500-01-01'), dayOfYear('1500-01-01')
 -- !query schema
-struct<year(CAST(1500-01-01 AS DATE)):int,month(CAST(1500-01-01 AS 
DATE)):int,dayofyear(CAST(1500-01-01 AS DATE)):int>
+struct<>
 -- !query output
-1500   1       1
+org.apache.spark.sql.catalyst.parser.ParseException
+
+no viable alternative at input 'year'(line 1, pos 7)
+
+== SQL ==
+select year('1500-01-01'), month('1500-01-01'), dayOfYear('1500-01-01')
+-------^^^
 
 
 -- !query
@@ -134,17 +160,19 @@ struct<CAST(TIMESTAMP '2011-11-11 11:11:11' - INTERVAL '2 
days' AS TIMESTAMP):ti
 -- !query
 select date'2011-11-11 11:11:11' + interval '2' second
 -- !query schema
-struct<CAST(CAST(DATE '2011-11-11' AS TIMESTAMP) + INTERVAL '2 seconds' AS 
DATE):date>
+struct<>
 -- !query output
-2011-11-11
+java.lang.IllegalArgumentException
+requirement failed: Cannot add hours, minutes or seconds, milliseconds, 
microseconds to a date
 
 
 -- !query
 select date'2011-11-11 11:11:11' - interval '2' second
 -- !query schema
-struct<CAST(CAST(DATE '2011-11-11' AS TIMESTAMP) - INTERVAL '2 seconds' AS 
DATE):date>
+struct<>
 -- !query output
-2011-11-10
+java.lang.IllegalArgumentException
+requirement failed: Cannot add hours, minutes or seconds, milliseconds, 
microseconds to a date
 
 
 -- !query
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 d4238c7..e8201d4 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
@@ -689,7 +689,7 @@ select
   interval '2-2' year to month + dateval
 from interval_arithmetic
 -- !query schema
-struct<dateval:date,CAST(CAST(dateval AS TIMESTAMP) - INTERVAL '2 years 2 
months' AS DATE):date,CAST(CAST(dateval AS TIMESTAMP) - INTERVAL '-2 years -2 
months' AS DATE):date,CAST(CAST(dateval AS TIMESTAMP) + INTERVAL '2 years 2 
months' AS DATE):date,CAST(CAST(dateval AS TIMESTAMP) + INTERVAL '-2 years -2 
months' AS DATE):date,CAST(CAST(dateval AS TIMESTAMP) + (- INTERVAL '2 years 2 
months') AS DATE):date,CAST(CAST(dateval AS TIMESTAMP) + INTERVAL '2 years 2 
months' AS DATE):date>
+struct<dateval:date,dateval + (- INTERVAL '2 years 2 months'):date,dateval + 
(- INTERVAL '-2 years -2 months'):date,dateval + INTERVAL '2 years 2 
months':date,dateval + INTERVAL '-2 years -2 months':date,dateval + (- INTERVAL 
'2 years 2 months'):date,dateval + INTERVAL '2 years 2 months':date>
 -- !query output
 2012-01-01     2009-11-01      2014-03-01      2014-03-01      2009-11-01      
2009-11-01      2014-03-01
 
@@ -732,9 +732,10 @@ select
   interval '99 11:22:33.123456789' day to second + dateval
 from interval_arithmetic
 -- !query schema
-struct<dateval:date,CAST(CAST(dateval AS TIMESTAMP) - INTERVAL '99 days 11 
hours 22 minutes 33.123456 seconds' AS DATE):date,CAST(CAST(dateval AS 
TIMESTAMP) - INTERVAL '-99 days -11 hours -22 minutes -33.123456 seconds' AS 
DATE):date,CAST(CAST(dateval AS TIMESTAMP) + INTERVAL '99 days 11 hours 22 
minutes 33.123456 seconds' AS DATE):date,CAST(CAST(dateval AS TIMESTAMP) + 
INTERVAL '-99 days -11 hours -22 minutes -33.123456 seconds' AS 
DATE):date,CAST(CAST(dateval AS TIMESTAMP) + (- INTERVA [...]
+struct<>
 -- !query output
-2012-01-01     2011-09-23      2012-04-09      2012-04-09      2011-09-23      
2011-09-23      2012-04-09
+java.lang.IllegalArgumentException
+requirement failed: Cannot add hours, minutes or seconds, milliseconds, 
microseconds to a date
 
 
 -- !query
diff --git a/sql/core/src/test/resources/sql-tests/results/datetime.sql.out 
b/sql/core/src/test/resources/sql-tests/results/datetime.sql.out
index aec04da..2e60085 100755
--- a/sql/core/src/test/resources/sql-tests/results/datetime.sql.out
+++ b/sql/core/src/test/resources/sql-tests/results/datetime.sql.out
@@ -134,7 +134,7 @@ struct<CAST(TIMESTAMP '2011-11-11 11:11:11' - INTERVAL '2 
days' AS TIMESTAMP):ti
 -- !query
 select date'2011-11-11 11:11:11' + interval '2' second
 -- !query schema
-struct<CAST(CAST(DATE '2011-11-11' AS TIMESTAMP) + INTERVAL '2 seconds' AS 
DATE):date>
+struct<DATE '2011-11-11' + INTERVAL '2 seconds':date>
 -- !query output
 2011-11-11
 
@@ -142,7 +142,7 @@ struct<CAST(CAST(DATE '2011-11-11' AS TIMESTAMP) + INTERVAL 
'2 seconds' AS DATE)
 -- !query
 select date'2011-11-11 11:11:11' - interval '2' second
 -- !query schema
-struct<CAST(CAST(DATE '2011-11-11' AS TIMESTAMP) - INTERVAL '2 seconds' AS 
DATE):date>
+struct<DATE '2011-11-11' + (- INTERVAL '2 seconds'):date>
 -- !query output
 2011-11-10
 
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 0d758ca..84e3fb3 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
@@ -668,7 +668,7 @@ select
   interval '2-2' year to month + dateval
 from interval_arithmetic
 -- !query schema
-struct<dateval:date,CAST(CAST(dateval AS TIMESTAMP) - INTERVAL '2 years 2 
months' AS DATE):date,CAST(CAST(dateval AS TIMESTAMP) - INTERVAL '-2 years -2 
months' AS DATE):date,CAST(CAST(dateval AS TIMESTAMP) + INTERVAL '2 years 2 
months' AS DATE):date,CAST(CAST(dateval AS TIMESTAMP) + INTERVAL '-2 years -2 
months' AS DATE):date,CAST(CAST(dateval AS TIMESTAMP) + (- INTERVAL '2 years 2 
months') AS DATE):date,CAST(CAST(dateval AS TIMESTAMP) + INTERVAL '2 years 2 
months' AS DATE):date>
+struct<dateval:date,dateval + (- INTERVAL '2 years 2 months'):date,dateval + 
(- INTERVAL '-2 years -2 months'):date,dateval + INTERVAL '2 years 2 
months':date,dateval + INTERVAL '-2 years -2 months':date,dateval + (- INTERVAL 
'2 years 2 months'):date,dateval + INTERVAL '2 years 2 months':date>
 -- !query output
 2012-01-01     2009-11-01      2014-03-01      2014-03-01      2009-11-01      
2009-11-01      2014-03-01
 
@@ -711,7 +711,7 @@ select
   interval '99 11:22:33.123456789' day to second + dateval
 from interval_arithmetic
 -- !query schema
-struct<dateval:date,CAST(CAST(dateval AS TIMESTAMP) - INTERVAL '99 days 11 
hours 22 minutes 33.123456 seconds' AS DATE):date,CAST(CAST(dateval AS 
TIMESTAMP) - INTERVAL '-99 days -11 hours -22 minutes -33.123456 seconds' AS 
DATE):date,CAST(CAST(dateval AS TIMESTAMP) + INTERVAL '99 days 11 hours 22 
minutes 33.123456 seconds' AS DATE):date,CAST(CAST(dateval AS TIMESTAMP) + 
INTERVAL '-99 days -11 hours -22 minutes -33.123456 seconds' AS 
DATE):date,CAST(CAST(dateval AS TIMESTAMP) + (- INTERVA [...]
+struct<dateval:date,dateval + (- INTERVAL '99 days 11 hours 22 minutes 
33.123456 seconds'):date,dateval + (- INTERVAL '-99 days -11 hours -22 minutes 
-33.123456 seconds'):date,dateval + INTERVAL '99 days 11 hours 22 minutes 
33.123456 seconds':date,dateval + INTERVAL '-99 days -11 hours -22 minutes 
-33.123456 seconds':date,dateval + (- INTERVAL '99 days 11 hours 22 minutes 
33.123456 seconds'):date,dateval + INTERVAL '99 days 11 hours 22 minutes 
33.123456 seconds':date>
 -- !query output
 2012-01-01     2011-09-23      2012-04-09      2012-04-09      2011-09-23      
2011-09-23      2012-04-09
 
diff --git 
a/sql/core/src/test/resources/sql-tests/results/typeCoercion/native/dateTimeOperations.sql.out
 
b/sql/core/src/test/resources/sql-tests/results/typeCoercion/native/dateTimeOperations.sql.out
index d5c27ad..7b1fcdd 100644
--- 
a/sql/core/src/test/resources/sql-tests/results/typeCoercion/native/dateTimeOperations.sql.out
+++ 
b/sql/core/src/test/resources/sql-tests/results/typeCoercion/native/dateTimeOperations.sql.out
@@ -118,7 +118,7 @@ struct<CAST(CAST(2017-12-11 09:30:00.0 AS TIMESTAMP) + 
INTERVAL '2 days' AS TIME
 -- !query
 select cast('2017-12-11 09:30:00' as date) + interval 2 day
 -- !query schema
-struct<CAST(CAST(CAST(2017-12-11 09:30:00 AS DATE) AS TIMESTAMP) + INTERVAL '2 
days' AS DATE):date>
+struct<CAST(2017-12-11 09:30:00 AS DATE) + INTERVAL '2 days':date>
 -- !query output
 2017-12-13
 
@@ -231,7 +231,7 @@ struct<CAST(CAST(2017-12-11 09:30:00.0 AS TIMESTAMP) + 
INTERVAL '2 days' AS TIME
 -- !query
 select interval 2 day + cast('2017-12-11 09:30:00' as date)
 -- !query schema
-struct<CAST(CAST(CAST(2017-12-11 09:30:00 AS DATE) AS TIMESTAMP) + INTERVAL '2 
days' AS DATE):date>
+struct<CAST(2017-12-11 09:30:00 AS DATE) + INTERVAL '2 days':date>
 -- !query output
 2017-12-13
 
@@ -344,6 +344,6 @@ struct<CAST(CAST(2017-12-11 09:30:00.0 AS TIMESTAMP) - 
INTERVAL '2 days' AS TIME
 -- !query
 select cast('2017-12-11 09:30:00' as date) - interval 2 day
 -- !query schema
-struct<CAST(CAST(CAST(2017-12-11 09:30:00 AS DATE) AS TIMESTAMP) - INTERVAL '2 
days' AS DATE):date>
+struct<CAST(2017-12-11 09:30:00 AS DATE) + (- INTERVAL '2 days'):date>
 -- !query output
 2017-12-09


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to