Skip to content

Commit 104887f

Browse files
compheadalamb
authored andcommitted
Implement current_date scalar function (apache#4022)
* current_date impl * Update datafusion/expr/src/expr_fn.rs Co-authored-by: Andrew Lamb <[email protected]> * Update datafusion/physical-expr/src/functions.rs Co-authored-by: Andrew Lamb <[email protected]> Co-authored-by: Andrew Lamb <[email protected]>
1 parent b4f61f5 commit 104887f

File tree

8 files changed

+75
-0
lines changed

8 files changed

+75
-0
lines changed

datafusion/core/src/physical_plan/functions.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ pub fn return_type(
211211
BuiltinScalarFunction::UtcTimestamp => {
212212
Ok(DataType::Timestamp(TimeUnit::Nanosecond, None))
213213
}
214+
BuiltinScalarFunction::CurrentDate => Ok(DataType::Date32),
214215
BuiltinScalarFunction::Translate => {
215216
utf8_to_str_type(&input_expr_types[0], "translate")
216217
}
@@ -893,6 +894,12 @@ pub fn create_physical_fun(
893894
execution_props.query_execution_start_time,
894895
))
895896
}
897+
BuiltinScalarFunction::CurrentDate => {
898+
// bind value for current_date at plan time
899+
Arc::new(datetime_expressions::make_current_date(
900+
execution_props.query_execution_start_time,
901+
))
902+
}
896903
BuiltinScalarFunction::InitCap => Arc::new(|args| match args[0].data_type() {
897904
DataType::Utf8 => {
898905
make_scalar_function(string_expressions::initcap::<i32>)(args)

datafusion/core/tests/sql/timestamp.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,3 +814,35 @@ async fn group_by_timestamp_millis() -> Result<()> {
814814
assert_batches_eq!(expected, &actual);
815815
Ok(())
816816
}
817+
818+
#[tokio::test]
819+
async fn test_current_date() -> Result<()> {
820+
let ctx = SessionContext::new();
821+
822+
let sql = "select current_date() dt";
823+
let results = execute_to_batches(&ctx, sql).await;
824+
assert_eq!(
825+
results[0]
826+
.schema()
827+
.field_with_name("dt")
828+
.unwrap()
829+
.data_type()
830+
.to_owned(),
831+
DataType::Date32
832+
);
833+
834+
let sql = "select case when current_date() = cast(now() as date) then 'OK' else 'FAIL' end result";
835+
let results = execute_to_batches(&ctx, sql).await;
836+
837+
let expected = vec![
838+
"+--------+",
839+
"| result |",
840+
"+--------+",
841+
"| OK |",
842+
"+--------+",
843+
];
844+
845+
assert_batches_eq!(expected, &results);
846+
847+
Ok(())
848+
}

datafusion/expr/src/built_in_function.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,10 @@ pub enum BuiltinScalarFunction {
150150
ToTimestampSeconds,
151151
///now
152152
Now,
153+
///utctimestamp
153154
UtcTimestamp,
155+
///current_date
156+
CurrentDate,
154157
/// translate
155158
Translate,
156159
/// trim
@@ -170,6 +173,7 @@ impl BuiltinScalarFunction {
170173
BuiltinScalarFunction::Random
171174
| BuiltinScalarFunction::Now
172175
| BuiltinScalarFunction::UtcTimestamp
176+
| BuiltinScalarFunction::CurrentDate
173177
)
174178
}
175179
/// Returns the [Volatility] of the builtin function.
@@ -244,6 +248,7 @@ impl BuiltinScalarFunction {
244248
// Stable builtin functions
245249
BuiltinScalarFunction::Now => Volatility::Stable,
246250
BuiltinScalarFunction::UtcTimestamp => Volatility::Stable,
251+
BuiltinScalarFunction::CurrentDate => Volatility::Stable,
247252

248253
// Volatile builtin functions
249254
BuiltinScalarFunction::Random => Volatility::Volatile,
@@ -297,6 +302,7 @@ impl FromStr for BuiltinScalarFunction {
297302
"concat" => BuiltinScalarFunction::Concat,
298303
"concat_ws" => BuiltinScalarFunction::ConcatWithSeparator,
299304
"chr" => BuiltinScalarFunction::Chr,
305+
"current_date" => BuiltinScalarFunction::CurrentDate,
300306
"date_part" | "datepart" => BuiltinScalarFunction::DatePart,
301307
"date_trunc" | "datetrunc" => BuiltinScalarFunction::DateTrunc,
302308
"initcap" => BuiltinScalarFunction::InitCap,

datafusion/expr/src/expr_fn.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,14 @@ pub fn coalesce(args: Vec<Expr>) -> Expr {
324324
}
325325
}
326326

327+
/// Returns current UTC date as a [`DataType::Date32`] value
328+
pub fn current_date() -> Expr {
329+
Expr::ScalarFunction {
330+
fun: built_in_function::BuiltinScalarFunction::CurrentDate,
331+
args: vec![],
332+
}
333+
}
334+
327335
#[cfg(test)]
328336
mod test {
329337
use super::*;

datafusion/physical-expr/src/datetime_expressions.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,24 @@ pub fn make_now(
356356
}
357357
}
358358

359+
/// Create an implementation of `current_date()` that always returns the
360+
/// specified current date.
361+
///
362+
/// The semantics of `current_date()` require it to return the same value
363+
/// wherever it appears within a single statement. This value is
364+
/// chosen during planning time.
365+
pub fn make_current_date(
366+
now_ts: DateTime<Utc>,
367+
) -> impl Fn(&[ColumnarValue]) -> Result<ColumnarValue> {
368+
let days = Some(
369+
now_ts.num_days_from_ce()
370+
- NaiveDate::from_ymd_opt(1970, 1, 1)
371+
.unwrap()
372+
.num_days_from_ce(),
373+
);
374+
move |_arg| Ok(ColumnarValue::Scalar(ScalarValue::Date32(days)))
375+
}
376+
359377
fn quarter_month(date: &NaiveDateTime) -> u32 {
360378
1 + 3 * ((date.month() - 1) / 3)
361379
}

datafusion/proto/proto/datafusion.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ enum ScalarFunction {
189189
Trim=61;
190190
Upper=62;
191191
Coalesce=63;
192+
// Upstream
193+
CurrentDate=70;
192194
// Cubesql
193195
UtcTimestamp=101;
194196
ToDayInterval=102;

datafusion/proto/src/from_proto.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ impl From<&protobuf::ScalarFunction> for BuiltinScalarFunction {
428428
ScalarFunction::ToTimestampMicros => Self::ToTimestampMicros,
429429
ScalarFunction::ToTimestampSeconds => Self::ToTimestampSeconds,
430430
ScalarFunction::Now => Self::Now,
431+
ScalarFunction::CurrentDate => Self::CurrentDate,
431432
ScalarFunction::Translate => Self::Translate,
432433
ScalarFunction::RegexpMatch => Self::RegexpMatch,
433434
ScalarFunction::Coalesce => Self::Coalesce,

datafusion/proto/src/to_proto.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,7 @@ impl TryFrom<&BuiltinScalarFunction> for protobuf::ScalarFunction {
10841084
BuiltinScalarFunction::ToTimestampMicros => Self::ToTimestampMicros,
10851085
BuiltinScalarFunction::ToTimestampSeconds => Self::ToTimestampSeconds,
10861086
BuiltinScalarFunction::Now => Self::Now,
1087+
BuiltinScalarFunction::CurrentDate => Self::CurrentDate,
10871088
BuiltinScalarFunction::Translate => Self::Translate,
10881089
BuiltinScalarFunction::RegexpMatch => Self::RegexpMatch,
10891090
BuiltinScalarFunction::Coalesce => Self::Coalesce,

0 commit comments

Comments
 (0)