[SPARK-35977][SQL] Support non-reserved keyword TIMESTAMP_NTZ

### What changes were proposed in this pull request?

Support new keyword TIMESTAMP_NTZ, which can be used for:

- timestamp without time zone data type in DDL
- timestamp without time zone data type in Cast clause.
- timestamp without time zone data type literal

### Why are the changes needed?

Users can use `TIMESTAMP_NTZ` in DDL/Cast/Literals for the timestamp without time zone type directly.

### Does this PR introduce _any_ user-facing change?

No, the new timestamp type is not released yet.

### How was this patch tested?

Unit test

Closes #33221 from gengliangwang/timstamp_ntz.

Authored-by: Gengliang Wang <gengliang@apache.org>
Signed-off-by: Max Gekk <max.gekk@gmail.com>
(cherry picked from commit 5f44acff3d)
Signed-off-by: Max Gekk <max.gekk@gmail.com>
This commit is contained in:
Gengliang Wang 2021-07-05 22:30:44 +03:00 committed by Max Gekk
parent a9947cbd71
commit 1ec37dd164
3 changed files with 8 additions and 0 deletions

View file

@ -2125,6 +2125,9 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with SQLConfHelper with Logg
val zoneId = getZoneId(conf.sessionLocalTimeZone) val zoneId = getZoneId(conf.sessionLocalTimeZone)
val specialDate = convertSpecialDate(value, zoneId).map(Literal(_, DateType)) val specialDate = convertSpecialDate(value, zoneId).map(Literal(_, DateType))
specialDate.getOrElse(toLiteral(stringToDate, DateType)) specialDate.getOrElse(toLiteral(stringToDate, DateType))
case "TIMESTAMP_NTZ" =>
val specialTs = convertSpecialTimestampNTZ(value).map(Literal(_, TimestampNTZType))
specialTs.getOrElse(toLiteral(stringToTimestampWithoutTimeZone, TimestampNTZType))
case "TIMESTAMP" => case "TIMESTAMP" =>
def constructTimestampLTZLiteral(value: String): Literal = { def constructTimestampLTZLiteral(value: String): Literal = {
val zoneId = getZoneId(conf.sessionLocalTimeZone) val zoneId = getZoneId(conf.sessionLocalTimeZone)
@ -2525,6 +2528,7 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with SQLConfHelper with Logg
case ("double", Nil) => DoubleType case ("double", Nil) => DoubleType
case ("date", Nil) => DateType case ("date", Nil) => DateType
case ("timestamp", Nil) => SQLConf.get.timestampType case ("timestamp", Nil) => SQLConf.get.timestampType
case ("timestamp_ntz", Nil) => TimestampNTZType
case ("string", Nil) => StringType case ("string", Nil) => StringType
case ("character" | "char", length :: Nil) => CharType(length.getText.toInt) case ("character" | "char", length :: Nil) => CharType(length.getText.toInt)
case ("varchar", length :: Nil) => VarcharType(length.getText.toInt) case ("varchar", length :: Nil) => VarcharType(length.getText.toInt)

View file

@ -58,6 +58,7 @@ class DataTypeParserSuite extends SparkFunSuite with SQLHelper {
checkDataType("deC", DecimalType.USER_DEFAULT) checkDataType("deC", DecimalType.USER_DEFAULT)
checkDataType("DATE", DateType) checkDataType("DATE", DateType)
checkDataType("timestamp", TimestampType) checkDataType("timestamp", TimestampType)
checkDataType("timestamp_ntz", TimestampNTZType)
checkDataType("string", StringType) checkDataType("string", StringType)
checkDataType("ChaR(5)", CharType(5)) checkDataType("ChaR(5)", CharType(5))
checkDataType("ChaRacter(5)", CharType(5)) checkDataType("ChaRacter(5)", CharType(5))

View file

@ -465,6 +465,9 @@ class ExpressionParserSuite extends AnalysisTest {
intercept("timestamP '2016-33-11 20:54:00.000'", "Cannot parse the TIMESTAMP value") intercept("timestamP '2016-33-11 20:54:00.000'", "Cannot parse the TIMESTAMP value")
// Timestamp without time zone // Timestamp without time zone
assertEqual("tImEstAmp_Ntz '2016-03-11 20:54:00.000'",
Literal(LocalDateTime.parse("2016-03-11T20:54:00.000")))
intercept("tImEstAmp_Ntz '2016-33-11 20:54:00.000'", "Cannot parse the TIMESTAMP_NTZ value")
withSQLConf(SQLConf.TIMESTAMP_TYPE.key -> TimestampTypes.TIMESTAMP_NTZ.toString) { withSQLConf(SQLConf.TIMESTAMP_TYPE.key -> TimestampTypes.TIMESTAMP_NTZ.toString) {
assertEqual("tImEstAmp '2016-03-11 20:54:00.000'", assertEqual("tImEstAmp '2016-03-11 20:54:00.000'",
Literal(LocalDateTime.parse("2016-03-11T20:54:00.000"))) Literal(LocalDateTime.parse("2016-03-11T20:54:00.000")))