You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by ma...@apache.org on 2021/04/16 05:22:57 UTC
[spark] branch master updated: [SPARK-35099][SQL] Convert ANSI
interval literals to SQL string in ANSI style
This is an automated email from the ASF dual-hosted git repository.
maxgekk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/master by this push:
new 3f4c32b [SPARK-35099][SQL] Convert ANSI interval literals to SQL string in ANSI style
3f4c32b is described below
commit 3f4c32b3ca2d0f20806f81422e086d035b2eb5ce
Author: Max Gekk <ma...@gmail.com>
AuthorDate: Fri Apr 16 08:22:25 2021 +0300
[SPARK-35099][SQL] Convert ANSI interval literals to SQL string in ANSI style
### What changes were proposed in this pull request?
Handle `YearMonthIntervalType` and `DayTimeIntervalType` in the `sql()` and `toString()` method of `Literal`, and format the ANSI interval in the ANSI style.
### Why are the changes needed?
To improve readability and UX with Spark SQL. For example, a test output before the changes:
```
-- !query
select timestamp'2011-11-11 11:11:11' - interval '2' day
-- !query schema
struct<TIMESTAMP '2011-11-11 11:11:11' - 172800000000:timestamp>
-- !query output
2011-11-09 11:11:11
```
### Does this PR introduce _any_ user-facing change?
Should not since the new intervals haven't been released yet.
### How was this patch tested?
By running new tests:
```
$ ./build/sbt "test:testOnly *LiteralExpressionSuite"
```
Closes #32196 from MaxGekk/literal-ansi-interval-sql.
Authored-by: Max Gekk <ma...@gmail.com>
Signed-off-by: Max Gekk <ma...@gmail.com>
---
.../spark/sql/catalyst/expressions/literals.scala | 7 +++++-
.../expressions/LiteralExpressionSuite.scala | 27 ++++++++++++++++++++++
2 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/literals.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/literals.scala
index 2ea73e8..47eebc5 100644
--- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/literals.scala
+++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/literals.scala
@@ -43,7 +43,8 @@ import org.apache.spark.sql.catalyst.{CatalystTypeConverters, InternalRow, Scala
import org.apache.spark.sql.catalyst.expressions.codegen._
import org.apache.spark.sql.catalyst.util._
import org.apache.spark.sql.catalyst.util.DateTimeUtils.instantToMicros
-import org.apache.spark.sql.catalyst.util.IntervalUtils.{durationToMicros, periodToMonths}
+import org.apache.spark.sql.catalyst.util.IntervalStringStyles.ANSI_STYLE
+import org.apache.spark.sql.catalyst.util.IntervalUtils.{durationToMicros, periodToMonths, toDayTimeIntervalString, toYearMonthIntervalString}
import org.apache.spark.sql.errors.{QueryCompilationErrors, QueryExecutionErrors}
import org.apache.spark.sql.internal.SQLConf
import org.apache.spark.sql.types._
@@ -317,6 +318,8 @@ case class Literal (value: Any, dataType: DataType) extends LeafExpression {
DateFormatter(timeZoneId).format(value.asInstanceOf[Int])
case TimestampType =>
TimestampFormatter.getFractionFormatter(timeZoneId).format(value.asInstanceOf[Long])
+ case DayTimeIntervalType => toDayTimeIntervalString(value.asInstanceOf[Long], ANSI_STYLE)
+ case YearMonthIntervalType => toYearMonthIntervalString(value.asInstanceOf[Int], ANSI_STYLE)
case _ =>
other.toString
}
@@ -437,6 +440,8 @@ case class Literal (value: Any, dataType: DataType) extends LeafExpression {
case (i: CalendarInterval, CalendarIntervalType) =>
s"INTERVAL '${i.toString}'"
case (v: Array[Byte], BinaryType) => s"X'${DatatypeConverter.printHexBinary(v)}'"
+ case (i: Long, DayTimeIntervalType) => toDayTimeIntervalString(i, ANSI_STYLE)
+ case (i: Int, YearMonthIntervalType) => toYearMonthIntervalString(i, ANSI_STYLE)
case _ => value.toString
}
}
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/LiteralExpressionSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/LiteralExpressionSuite.scala
index f8766f3..a5f70fd 100644
--- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/LiteralExpressionSuite.scala
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/LiteralExpressionSuite.scala
@@ -19,6 +19,7 @@ package org.apache.spark.sql.catalyst.expressions
import java.nio.charset.StandardCharsets
import java.time.{Duration, Instant, LocalDate, LocalDateTime, Period, ZoneOffset}
+import java.time.temporal.ChronoUnit
import java.util.TimeZone
import scala.reflect.runtime.universe.TypeTag
@@ -385,4 +386,30 @@ class LiteralExpressionSuite extends SparkFunSuite with ExpressionEvalHelper {
val period1 = Period.ofMonths(-1024)
checkEvaluation(Literal(Array(period0, period1)), Array(period0, period1))
}
+
+ test("SPARK-35099: convert a literal of day-time interval to SQL string") {
+ Seq(
+ Duration.ofDays(-1) -> "-1 00:00:00",
+ Duration.of(10, ChronoUnit.MICROS) -> "0 00:00:00.00001",
+ Duration.of(MICROS_PER_DAY - 1, ChronoUnit.MICROS) -> "0 23:59:59.999999"
+ ).foreach { case (duration, intervalPayload) =>
+ val literal = Literal.apply(duration)
+ val expected = s"INTERVAL '$intervalPayload' DAY TO SECOND"
+ assert(literal.sql === expected)
+ assert(literal.toString === expected)
+ }
+ }
+
+ test("SPARK-35099: convert a literal of year-month interval to SQL string") {
+ Seq(
+ Period.ofYears(-1) -> "-1-0",
+ Period.of(9999, 11, 0) -> "9999-11",
+ Period.ofMonths(-11) -> "-0-11"
+ ).foreach { case (period, intervalPayload) =>
+ val literal = Literal.apply(period)
+ val expected = s"INTERVAL '$intervalPayload' YEAR TO MONTH"
+ assert(literal.sql === expected)
+ assert(literal.toString === expected)
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org