Skip to content

Commit 435cb4b

Browse files
committed
[SPARK-52493][SQL] Support TIMESTAMP WITHOUT TIME ZONE
### What changes were proposed in this pull request? In the PR, I propose to introduce a synonym for the existing type `TIMESTAMP_NTZ` as the SQL standard defines: `TIMESTAMP WITHOUT TIME ZONE`. ### Why are the changes needed? - To conform to the SQL standard - To simplify migration from other systems that recognize the fully qualified type name. - To be consistent with the `TIME` type, see #51177 ### Does this PR introduce _any_ user-facing change? No, it just extends the existing syntax. ### How was this patch tested? By running the modified test suite: ``` $ build/sbt "test:testOnly *DataTypeParserSuite" ``` ### Was this patch authored or co-authored using generative AI tooling? No. Closes #51181 from MaxGekk/timestamp-without-timezone. Authored-by: Max Gekk <[email protected]> Signed-off-by: Max Gekk <[email protected]>
1 parent c4fb4a4 commit 435cb4b

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

sql/api/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBaseParser.g4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,7 @@ dataType
13451345
(TO to=(HOUR | MINUTE | SECOND))? #dayTimeIntervalDataType
13461346
| TIME (LEFT_PAREN precision=INTEGER_VALUE RIGHT_PAREN)?
13471347
(WITHOUT TIME ZONE)? #timeDataType
1348+
| (TIMESTAMP_NTZ | TIMESTAMP WITHOUT TIME ZONE) #timestampNtzDataType
13481349
| type (LEFT_PAREN INTEGER_VALUE
13491350
(COMMA INTEGER_VALUE)* RIGHT_PAREN)? #primitiveDataType
13501351
;

sql/api/src/main/scala/org/apache/spark/sql/catalyst/parser/DataTypeAstBuilder.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ class DataTypeAstBuilder extends SqlBaseParserBaseVisitor[AnyRef] {
7777
TimeType(precision)
7878
}
7979

80+
/**
81+
* Create the TIMESTAMP_NTZ primitive type.
82+
*/
83+
override def visitTimestampNtzDataType(ctx: TimestampNtzDataTypeContext): DataType = {
84+
withOrigin(ctx)(TimestampNTZType)
85+
}
86+
8087
/**
8188
* Resolve/create a primitive type.
8289
*/
@@ -92,7 +99,6 @@ class DataTypeAstBuilder extends SqlBaseParserBaseVisitor[AnyRef] {
9299
case (DOUBLE, Nil) => DoubleType
93100
case (DATE, Nil) => DateType
94101
case (TIMESTAMP, Nil) => SqlApiConf.get.timestampType
95-
case (TIMESTAMP_NTZ, Nil) => TimestampNTZType
96102
case (TIMESTAMP_LTZ, Nil) => TimestampType
97103
case (STRING, Nil) =>
98104
typeCtx.children.asScala.toSeq match {

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/DataTypeParserSuite.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class DataTypeParserSuite extends SparkFunSuite with SQLHelper {
6464
checkDataType("TIME(6)", TimeType(6))
6565
checkDataType("TIME(6) WITHOUT TIME ZONE", TimeType(6))
6666
checkDataType("timestamp", TimestampType)
67+
checkDataType("TIMESTAMP WITHOUT TIME ZONE", TimestampNTZType)
6768
checkDataType("timestamp_ntz", TimestampNTZType)
6869
checkDataType("timestamp_ltz", TimestampType)
6970
checkDataType("string", StringType)
@@ -160,6 +161,7 @@ class DataTypeParserSuite extends SparkFunSuite with SQLHelper {
160161
}
161162
withSQLConf(SQLConf.TIMESTAMP_TYPE.key -> TimestampTypes.TIMESTAMP_LTZ.toString) {
162163
assert(parse("timestamp") === TimestampType)
164+
assert(parse("timestamp without time zone") === TimestampNTZType)
163165
}
164166
}
165167

@@ -220,4 +222,19 @@ class DataTypeParserSuite extends SparkFunSuite with SQLHelper {
220222
condition = "PARSE_SYNTAX_ERROR",
221223
parameters = Map("error" -> "'WITH'", "hint" -> ""))
222224
}
225+
226+
test("invalid TIMESTAMP suffix") {
227+
checkError(
228+
exception = intercept[ParseException] {
229+
CatalystSqlParser.parseDataType("timestamp WITHOUT TIMEZONE")
230+
},
231+
condition = "PARSE_SYNTAX_ERROR",
232+
parameters = Map("error" -> "'WITHOUT'", "hint" -> ""))
233+
checkError(
234+
exception = intercept[ParseException] {
235+
CatalystSqlParser.parseDataType("timestamp WITH TIME ZONE")
236+
},
237+
condition = "PARSE_SYNTAX_ERROR",
238+
parameters = Map("error" -> "'WITH'", "hint" -> ""))
239+
}
223240
}

0 commit comments

Comments
 (0)