This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-datafusion.git


The following commit(s) were added to refs/heads/master by this push:
     new f91eddfdc Implement current_date scalar function (#4022)
f91eddfdc is described below

commit f91eddfdc9f3e805abc1cb7186aec31ed211c22e
Author: comphead <[email protected]>
AuthorDate: Mon Oct 31 03:32:36 2022 -0700

    Implement current_date scalar function (#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]>
---
 datafusion/core/tests/sql/timestamp.rs             | 32 ++++++++++++++++++++++
 datafusion/expr/src/built_in_function.rs           |  8 +++++-
 datafusion/expr/src/expr_fn.rs                     |  8 ++++++
 datafusion/expr/src/function.rs                    |  1 +
 .../physical-expr/src/datetime_expressions.rs      | 15 ++++++++++
 datafusion/physical-expr/src/functions.rs          |  6 ++++
 datafusion/proto/proto/datafusion.proto            |  1 +
 datafusion/proto/src/from_proto.rs                 |  1 +
 datafusion/proto/src/generated/pbjson.rs           |  3 ++
 datafusion/proto/src/generated/prost.rs            |  2 ++
 datafusion/proto/src/to_proto.rs                   |  1 +
 11 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/datafusion/core/tests/sql/timestamp.rs 
b/datafusion/core/tests/sql/timestamp.rs
index b6cf2bb67..890950200 100644
--- a/datafusion/core/tests/sql/timestamp.rs
+++ b/datafusion/core/tests/sql/timestamp.rs
@@ -1619,3 +1619,35 @@ async fn test_cast_to_timetz_should_not_work() -> 
Result<()> {
     );
     Ok(())
 }
+
+#[tokio::test]
+async fn test_current_date() -> Result<()> {
+    let ctx = SessionContext::new();
+
+    let sql = "select current_date() dt";
+    let results = execute_to_batches(&ctx, sql).await;
+    assert_eq!(
+        results[0]
+            .schema()
+            .field_with_name("dt")
+            .unwrap()
+            .data_type()
+            .to_owned(),
+        DataType::Date32
+    );
+
+    let sql = "select case when current_date() = cast(now() as date) then 'OK' 
else 'FAIL' end result";
+    let results = execute_to_batches(&ctx, sql).await;
+
+    let expected = vec![
+        "+--------+",
+        "| result |",
+        "+--------+",
+        "| OK     |",
+        "+--------+",
+    ];
+
+    assert_batches_eq!(expected, &results);
+
+    Ok(())
+}
diff --git a/datafusion/expr/src/built_in_function.rs 
b/datafusion/expr/src/built_in_function.rs
index fa3adbab6..796f0c909 100644
--- a/datafusion/expr/src/built_in_function.rs
+++ b/datafusion/expr/src/built_in_function.rs
@@ -156,6 +156,8 @@ pub enum BuiltinScalarFunction {
     FromUnixtime,
     ///now
     Now,
+    ///current_date
+    CurrentDate,
     /// translate
     Translate,
     /// trim
@@ -176,7 +178,9 @@ impl BuiltinScalarFunction {
     pub fn supports_zero_argument(&self) -> bool {
         matches!(
             self,
-            BuiltinScalarFunction::Random | BuiltinScalarFunction::Now
+            BuiltinScalarFunction::Random
+                | BuiltinScalarFunction::Now
+                | BuiltinScalarFunction::CurrentDate
         )
     }
     /// Returns the [Volatility] of the builtin function.
@@ -254,6 +258,7 @@ impl BuiltinScalarFunction {
 
             // Stable builtin functions
             BuiltinScalarFunction::Now => Volatility::Stable,
+            BuiltinScalarFunction::CurrentDate => Volatility::Stable,
 
             // Volatile builtin functions
             BuiltinScalarFunction::Random => Volatility::Volatile,
@@ -309,6 +314,7 @@ impl FromStr for BuiltinScalarFunction {
             "concat" => BuiltinScalarFunction::Concat,
             "concat_ws" => BuiltinScalarFunction::ConcatWithSeparator,
             "chr" => BuiltinScalarFunction::Chr,
+            "current_date" => BuiltinScalarFunction::CurrentDate,
             "date_part" | "datepart" => BuiltinScalarFunction::DatePart,
             "date_trunc" | "datetrunc" => BuiltinScalarFunction::DateTrunc,
             "date_bin" => BuiltinScalarFunction::DateBin,
diff --git a/datafusion/expr/src/expr_fn.rs b/datafusion/expr/src/expr_fn.rs
index 0685ec835..cfd043a3a 100644
--- a/datafusion/expr/src/expr_fn.rs
+++ b/datafusion/expr/src/expr_fn.rs
@@ -452,6 +452,14 @@ pub fn now() -> Expr {
     }
 }
 
+/// Returns current UTC date as a [`DataType::Date32`] value
+pub fn current_date() -> Expr {
+    Expr::ScalarFunction {
+        fun: BuiltinScalarFunction::CurrentDate,
+        args: vec![],
+    }
+}
+
 /// Create a CASE WHEN statement with literal WHEN expressions for comparison 
to the base expression.
 pub fn case(expr: Expr) -> CaseBuilder {
     CaseBuilder::new(Some(Box::new(expr)), vec![], vec![], None)
diff --git a/datafusion/expr/src/function.rs b/datafusion/expr/src/function.rs
index e39339c20..4a47d8209 100644
--- a/datafusion/expr/src/function.rs
+++ b/datafusion/expr/src/function.rs
@@ -221,6 +221,7 @@ pub fn return_type(
             TimeUnit::Nanosecond,
             Some("UTC".to_owned()),
         )),
+        BuiltinScalarFunction::CurrentDate => Ok(DataType::Date32),
         BuiltinScalarFunction::Translate => {
             utf8_to_str_type(&input_expr_types[0], "translate")
         }
diff --git a/datafusion/physical-expr/src/datetime_expressions.rs 
b/datafusion/physical-expr/src/datetime_expressions.rs
index 0214d1bfb..c243cf587 100644
--- a/datafusion/physical-expr/src/datetime_expressions.rs
+++ b/datafusion/physical-expr/src/datetime_expressions.rs
@@ -184,6 +184,21 @@ pub fn make_now(
     }
 }
 
+/// Create an implementation of `current_date()` that always returns the
+/// specified current date.
+///
+/// The semantics of `current_date()` require it to return the same value
+/// wherever it appears within a single statement. This value is
+/// chosen during planning time.
+pub fn make_current_date(
+    now_ts: DateTime<Utc>,
+) -> impl Fn(&[ColumnarValue]) -> Result<ColumnarValue> {
+    let days = Some(
+        now_ts.num_days_from_ce() - NaiveDate::from_ymd(1970, 1, 
1).num_days_from_ce(),
+    );
+    move |_arg| Ok(ColumnarValue::Scalar(ScalarValue::Date32(days)))
+}
+
 fn quarter_month(date: &NaiveDateTime) -> u32 {
     1 + 3 * ((date.month() - 1) / 3)
 }
diff --git a/datafusion/physical-expr/src/functions.rs 
b/datafusion/physical-expr/src/functions.rs
index 6f7b864ef..f7c3cbef9 100644
--- a/datafusion/physical-expr/src/functions.rs
+++ b/datafusion/physical-expr/src/functions.rs
@@ -427,6 +427,12 @@ pub fn create_physical_fun(
                 execution_props.query_execution_start_time,
             ))
         }
+        BuiltinScalarFunction::CurrentDate => {
+            // bind value for current_date at plan time
+            Arc::new(datetime_expressions::make_current_date(
+                execution_props.query_execution_start_time,
+            ))
+        }
         BuiltinScalarFunction::InitCap => Arc::new(|args| match 
args[0].data_type() {
             DataType::Utf8 => {
                 make_scalar_function(string_expressions::initcap::<i32>)(args)
diff --git a/datafusion/proto/proto/datafusion.proto 
b/datafusion/proto/proto/datafusion.proto
index e0f8f5160..1ff2952df 100644
--- a/datafusion/proto/proto/datafusion.proto
+++ b/datafusion/proto/proto/datafusion.proto
@@ -495,6 +495,7 @@ enum ScalarFunction {
   Atan2=67;
   DateBin=68;
   ArrowTypeof=69;
+  CurrentDate=70;
 }
 
 message ScalarFunctionNode {
diff --git a/datafusion/proto/src/from_proto.rs 
b/datafusion/proto/src/from_proto.rs
index f1e8a9f21..cd61bba7a 100644
--- a/datafusion/proto/src/from_proto.rs
+++ b/datafusion/proto/src/from_proto.rs
@@ -429,6 +429,7 @@ impl From<&protobuf::ScalarFunction> for 
BuiltinScalarFunction {
             ScalarFunction::ToTimestampMicros => Self::ToTimestampMicros,
             ScalarFunction::ToTimestampSeconds => Self::ToTimestampSeconds,
             ScalarFunction::Now => Self::Now,
+            ScalarFunction::CurrentDate => Self::CurrentDate,
             ScalarFunction::Translate => Self::Translate,
             ScalarFunction::RegexpMatch => Self::RegexpMatch,
             ScalarFunction::Coalesce => Self::Coalesce,
diff --git a/datafusion/proto/src/generated/pbjson.rs 
b/datafusion/proto/src/generated/pbjson.rs
index 71502f812..941cc461f 100644
--- a/datafusion/proto/src/generated/pbjson.rs
+++ b/datafusion/proto/src/generated/pbjson.rs
@@ -9620,6 +9620,7 @@ impl serde::Serialize for ScalarFunction {
             Self::Atan2 => "Atan2",
             Self::DateBin => "DateBin",
             Self::ArrowTypeof => "ArrowTypeof",
+            Self::CurrentDate => "CurrentDate",
         };
         serializer.serialize_str(variant)
     }
@@ -9701,6 +9702,7 @@ impl<'de> serde::Deserialize<'de> for ScalarFunction {
             "Atan2",
             "DateBin",
             "ArrowTypeof",
+            "CurrentDate",
         ];
 
         struct GeneratedVisitor;
@@ -9813,6 +9815,7 @@ impl<'de> serde::Deserialize<'de> for ScalarFunction {
                     "Atan2" => Ok(ScalarFunction::Atan2),
                     "DateBin" => Ok(ScalarFunction::DateBin),
                     "ArrowTypeof" => Ok(ScalarFunction::ArrowTypeof),
+                    "CurrentDate" => Ok(ScalarFunction::CurrentDate),
                     _ => Err(serde::de::Error::unknown_variant(value, FIELDS)),
                 }
             }
diff --git a/datafusion/proto/src/generated/prost.rs 
b/datafusion/proto/src/generated/prost.rs
index 8287d1289..038195c94 100644
--- a/datafusion/proto/src/generated/prost.rs
+++ b/datafusion/proto/src/generated/prost.rs
@@ -1224,6 +1224,7 @@ pub enum ScalarFunction {
     Atan2 = 67,
     DateBin = 68,
     ArrowTypeof = 69,
+    CurrentDate = 70,
 }
 impl ScalarFunction {
     /// String value of the enum field names used in the ProtoBuf definition.
@@ -1302,6 +1303,7 @@ impl ScalarFunction {
             ScalarFunction::Atan2 => "Atan2",
             ScalarFunction::DateBin => "DateBin",
             ScalarFunction::ArrowTypeof => "ArrowTypeof",
+            ScalarFunction::CurrentDate => "CurrentDate",
         }
     }
 }
diff --git a/datafusion/proto/src/to_proto.rs b/datafusion/proto/src/to_proto.rs
index 14a5f24e5..a089f0768 100644
--- a/datafusion/proto/src/to_proto.rs
+++ b/datafusion/proto/src/to_proto.rs
@@ -1178,6 +1178,7 @@ impl TryFrom<&BuiltinScalarFunction> for 
protobuf::ScalarFunction {
             BuiltinScalarFunction::ToTimestampMicros => 
Self::ToTimestampMicros,
             BuiltinScalarFunction::ToTimestampSeconds => 
Self::ToTimestampSeconds,
             BuiltinScalarFunction::Now => Self::Now,
+            BuiltinScalarFunction::CurrentDate => Self::CurrentDate,
             BuiltinScalarFunction::Translate => Self::Translate,
             BuiltinScalarFunction::RegexpMatch => Self::RegexpMatch,
             BuiltinScalarFunction::Coalesce => Self::Coalesce,

Reply via email to