Skip to content

Commit 6d625cc

Browse files
ulysses-youdongjoon-hyun
authored andcommitted
[SPARK-33469][SQL] Add current_timezone function
### What changes were proposed in this pull request? Add a `CurrentTimeZone` function and replace the value at `Optimizer` side. ### Why are the changes needed? Let user get current timezone easily. Then user can call ``` SELECT current_timezone() ``` Presto: https://prestodb.io/docs/current/functions/datetime.html SQL Server: https://docs.microsoft.com/en-us/sql/t-sql/functions/current-timezone-transact-sql?view=sql-server-ver15 ### Does this PR introduce _any_ user-facing change? Yes, a new function. ### How was this patch tested? Add test. Closes #30400 from ulysses-you/SPARK-33469. Lead-authored-by: ulysses <[email protected]> Co-authored-by: ulysses-you <[email protected]> Signed-off-by: Dongjoon Hyun <[email protected]>
1 parent d338af3 commit 6d625cc

File tree

7 files changed

+45
-2
lines changed

7 files changed

+45
-2
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/FunctionRegistry.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ object FunctionRegistry {
391391
expression[AddMonths]("add_months"),
392392
expression[CurrentDate]("current_date"),
393393
expression[CurrentTimestamp]("current_timestamp"),
394+
expression[CurrentTimeZone]("current_timezone"),
394395
expression[DateDiff]("datediff"),
395396
expression[DateAdd]("date_add"),
396397
expression[DateFormatClass]("date_format"),

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/datetimeExpressions.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,21 @@ trait TimestampFormatterHelper extends TimeZoneAwareExpression {
7373
}
7474
}
7575

76+
@ExpressionDescription(
77+
usage = "_FUNC_() - Returns the current session local timezone.",
78+
examples = """
79+
Examples:
80+
> SELECT _FUNC_();
81+
Asia/Shanghai
82+
""",
83+
group = "datetime_funcs",
84+
since = "3.1.0")
85+
case class CurrentTimeZone() extends LeafExpression with Unevaluable {
86+
override def nullable: Boolean = false
87+
override def dataType: DataType = StringType
88+
override def prettyName: String = "current_timezone"
89+
}
90+
7691
/**
7792
* Returns the current date at the start of query evaluation.
7893
* There is no code generation since this expression should get constant folded by the optimizer.

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/finishAnalysis.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import org.apache.spark.sql.catalyst.plans.logical._
2525
import org.apache.spark.sql.catalyst.rules._
2626
import org.apache.spark.sql.catalyst.util.DateTimeUtils
2727
import org.apache.spark.sql.connector.catalog.CatalogManager
28+
import org.apache.spark.sql.internal.SQLConf
2829
import org.apache.spark.sql.types._
2930

3031

@@ -75,6 +76,7 @@ object ComputeCurrentTime extends Rule[LogicalPlan] {
7576
val timeExpr = CurrentTimestamp()
7677
val timestamp = timeExpr.eval(EmptyRow).asInstanceOf[Long]
7778
val currentTime = Literal.create(timestamp, timeExpr.dataType)
79+
val timezone = Literal.create(SQLConf.get.sessionLocalTimeZone, StringType)
7880

7981
plan transformAllExpressions {
8082
case currentDate @ CurrentDate(Some(timeZoneId)) =>
@@ -84,6 +86,7 @@ object ComputeCurrentTime extends Rule[LogicalPlan] {
8486
DateType)
8587
})
8688
case CurrentTimestamp() | Now() => currentTime
89+
case CurrentTimeZone() => timezone
8790
}
8891
}
8992
}

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/ComputeCurrentTimeSuite.scala

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ package org.apache.spark.sql.catalyst.optimizer
2020
import java.time.ZoneId
2121

2222
import org.apache.spark.sql.catalyst.dsl.plans._
23-
import org.apache.spark.sql.catalyst.expressions.{Alias, CurrentDate, CurrentTimestamp, Literal}
23+
import org.apache.spark.sql.catalyst.expressions.{Alias, CurrentDate, CurrentTimestamp, CurrentTimeZone, Literal}
2424
import org.apache.spark.sql.catalyst.plans.PlanTest
2525
import org.apache.spark.sql.catalyst.plans.logical.{LocalRelation, LogicalPlan, Project}
2626
import org.apache.spark.sql.catalyst.rules.RuleExecutor
2727
import org.apache.spark.sql.catalyst.util.DateTimeUtils
28+
import org.apache.spark.sql.internal.SQLConf
29+
import org.apache.spark.unsafe.types.UTF8String
2830

2931
class ComputeCurrentTimeSuite extends PlanTest {
3032
object Optimize extends RuleExecutor[LogicalPlan] {
@@ -67,4 +69,16 @@ class ComputeCurrentTimeSuite extends PlanTest {
6769
assert(lits(1) >= min && lits(1) <= max)
6870
assert(lits(0) == lits(1))
6971
}
72+
73+
test("SPARK-33469: Add current_timezone function") {
74+
val in = Project(Seq(Alias(CurrentTimeZone(), "c")()), LocalRelation())
75+
val plan = Optimize.execute(in.analyze).asInstanceOf[Project]
76+
val lits = new scala.collection.mutable.ArrayBuffer[String]
77+
plan.transformAllExpressions { case e: Literal =>
78+
lits += e.value.asInstanceOf[UTF8String].toString
79+
e
80+
}
81+
assert(lits.size == 1)
82+
assert(lits.head == SQLConf.get.sessionLocalTimeZone)
83+
}
7084
}

sql/core/src/test/resources/sql-functions/sql-expression-schema.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!-- Automatically generated by ExpressionsSchemaSuite -->
22
## Summary
3-
- Number of queries: 341
3+
- Number of queries: 342
44
- Number of expressions that missing example: 13
55
- Expressions missing examples: bigint,binary,boolean,date,decimal,double,float,int,smallint,string,timestamp,tinyint,window
66
## Schema of Built-in Functions
@@ -86,6 +86,7 @@
8686
| org.apache.spark.sql.catalyst.expressions.CurrentCatalog | current_catalog | SELECT current_catalog() | struct<current_catalog():string> |
8787
| org.apache.spark.sql.catalyst.expressions.CurrentDatabase | current_database | SELECT current_database() | struct<current_database():string> |
8888
| org.apache.spark.sql.catalyst.expressions.CurrentDate | current_date | SELECT current_date() | struct<current_date():date> |
89+
| org.apache.spark.sql.catalyst.expressions.CurrentTimeZone | current_timezone | SELECT current_timezone() | struct<current_timezone():string> |
8990
| org.apache.spark.sql.catalyst.expressions.CurrentTimestamp | current_timestamp | SELECT current_timestamp() | struct<current_timestamp():timestamp> |
9091
| org.apache.spark.sql.catalyst.expressions.DateAdd | date_add | SELECT date_add('2016-07-30', 1) | struct<date_add(CAST(2016-07-30 AS DATE), 1):date> |
9192
| org.apache.spark.sql.catalyst.expressions.DateDiff | datediff | SELECT datediff('2009-07-31', '2009-07-30') | struct<datediff(CAST(2009-07-31 AS DATE), CAST(2009-07-30 AS DATE)):int> |

sql/core/src/test/scala/org/apache/spark/sql/DatasetSuite.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,14 @@ class DatasetSuite extends QueryTest
19471947
df.where($"zoo".contains(Array('a', 'b'))),
19481948
Seq(Row("abc")))
19491949
}
1950+
1951+
test("SPARK-33469: Add current_timezone function") {
1952+
val df = Seq(1).toDF("c")
1953+
withSQLConf(SQLConf.SESSION_LOCAL_TIMEZONE.key -> "Asia/Shanghai") {
1954+
val timezone = df.selectExpr("current_timezone()").collect().head.getString(0)
1955+
assert(timezone == "Asia/Shanghai")
1956+
}
1957+
}
19501958
}
19511959

19521960
object AssertExecutionId {

sql/core/src/test/scala/org/apache/spark/sql/expressions/ExpressionInfoSuite.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ class ExpressionInfoSuite extends SparkFunSuite with SharedSparkSession {
149149
"org.apache.spark.sql.catalyst.expressions.UnixTimestamp",
150150
"org.apache.spark.sql.catalyst.expressions.CurrentDate",
151151
"org.apache.spark.sql.catalyst.expressions.CurrentTimestamp",
152+
"org.apache.spark.sql.catalyst.expressions.CurrentTimeZone",
152153
"org.apache.spark.sql.catalyst.expressions.Now",
153154
// Random output without a seed
154155
"org.apache.spark.sql.catalyst.expressions.Rand",

0 commit comments

Comments
 (0)