Skip to content

[SPARK-31797][SQL] Adds TIMESTAMP_SECONDS, TIMESTAMP_MILLIS and TIMESTAMP_MICROS functions #28534

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,9 @@ object FunctionRegistry {
expression[MakeInterval]("make_interval"),
expression[DatePart]("date_part"),
expression[Extract]("extract"),
expression[SecondsToTimestamp]("timestamp_seconds"),
expression[MillisToTimestamp]("timestamp_millis"),
expression[MicrosToTimestamp]("timestamp_micros"),

// collection functions
expression[CreateArray]("array"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,83 @@ case class DayOfYear(child: Expression) extends UnaryExpression with ImplicitCas
}
}

abstract class NumberToTimestampBase extends UnaryExpression
with ExpectsInputTypes {

protected def upScaleFactor: Long

override def inputTypes: Seq[AbstractDataType] = Seq(IntegralType)

override def dataType: DataType = TimestampType

override def nullSafeEval(input: Any): Any = {
Math.multiplyExact(input.asInstanceOf[Number].longValue(), upScaleFactor)
}

override protected def doGenCode(ctx: CodegenContext, ev: ExprCode): ExprCode = {
if (upScaleFactor == 1) {
defineCodeGen(ctx, ev, c => c)
} else {
defineCodeGen(ctx, ev, c => s"java.lang.Math.multiplyExact($c, ${upScaleFactor}L)")
}
}
}

@ExpressionDescription(
usage = "_FUNC_(seconds) - Creates timestamp from the number of seconds since UTC epoch.",
examples = """
Examples:
> SELECT _FUNC_(1230219000);
2008-12-25 07:30:00
""",
group = "datetime_funcs",
since = "3.1.0")
case class SecondsToTimestamp(child: Expression)
extends NumberToTimestampBase {

override def upScaleFactor: Long = MICROS_PER_SECOND

override def prettyName: String = "timestamp_seconds"
}

// scalastyle:off line.size.limit
@ExpressionDescription(
usage = "_FUNC_(milliseconds) - Creates timestamp from the number of milliseconds since UTC epoch.",
examples = """
Examples:
> SELECT _FUNC_(1230219000123);
2008-12-25 07:30:00.123
""",
group = "datetime_funcs",
since = "3.1.0")
// scalastyle:on line.size.limit
case class MillisToTimestamp(child: Expression)
extends NumberToTimestampBase {

override def upScaleFactor: Long = MICROS_PER_MILLIS

override def prettyName: String = "timestamp_millis"
}

// scalastyle:off line.size.limit
@ExpressionDescription(
usage = "_FUNC_(microseconds) - Creates timestamp from the number of microseconds since UTC epoch.",
examples = """
Examples:
> SELECT _FUNC_(1230219000123123);
2008-12-25 07:30:00.123123
""",
group = "datetime_funcs",
since = "3.1.0")
// scalastyle:on line.size.limit
case class MicrosToTimestamp(child: Expression)
extends NumberToTimestampBase {

override def upScaleFactor: Long = 1L

override def prettyName: String = "timestamp_micros"
}

@ExpressionDescription(
usage = "_FUNC_(date) - Returns the year component of the date/timestamp.",
examples = """
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1146,4 +1146,26 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
Literal("yyyy-MM-dd'T'HH:mm:ss.SSSz")), "Fail to parse")
}
}

test("SPARK-31710:Adds TIMESTAMP_SECONDS, " +
"TIMESTAMP_MILLIS and TIMESTAMP_MICROS functions") {
checkEvaluation(SecondsToTimestamp(Literal(1230219000)), 1230219000L * MICROS_PER_SECOND)
checkEvaluation(SecondsToTimestamp(Literal(-1230219000)), -1230219000L * MICROS_PER_SECOND)
checkEvaluation(SecondsToTimestamp(Literal(null, IntegerType)), null)
checkEvaluation(MillisToTimestamp(Literal(1230219000123L)), 1230219000123L * MICROS_PER_MILLIS)
checkEvaluation(MillisToTimestamp(
Literal(-1230219000123L)), -1230219000123L * MICROS_PER_MILLIS)
checkEvaluation(MillisToTimestamp(Literal(null, IntegerType)), null)
checkEvaluation(MicrosToTimestamp(Literal(1230219000123123L)), 1230219000123123L)
checkEvaluation(MicrosToTimestamp(Literal(-1230219000123123L)), -1230219000123123L)
checkEvaluation(MicrosToTimestamp(Literal(null, IntegerType)), null)
checkExceptionInExpression[ArithmeticException](
SecondsToTimestamp(Literal(1230219000123123L)), "long overflow")
checkExceptionInExpression[ArithmeticException](
SecondsToTimestamp(Literal(-1230219000123123L)), "long overflow")
checkExceptionInExpression[ArithmeticException](
MillisToTimestamp(Literal(92233720368547758L)), "long overflow")
checkExceptionInExpression[ArithmeticException](
MillisToTimestamp(Literal(-92233720368547758L)), "long overflow")
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!-- Automatically generated by ExpressionsSchemaSuite -->
## Summary
- Number of queries: 333
- Number of queries: 336
- Number of expressions that missing example: 34
- Expressions missing examples: and,string,tinyint,double,smallint,date,decimal,boolean,float,binary,bigint,int,timestamp,cume_dist,dense_rank,input_file_block_length,input_file_block_start,input_file_name,lag,lead,monotonically_increasing_id,ntile,struct,!,not,or,percent_rank,rank,row_number,spark_partition_id,version,window,positive,count_min_sketch
## Schema of Built-in Functions
Expand Down Expand Up @@ -175,6 +175,8 @@
| org.apache.spark.sql.catalyst.expressions.MapValues | map_values | SELECT map_values(map(1, 'a', 2, 'b')) | struct<map_values(map(1, a, 2, b)):array<string>> |
| org.apache.spark.sql.catalyst.expressions.MapZipWith | map_zip_with | SELECT map_zip_with(map(1, 'a', 2, 'b'), map(1, 'x', 2, 'y'), (k, v1, v2) -> concat(v1, v2)) | struct<map_zip_with(map(1, a, 2, b), map(1, x, 2, y), lambdafunction(concat(namedlambdavariable(), namedlambdavariable()), namedlambdavariable(), namedlambdavariable(), namedlambdavariable())):map<int,string>> |
| org.apache.spark.sql.catalyst.expressions.Md5 | md5 | SELECT md5('Spark') | struct<md5(CAST(Spark AS BINARY)):string> |
| org.apache.spark.sql.catalyst.expressions.MicrosToTimestamp | timestamp_micros | SELECT timestamp_micros(1230219000123123) | struct<timestamp_micros(1230219000123123):timestamp> |
| org.apache.spark.sql.catalyst.expressions.MillisToTimestamp | timestamp_millis | SELECT timestamp_millis(1230219000123) | struct<timestamp_millis(1230219000123):timestamp> |
| org.apache.spark.sql.catalyst.expressions.Minute | minute | SELECT minute('2009-07-30 12:58:59') | struct<minute(CAST(2009-07-30 12:58:59 AS TIMESTAMP)):int> |
| org.apache.spark.sql.catalyst.expressions.MonotonicallyIncreasingID | monotonically_increasing_id | N/A | N/A |
| org.apache.spark.sql.catalyst.expressions.Month | month | SELECT month('2016-07-30') | struct<month(CAST(2016-07-30 AS DATE)):int> |
Expand Down Expand Up @@ -223,6 +225,7 @@
| org.apache.spark.sql.catalyst.expressions.SchemaOfCsv | schema_of_csv | SELECT schema_of_csv('1,abc') | struct<schema_of_csv(1,abc):string> |
| org.apache.spark.sql.catalyst.expressions.SchemaOfJson | schema_of_json | SELECT schema_of_json('[{"col":0}]') | struct<schema_of_json([{"col":0}]):string> |
| org.apache.spark.sql.catalyst.expressions.Second | second | SELECT second('2009-07-30 12:58:59') | struct<second(CAST(2009-07-30 12:58:59 AS TIMESTAMP)):int> |
| org.apache.spark.sql.catalyst.expressions.SecondsToTimestamp | timestamp_seconds | SELECT timestamp_seconds(1230219000) | struct<timestamp_seconds(1230219000):timestamp> |
| org.apache.spark.sql.catalyst.expressions.Sentences | sentences | SELECT sentences('Hi there! Good morning.') | struct<sentences(Hi there! Good morning., , ):array<array<string>>> |
| org.apache.spark.sql.catalyst.expressions.Sequence | sequence | SELECT sequence(1, 5) | struct<sequence(1, 5):array<int>> |
| org.apache.spark.sql.catalyst.expressions.Sha1 | sha1 | SELECT sha1('Spark') | struct<sha1(CAST(Spark AS BINARY)):string> |
Expand Down
10 changes: 10 additions & 0 deletions sql/core/src/test/resources/sql-tests/inputs/datetime.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
-- date time functions

-- [SPARK-31710] TIMESTAMP_SECONDS, TIMESTAMP_MILLISECONDS and TIMESTAMP_MICROSECONDS to timestamp transfer
select TIMESTAMP_SECONDS(1230219000),TIMESTAMP_SECONDS(-1230219000),TIMESTAMP_SECONDS(null);
select TIMESTAMP_MILLIS(1230219000123),TIMESTAMP_MILLIS(-1230219000123),TIMESTAMP_MILLIS(null);
select TIMESTAMP_MICROS(1230219000123123),TIMESTAMP_MICROS(-1230219000123123),TIMESTAMP_MICROS(null);
-- overflow exception:
select TIMESTAMP_SECONDS(1230219000123123);
select TIMESTAMP_SECONDS(-1230219000123123);
select TIMESTAMP_MILLIS(92233720368547758);
select TIMESTAMP_MILLIS(-92233720368547758);

-- [SPARK-16836] current_date and current_timestamp literals
select current_date = current_date(), current_timestamp = current_timestamp();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,65 @@
-- Automatically generated by SQLQueryTestSuite
-- Number of queries: 91
-- Number of queries: 92


-- !query
select TIMESTAMP_SECONDS(1230219000),TIMESTAMP_SECONDS(-1230219000),TIMESTAMP_SECONDS(null)
-- !query schema
struct<timestamp_seconds(1230219000):timestamp,timestamp_seconds(-1230219000):timestamp,timestamp_seconds(CAST(NULL AS INT)):timestamp>
-- !query output
2008-12-25 07:30:00 1931-01-07 00:30:00 NULL


-- !query
select TIMESTAMP_MILLIS(1230219000123),TIMESTAMP_MILLIS(-1230219000123),TIMESTAMP_MILLIS(null)
-- !query schema
struct<timestamp_millis(1230219000123):timestamp,timestamp_millis(-1230219000123):timestamp,timestamp_millis(CAST(NULL AS INT)):timestamp>
-- !query output
2008-12-25 07:30:00.123 1931-01-07 00:29:59.877 NULL


-- !query
select TIMESTAMP_MICROS(1230219000123123),TIMESTAMP_MICROS(-1230219000123123),TIMESTAMP_MICROS(null)
-- !query schema
struct<timestamp_micros(1230219000123123):timestamp,timestamp_micros(-1230219000123123):timestamp,timestamp_micros(CAST(NULL AS INT)):timestamp>
-- !query output
2008-12-25 07:30:00.123123 1931-01-07 00:29:59.876877 NULL


-- !query
select TIMESTAMP_SECONDS(1230219000123123)
-- !query schema
struct<>
-- !query output
java.lang.ArithmeticException
long overflow


-- !query
select TIMESTAMP_SECONDS(-1230219000123123)
-- !query schema
struct<>
-- !query output
java.lang.ArithmeticException
long overflow


-- !query
select TIMESTAMP_MILLIS(92233720368547758)
-- !query schema
struct<>
-- !query output
java.lang.ArithmeticException
long overflow


-- !query
select TIMESTAMP_MILLIS(-92233720368547758)
-- !query schema
struct<>
-- !query output
java.lang.ArithmeticException
long overflow


-- !query
Expand Down
60 changes: 60 additions & 0 deletions sql/core/src/test/resources/sql-tests/results/datetime.sql.out
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,66 @@
-- Number of queries: 91


-- !query
select TIMESTAMP_SECONDS(1230219000),TIMESTAMP_SECONDS(-1230219000),TIMESTAMP_SECONDS(null)
-- !query schema
struct<timestamp_seconds(1230219000):timestamp,timestamp_seconds(-1230219000):timestamp,timestamp_seconds(CAST(NULL AS INT)):timestamp>
-- !query output
2008-12-25 07:30:00 1931-01-07 00:30:00 NULL


-- !query
select TIMESTAMP_MILLIS(1230219000123),TIMESTAMP_MILLIS(-1230219000123),TIMESTAMP_MILLIS(null)
-- !query schema
struct<timestamp_millis(1230219000123):timestamp,timestamp_millis(-1230219000123):timestamp,timestamp_millis(CAST(NULL AS INT)):timestamp>
-- !query output
2008-12-25 07:30:00.123 1931-01-07 00:29:59.877 NULL


-- !query
select TIMESTAMP_MICROS(1230219000123123),TIMESTAMP_MICROS(-1230219000123123),TIMESTAMP_MICROS(null)
-- !query schema
struct<timestamp_micros(1230219000123123):timestamp,timestamp_micros(-1230219000123123):timestamp,timestamp_micros(CAST(NULL AS INT)):timestamp>
-- !query output
2008-12-25 07:30:00.123123 1931-01-07 00:29:59.876877 NULL


-- !query
select TIMESTAMP_SECONDS(1230219000123123)
-- !query schema
struct<>
-- !query output
java.lang.ArithmeticException
long overflow


-- !query
select TIMESTAMP_SECONDS(-1230219000123123)
-- !query schema
struct<>
-- !query output
java.lang.ArithmeticException
long overflow


-- !query
select TIMESTAMP_MILLIS(92233720368547758)
-- !query schema
struct<>
-- !query output
java.lang.ArithmeticException
long overflow


-- !query
select TIMESTAMP_MILLIS(-92233720368547758)
-- !query schema
struct<>
-- !query output
java.lang.ArithmeticException
long overflow


-- !query
select current_date = current_date(), current_timestamp = current_timestamp()
-- !query schema
Expand Down