You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by gu...@apache.org on 2026/09/28 01:20:54 UTC

(spark) branch master updated: [SPARK-59534][SQL] Support implicit casting of DATE and STRING to TIMESTAMP in time_bucket

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

HyukjinKwon 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 ded027de5395 [SPARK-59534][SQL] Support implicit casting of DATE and STRING to TIMESTAMP in time_bucket
ded027de5395 is described below

commit ded027de5395f7d2c8510fa8267db03f19090632
Author: Nikolina Vraneš <ni...@databricks.com>
AuthorDate: Mon Sep 28 10:20:37 2026 +0900

    [SPARK-59534][SQL] Support implicit casting of DATE and STRING to TIMESTAMP in time_bucket
    
    ### What changes were proposed in this pull request?
    
    This PR enables implicit type coercion for the timestamp and origin arguments of
    `time_bucket`. Spark casts `DATE` and `STRING` inputs to `TIMESTAMP` in both ANSI and legacy
    modes.
    
    The coercion rule leaves `TIME` inputs unchanged because converting `TIME` to `TIMESTAMP`
    requires `CURRENT_DATE`. Normal input validation rejects these inputs unless the caller uses an
    explicit cast. The rule continues to coerce the bucket-size argument where applicable. String
    bucket sizes remain invalid, while an untyped `NULL` bucket size becomes a day-time interval.
    
    ### Why are the changes needed?
    
    `time_bucket` rejected `DATE` and `STRING` timestamp and origin arguments instead of applying
    Spark's standard timestamp coercion. A targeted rule enables these conversions without adding
    an implicit, current-date-dependent conversion from `TIME`.
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes. `time_bucket` now accepts `DATE` and `STRING` values for its timestamp and origin arguments
    in both ANSI and legacy modes. For example:
    
    ```sql
    SELECT time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15');
    -- 2024-01-15 00:00:00
    
    SELECT time_bucket(INTERVAL '15' MINUTE, '2024-01-15 10:23:00');
    -- 2024-01-15 10:15:00
    ```
    
    `TIME` requires an explicit cast to `TIMESTAMP`.
    
    ### How was this patch tested?
    
    The patch adds ANSI and legacy type-coercion tests for `DATE` and `STRING` conversion, `TIME`
    rejection, string bucket-size rejection, and untyped `NULL` bucket-size coercion. It also adds SQL
    query coverage for `DATE` and `STRING` timestamp and origin arguments.
    
    ```bash
    build/sbt 'catalyst/testOnly *TypeCoercionSuite -- -z "time_bucket"'
    build/sbt 'sql/testOnly org.apache.spark.sql.SQLQueryTestSuite -- -z "time-bucket.sql"'
    ```
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Generated-by: OpenAI Codex (GPT-5)
    
    This pull request and its description were written by Isaac.
    
    Closes #58852 from vranes/effort/time-bucket-date.
    
    Authored-by: Nikolina Vraneš <ni...@databricks.com>
    Signed-off-by: Hyukjin Kwon <hy...@databricks.com>
---
 .../sql/catalyst/analysis/TypeCoercionHelper.scala | 11 +++
 .../catalyst/expressions/datetimeExpressions.scala |  2 +-
 .../catalyst/analysis/AnsiTypeCoercionSuite.scala  |  3 +
 .../sql/catalyst/analysis/TypeCoercionSuite.scala  | 59 +++++++++++++-
 .../sql-tests/analyzer-results/time-bucket.sql.out | 82 +++++++++++++-------
 .../resources/sql-tests/inputs/time-bucket.sql     | 13 +++-
 .../sql-tests/results/time-bucket.sql.out          | 90 +++++++++++++++-------
 7 files changed, 198 insertions(+), 62 deletions(-)

diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionHelper.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionHelper.scala
index 51cb4f922835..67af8f9ee111 100644
--- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionHelper.scala
+++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionHelper.scala
@@ -53,6 +53,7 @@ import org.apache.spark.sql.catalyst.expressions.{
   SpecialFrameBoundary,
   SpecifiedWindowFrame,
   SubtractTimestamps,
+  TimeBucket,
   TimestampAddInterval,
   WindowSpecDefinition
 }
@@ -711,6 +712,16 @@ abstract class TypeCoercionHelper {
           }
           .getOrElse(b) // If there is no applicable conversion, leave expression unchanged.
 
+      case t: TimeBucket =>
+        val children = t.children.zip(t.inputTypes).zipWithIndex.map {
+          case ((in, _), index) if index > 0 && in.dataType.isInstanceOf[TimeType] =>
+            // TIME-to-timestamp depends on CURRENT_DATE, so require an explicit cast.
+            in
+          case ((in, expected), _) =>
+            implicitCast(in, expected).getOrElse(in)
+        }
+        t.withNewChildren(children)
+
       case e: ImplicitCastInputTypes if e.inputTypes.nonEmpty =>
         val children: Seq[Expression] = e.children.zip(e.inputTypes).map {
           case (in, expected) =>
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 722265ac1c47..50f659e1f4d1 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
@@ -5410,7 +5410,7 @@ object TimeBucketExpressionBuilder extends ExpressionBuilder {
     expressions match {
       case Seq(rawBucketSize, rawTs) =>
         val bucketSize = retypeNull(rawBucketSize, DayTimeIntervalType())
-        // Fall back to TimestampType for bad ts types; ExpectsInputTypes will report it.
+        // Fall back to TimestampType when ts is not a recognized timestamp type.
         val tsType = rawTs.dataType match {
           case t if acceptsTsType(t) => t
           case _ => TimestampType
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnsiTypeCoercionSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnsiTypeCoercionSuite.scala
index c222655525ec..107ca4300e8c 100644
--- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnsiTypeCoercionSuite.scala
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnsiTypeCoercionSuite.scala
@@ -61,6 +61,9 @@ class AnsiTypeCoercionSuite extends TypeCoercionSuiteBase {
   override def implicitCast(e: Expression, expectedType: AbstractDataType): Option[Expression] =
     AnsiTypeCoercion.implicitCast(e, expectedType)
 
+  override protected def implicitTypeCastsRule: TypeCoercionRule =
+    AnsiTypeCoercion.ImplicitTypeCasts
+
   override def dateTimeOperationsRule: TypeCoercionRule = AnsiTypeCoercion.DateTimeOperations
 
   private def checkWidenType(
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionSuite.scala
index 80cdf90fc973..9c7832aae43c 100644
--- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionSuite.scala
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionSuite.scala
@@ -18,7 +18,7 @@
 package org.apache.spark.sql.catalyst.analysis
 
 import java.sql.Timestamp
-import java.time.{Duration, LocalDateTime, Period}
+import java.time.{Duration, LocalDateTime, LocalTime, Period}
 
 import org.apache.spark.internal.config.Tests.IS_TESTING
 import org.apache.spark.sql.catalyst.analysis.TypeCoercion._
@@ -45,6 +45,8 @@ abstract class TypeCoercionSuiteBase extends AnalysisTest {
 
   protected def implicitCast(e: Expression, expectedType: AbstractDataType): Option[Expression]
 
+  protected def implicitTypeCastsRule: TypeCoercionRule
+
   protected def dateTimeOperationsRule: TypeCoercionRule
 
   protected def shouldCast(from: DataType, to: AbstractDataType, expected: DataType): Unit = {
@@ -218,6 +220,58 @@ abstract class TypeCoercionSuiteBase extends AnalysisTest {
     shouldNotCast(checkedType, IntegralType)
   }
 
+  test("time_bucket implicitly casts date and string timestamp arguments") {
+    val bucketSize = Literal(Duration.ofMinutes(15))
+    val date = Literal(0, DateType)
+    val string = Literal("2024-01-01 00:00:00")
+
+    ruleTest(
+      rule = implicitTypeCastsRule,
+      initial = TimeBucket(bucketSize = bucketSize, ts = date, originTs = string),
+      transformed = TimeBucket(
+        bucketSize = bucketSize,
+        ts = Cast(date, TimestampType),
+        originTs = Cast(string, TimestampType)))
+  }
+
+  test("time_bucket does not implicitly cast time arguments to timestamp") {
+    val bucketSize = Literal(Duration.ofMinutes(15))
+    val time = Literal(LocalTime.of(10, 23, 0))
+    val timeBucket = TimeBucket(bucketSize = bucketSize, ts = time, originTs = time)
+
+    ruleTest(
+      rule = implicitTypeCastsRule,
+      initial = timeBucket,
+      transformed = timeBucket)
+  }
+
+  test("time_bucket does not implicitly cast string bucket size") {
+    val bucketSize = Literal("0 00:15:00")
+    val timestamp = Literal(Timestamp.valueOf("2024-01-01 00:00:00"))
+    val timeBucket = TimeBucket(
+      bucketSize = bucketSize,
+      ts = timestamp,
+      originTs = timestamp)
+
+    ruleTest(
+      rule = implicitTypeCastsRule,
+      initial = timeBucket,
+      transformed = timeBucket)
+  }
+
+  test("time_bucket implicitly casts null bucket size to day-time interval") {
+    val bucketSize = Literal(null)
+    val timestamp = Literal(Timestamp.valueOf("2024-01-01 00:00:00"))
+
+    ruleTest(
+      rule = implicitTypeCastsRule,
+      initial = TimeBucket(bucketSize = bucketSize, ts = timestamp, originTs = timestamp),
+      transformed = TimeBucket(
+        bucketSize = Cast(bucketSize, DayTimeIntervalType()),
+        ts = timestamp,
+        originTs = timestamp))
+  }
+
   test("SPARK-56152: implicit type cast - TimeType") {
     val checkedType = TimeType()
     checkTypeCasting(checkedType, castableTypes = Seq(checkedType, StringType) ++ datetimeTypes)
@@ -600,6 +654,9 @@ class TypeCoercionSuite extends TypeCoercionSuiteBase {
   override def implicitCast(e: Expression, expectedType: AbstractDataType): Option[Expression] =
     TypeCoercion.implicitCast(e, expectedType)
 
+  override protected def implicitTypeCastsRule: TypeCoercionRule =
+    TypeCoercion.ImplicitTypeCasts
+
   override def dateTimeOperationsRule: TypeCoercionRule = TypeCoercion.DateTimeOperations
 
   private def checkWidenType(
diff --git a/sql/core/src/test/resources/sql-tests/analyzer-results/time-bucket.sql.out b/sql/core/src/test/resources/sql-tests/analyzer-results/time-bucket.sql.out
index 2bc6cc2be0f1..954b7e82b4bb 100644
--- a/sql/core/src/test/resources/sql-tests/analyzer-results/time-bucket.sql.out
+++ b/sql/core/src/test/resources/sql-tests/analyzer-results/time-bucket.sql.out
@@ -310,95 +310,119 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException
 -- !query
 SELECT time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15')
 -- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+SELECT time_bucket(INTERVAL '15' MINUTE, '2024-01-15 10:23:00')
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', DATE '2024-01-01')
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', '2024-01-01 00:00:00')
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', DATE '2024-01-01')
+-- !query analysis
 org.apache.spark.sql.catalyst.ExtendedAnalysisException
 {
   "errorClass" : "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE",
   "sqlState" : "42K09",
   "messageParameters" : {
-    "inputSql" : "\"DATE '2024-01-15'\"",
-    "inputType" : "\"DATE\"",
-    "paramIndex" : "second",
-    "requiredType" : "(\"(TIMESTAMP OR TIMESTAMP WITHOUT TIME ZONE)\" or \"(TIMESTAMP_LTZ(P) OR TIMESTAMP_NTZ(P) WITH P IN [7, 9])\")",
-    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15', TIMESTAMP '1970-01-01 00:00:00')\""
+    "inputSql" : "\"DATE '2024-01-01'\"",
+    "inputType" : "\"TIMESTAMP\"",
+    "paramIndex" : "third",
+    "requiredType" : "\"TIMESTAMP_NTZ\"",
+    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', DATE '2024-01-01')\""
   },
   "queryContext" : [ {
     "objectType" : "",
     "objectName" : "",
     "startIndex" : 8,
-    "stopIndex" : 59,
-    "fragment" : "time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15')"
+    "stopIndex" : 96,
+    "fragment" : "time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', DATE '2024-01-01')"
   } ]
 }
 
 
 -- !query
-SELECT time_bucket(INTERVAL '15' MINUTE, '2024-01-15 10:23:00')
+SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', '2024-01-01 00:00:00')
 -- !query analysis
 org.apache.spark.sql.catalyst.ExtendedAnalysisException
 {
   "errorClass" : "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE",
   "sqlState" : "42K09",
   "messageParameters" : {
-    "inputSql" : "\"2024-01-15 10:23:00\"",
-    "inputType" : "\"STRING\"",
-    "paramIndex" : "second",
-    "requiredType" : "(\"(TIMESTAMP OR TIMESTAMP WITHOUT TIME ZONE)\" or \"(TIMESTAMP_LTZ(P) OR TIMESTAMP_NTZ(P) WITH P IN [7, 9])\")",
-    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, 2024-01-15 10:23:00, TIMESTAMP '1970-01-01 00:00:00')\""
+    "inputSql" : "\"2024-01-01 00:00:00\"",
+    "inputType" : "\"TIMESTAMP\"",
+    "paramIndex" : "third",
+    "requiredType" : "\"TIMESTAMP_NTZ\"",
+    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', 2024-01-01 00:00:00)\""
   },
   "queryContext" : [ {
     "objectType" : "",
     "objectName" : "",
     "startIndex" : 8,
-    "stopIndex" : 63,
-    "fragment" : "time_bucket(INTERVAL '15' MINUTE, '2024-01-15 10:23:00')"
+    "stopIndex" : 100,
+    "fragment" : "time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', '2024-01-01 00:00:00')"
   } ]
 }
 
 
 -- !query
-SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', DATE '2024-01-01')
+SELECT time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15', TIMESTAMP_NTZ '2024-01-01 00:00:00')
 -- !query analysis
 org.apache.spark.sql.catalyst.ExtendedAnalysisException
 {
   "errorClass" : "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE",
   "sqlState" : "42K09",
   "messageParameters" : {
-    "inputSql" : "\"DATE '2024-01-01'\"",
-    "inputType" : "\"DATE\"",
+    "inputSql" : "\"TIMESTAMP_NTZ '2024-01-01 00:00:00'\"",
+    "inputType" : "\"TIMESTAMP_NTZ\"",
     "paramIndex" : "third",
-    "requiredType" : "(\"(TIMESTAMP OR TIMESTAMP WITHOUT TIME ZONE)\" or \"(TIMESTAMP_LTZ(P) OR TIMESTAMP_NTZ(P) WITH P IN [7, 9])\")",
-    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', DATE '2024-01-01')\""
+    "requiredType" : "\"TIMESTAMP\"",
+    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15', TIMESTAMP_NTZ '2024-01-01 00:00:00')\""
   },
   "queryContext" : [ {
     "objectType" : "",
     "objectName" : "",
     "startIndex" : 8,
-    "stopIndex" : 92,
-    "fragment" : "time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', DATE '2024-01-01')"
+    "stopIndex" : 96,
+    "fragment" : "time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15', TIMESTAMP_NTZ '2024-01-01 00:00:00')"
   } ]
 }
 
 
 -- !query
-SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', '2024-01-01 00:00:00')
+SELECT time_bucket(INTERVAL '15' MINUTE, '2024-01-15 10:23:00', TIMESTAMP_NTZ '2024-01-01 00:00:00')
 -- !query analysis
 org.apache.spark.sql.catalyst.ExtendedAnalysisException
 {
   "errorClass" : "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE",
   "sqlState" : "42K09",
   "messageParameters" : {
-    "inputSql" : "\"2024-01-01 00:00:00\"",
-    "inputType" : "\"STRING\"",
+    "inputSql" : "\"TIMESTAMP_NTZ '2024-01-01 00:00:00'\"",
+    "inputType" : "\"TIMESTAMP_NTZ\"",
     "paramIndex" : "third",
-    "requiredType" : "(\"(TIMESTAMP OR TIMESTAMP WITHOUT TIME ZONE)\" or \"(TIMESTAMP_LTZ(P) OR TIMESTAMP_NTZ(P) WITH P IN [7, 9])\")",
-    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', 2024-01-01 00:00:00)\""
+    "requiredType" : "\"TIMESTAMP\"",
+    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, 2024-01-15 10:23:00, TIMESTAMP_NTZ '2024-01-01 00:00:00')\""
   },
   "queryContext" : [ {
     "objectType" : "",
     "objectName" : "",
     "startIndex" : 8,
-    "stopIndex" : 96,
-    "fragment" : "time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', '2024-01-01 00:00:00')"
+    "stopIndex" : 100,
+    "fragment" : "time_bucket(INTERVAL '15' MINUTE, '2024-01-15 10:23:00', TIMESTAMP_NTZ '2024-01-01 00:00:00')"
   } ]
 }
 
diff --git a/sql/core/src/test/resources/sql-tests/inputs/time-bucket.sql b/sql/core/src/test/resources/sql-tests/inputs/time-bucket.sql
index d13ad227a0ea..52cad7bae848 100644
--- a/sql/core/src/test/resources/sql-tests/inputs/time-bucket.sql
+++ b/sql/core/src/test/resources/sql-tests/inputs/time-bucket.sql
@@ -37,14 +37,23 @@ SELECT time_bucket(INTERVAL '1' HOUR, TIMESTAMP_NTZ '2024-01-01 11:27:00', TIMES
 -- bucket_size must be an interval (not a string)
 SELECT time_bucket('15 minutes', TIMESTAMP '2024-01-15 10:23:00');
 
--- ts must be TIMESTAMP or TIMESTAMP_NTZ (not DATE or string)
+-- Implicit casts for timestamp arguments
+
+-- DATE and string ts values cast to TIMESTAMP
 SELECT time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15');
 SELECT time_bucket(INTERVAL '15' MINUTE, '2024-01-15 10:23:00');
 
--- origin must be TIMESTAMP or TIMESTAMP_NTZ (not DATE or string)
+-- DATE and string origin values cast to TIMESTAMP
 SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', DATE '2024-01-01');
 SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', '2024-01-01 00:00:00');
 
+-- DATE and string cast to TIMESTAMP (LTZ). Mixing them with TIMESTAMP_NTZ
+-- makes ts and origin different types, so the call is rejected.
+SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', DATE '2024-01-01');
+SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', '2024-01-01 00:00:00');
+SELECT time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15', TIMESTAMP_NTZ '2024-01-01 00:00:00');
+SELECT time_bucket(INTERVAL '15' MINUTE, '2024-01-15 10:23:00', TIMESTAMP_NTZ '2024-01-01 00:00:00');
+
 
 -- Error: bucket_size and origin must be foldable
 
diff --git a/sql/core/src/test/resources/sql-tests/results/time-bucket.sql.out b/sql/core/src/test/resources/sql-tests/results/time-bucket.sql.out
index 7e59efc9c1e0..b5f734aa9840 100644
--- a/sql/core/src/test/resources/sql-tests/results/time-bucket.sql.out
+++ b/sql/core/src/test/resources/sql-tests/results/time-bucket.sql.out
@@ -338,6 +338,38 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException
 -- !query
 SELECT time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15')
 -- !query schema
+struct<time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15', TIMESTAMP '1970-01-01 00:00:00'):timestamp>
+-- !query output
+2024-01-15 00:00:00
+
+
+-- !query
+SELECT time_bucket(INTERVAL '15' MINUTE, '2024-01-15 10:23:00')
+-- !query schema
+struct<time_bucket(INTERVAL '15' MINUTE, 2024-01-15 10:23:00, TIMESTAMP '1970-01-01 00:00:00'):timestamp>
+-- !query output
+2024-01-15 10:15:00
+
+
+-- !query
+SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', DATE '2024-01-01')
+-- !query schema
+struct<time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', DATE '2024-01-01'):timestamp>
+-- !query output
+2024-01-15 10:15:00
+
+
+-- !query
+SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', '2024-01-01 00:00:00')
+-- !query schema
+struct<time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', 2024-01-01 00:00:00):timestamp>
+-- !query output
+2024-01-15 10:15:00
+
+
+-- !query
+SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', DATE '2024-01-01')
+-- !query schema
 struct<>
 -- !query output
 org.apache.spark.sql.catalyst.ExtendedAnalysisException
@@ -345,24 +377,24 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException
   "errorClass" : "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE",
   "sqlState" : "42K09",
   "messageParameters" : {
-    "inputSql" : "\"DATE '2024-01-15'\"",
-    "inputType" : "\"DATE\"",
-    "paramIndex" : "second",
-    "requiredType" : "(\"(TIMESTAMP OR TIMESTAMP WITHOUT TIME ZONE)\" or \"(TIMESTAMP_LTZ(P) OR TIMESTAMP_NTZ(P) WITH P IN [7, 9])\")",
-    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15', TIMESTAMP '1970-01-01 00:00:00')\""
+    "inputSql" : "\"DATE '2024-01-01'\"",
+    "inputType" : "\"TIMESTAMP\"",
+    "paramIndex" : "third",
+    "requiredType" : "\"TIMESTAMP_NTZ\"",
+    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', DATE '2024-01-01')\""
   },
   "queryContext" : [ {
     "objectType" : "",
     "objectName" : "",
     "startIndex" : 8,
-    "stopIndex" : 59,
-    "fragment" : "time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15')"
+    "stopIndex" : 96,
+    "fragment" : "time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', DATE '2024-01-01')"
   } ]
 }
 
 
 -- !query
-SELECT time_bucket(INTERVAL '15' MINUTE, '2024-01-15 10:23:00')
+SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', '2024-01-01 00:00:00')
 -- !query schema
 struct<>
 -- !query output
@@ -371,24 +403,24 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException
   "errorClass" : "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE",
   "sqlState" : "42K09",
   "messageParameters" : {
-    "inputSql" : "\"2024-01-15 10:23:00\"",
-    "inputType" : "\"STRING\"",
-    "paramIndex" : "second",
-    "requiredType" : "(\"(TIMESTAMP OR TIMESTAMP WITHOUT TIME ZONE)\" or \"(TIMESTAMP_LTZ(P) OR TIMESTAMP_NTZ(P) WITH P IN [7, 9])\")",
-    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, 2024-01-15 10:23:00, TIMESTAMP '1970-01-01 00:00:00')\""
+    "inputSql" : "\"2024-01-01 00:00:00\"",
+    "inputType" : "\"TIMESTAMP\"",
+    "paramIndex" : "third",
+    "requiredType" : "\"TIMESTAMP_NTZ\"",
+    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', 2024-01-01 00:00:00)\""
   },
   "queryContext" : [ {
     "objectType" : "",
     "objectName" : "",
     "startIndex" : 8,
-    "stopIndex" : 63,
-    "fragment" : "time_bucket(INTERVAL '15' MINUTE, '2024-01-15 10:23:00')"
+    "stopIndex" : 100,
+    "fragment" : "time_bucket(INTERVAL '15' MINUTE, TIMESTAMP_NTZ '2024-01-15 10:23:00', '2024-01-01 00:00:00')"
   } ]
 }
 
 
 -- !query
-SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', DATE '2024-01-01')
+SELECT time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15', TIMESTAMP_NTZ '2024-01-01 00:00:00')
 -- !query schema
 struct<>
 -- !query output
@@ -397,24 +429,24 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException
   "errorClass" : "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE",
   "sqlState" : "42K09",
   "messageParameters" : {
-    "inputSql" : "\"DATE '2024-01-01'\"",
-    "inputType" : "\"DATE\"",
+    "inputSql" : "\"TIMESTAMP_NTZ '2024-01-01 00:00:00'\"",
+    "inputType" : "\"TIMESTAMP_NTZ\"",
     "paramIndex" : "third",
-    "requiredType" : "(\"(TIMESTAMP OR TIMESTAMP WITHOUT TIME ZONE)\" or \"(TIMESTAMP_LTZ(P) OR TIMESTAMP_NTZ(P) WITH P IN [7, 9])\")",
-    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', DATE '2024-01-01')\""
+    "requiredType" : "\"TIMESTAMP\"",
+    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15', TIMESTAMP_NTZ '2024-01-01 00:00:00')\""
   },
   "queryContext" : [ {
     "objectType" : "",
     "objectName" : "",
     "startIndex" : 8,
-    "stopIndex" : 92,
-    "fragment" : "time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', DATE '2024-01-01')"
+    "stopIndex" : 96,
+    "fragment" : "time_bucket(INTERVAL '15' MINUTE, DATE '2024-01-15', TIMESTAMP_NTZ '2024-01-01 00:00:00')"
   } ]
 }
 
 
 -- !query
-SELECT time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', '2024-01-01 00:00:00')
+SELECT time_bucket(INTERVAL '15' MINUTE, '2024-01-15 10:23:00', TIMESTAMP_NTZ '2024-01-01 00:00:00')
 -- !query schema
 struct<>
 -- !query output
@@ -423,18 +455,18 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException
   "errorClass" : "DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE",
   "sqlState" : "42K09",
   "messageParameters" : {
-    "inputSql" : "\"2024-01-01 00:00:00\"",
-    "inputType" : "\"STRING\"",
+    "inputSql" : "\"TIMESTAMP_NTZ '2024-01-01 00:00:00'\"",
+    "inputType" : "\"TIMESTAMP_NTZ\"",
     "paramIndex" : "third",
-    "requiredType" : "(\"(TIMESTAMP OR TIMESTAMP WITHOUT TIME ZONE)\" or \"(TIMESTAMP_LTZ(P) OR TIMESTAMP_NTZ(P) WITH P IN [7, 9])\")",
-    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', 2024-01-01 00:00:00)\""
+    "requiredType" : "\"TIMESTAMP\"",
+    "sqlExpr" : "\"time_bucket(INTERVAL '15' MINUTE, 2024-01-15 10:23:00, TIMESTAMP_NTZ '2024-01-01 00:00:00')\""
   },
   "queryContext" : [ {
     "objectType" : "",
     "objectName" : "",
     "startIndex" : 8,
-    "stopIndex" : 96,
-    "fragment" : "time_bucket(INTERVAL '15' MINUTE, TIMESTAMP '2024-01-15 10:23:00', '2024-01-01 00:00:00')"
+    "stopIndex" : 100,
+    "fragment" : "time_bucket(INTERVAL '15' MINUTE, '2024-01-15 10:23:00', TIMESTAMP_NTZ '2024-01-01 00:00:00')"
   } ]
 }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org