Skip to content

Commit 78447d6

Browse files
authored
Add a make_date function (#9040)
* Add a make_date function #9024 * Fixed error message #9024 * minor typo fix.
1 parent 4d389c2 commit 78447d6

File tree

13 files changed

+569
-7
lines changed

13 files changed

+569
-7
lines changed

datafusion-examples/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ cargo run --example csv_sql
6464
- [`simple_udaf.rs`](examples/simple_udaf.rs): Define and invoke a User Defined Aggregate Function (UDAF)
6565
- [`advanced_udaf.rs`](examples/advanced_udaf.rs): Define and invoke a more complicated User Defined Aggregate Function (UDAF)
6666
- [`simple_udfw.rs`](examples/simple_udwf.rs): Define and invoke a User Defined Window Function (UDWF)
67+
- [`make_date.rs`](examples/make_date.rs): Examples of using the make_date function
6768
- [`to_timestamp.rs`](examples/to_timestamp.rs): Examples of using the to_timestamp functions
6869
- [`advanced_udwf.rs`](examples/advanced_udwf.rs): Define and invoke a more complicated User Defined Window Function (UDWF)
6970

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
use std::sync::Arc;
19+
20+
use datafusion::arrow::array::Int32Array;
21+
use datafusion::arrow::datatypes::{DataType, Field, Schema};
22+
use datafusion::arrow::record_batch::RecordBatch;
23+
use datafusion::error::Result;
24+
use datafusion::prelude::*;
25+
use datafusion_common::assert_contains;
26+
27+
/// This example demonstrates how to use the make_date
28+
/// function in the DataFrame API as well as via sql.
29+
#[tokio::main]
30+
async fn main() -> Result<()> {
31+
// define a schema.
32+
let schema = Arc::new(Schema::new(vec![
33+
Field::new("y", DataType::Int32, false),
34+
Field::new("m", DataType::Int32, false),
35+
Field::new("d", DataType::Int32, false),
36+
]));
37+
38+
// define data.
39+
let batch = RecordBatch::try_new(
40+
schema,
41+
vec![
42+
Arc::new(Int32Array::from(vec![2020, 2021, 2022, 2023, 2024])),
43+
Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5])),
44+
Arc::new(Int32Array::from(vec![15, 16, 17, 18, 19])),
45+
],
46+
)?;
47+
48+
// declare a new context. In spark API, this corresponds to a new spark SQLsession
49+
let ctx = SessionContext::new();
50+
51+
// declare a table in memory. In spark API, this corresponds to createDataFrame(...).
52+
ctx.register_batch("t", batch)?;
53+
let df = ctx.table("t").await?;
54+
55+
// use make_date function to convert col 'y', 'm' & 'd' to a date
56+
let df = df.with_column("a", make_date(col("y"), col("m"), col("d")))?;
57+
// use make_date function to convert col 'y' & 'm' with a static day to a date
58+
let df = df.with_column("b", make_date(col("y"), col("m"), lit(22)))?;
59+
60+
let df = df.select_columns(&["a", "b"])?;
61+
62+
// print the results
63+
df.show().await?;
64+
65+
// use sql to convert col 'y', 'm' & 'd' to a date
66+
let df = ctx.sql("select make_date(y, m, d) from t").await?;
67+
68+
// print the results
69+
df.show().await?;
70+
71+
// use sql to convert col 'y' & 'm' with a static string day to a date
72+
let df = ctx.sql("select make_date(y, m, '22') from t").await?;
73+
74+
// print the results
75+
df.show().await?;
76+
77+
// math expressions work
78+
let df = ctx.sql("select make_date(y + 1, m, d) from t").await?;
79+
80+
// print the results
81+
df.show().await?;
82+
83+
// you can cast to supported types (int, bigint, varchar) if required
84+
let df = ctx
85+
.sql("select make_date(2024::bigint, 01::bigint, 27::varchar(3))")
86+
.await?;
87+
88+
// print the results
89+
df.show().await?;
90+
91+
// arrow casts also work
92+
let df = ctx
93+
.sql("select make_date(arrow_cast(2024, 'Int64'), arrow_cast(1, 'Int64'), arrow_cast(27, 'Int64'))")
94+
.await?;
95+
96+
// print the results
97+
df.show().await?;
98+
99+
// invalid column values will result in an error
100+
let result = ctx
101+
.sql("select make_date(2024, null, 23)")
102+
.await?
103+
.collect()
104+
.await;
105+
106+
let expected = "Execution error: Unable to parse date from null/empty value";
107+
assert_contains!(result.unwrap_err().to_string(), expected);
108+
109+
// invalid date values will also result in an error
110+
let result = ctx
111+
.sql("select make_date(2024, 01, 32)")
112+
.await?
113+
.collect()
114+
.await;
115+
116+
let expected = "Execution error: Unable to parse date from 2024, 1, 32";
117+
assert_contains!(result.unwrap_err().to_string(), expected);
118+
119+
Ok(())
120+
}

datafusion/expr/src/built_in_function.rs

+10
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ pub enum BuiltinScalarFunction {
295295
CurrentDate,
296296
/// current_time
297297
CurrentTime,
298+
/// make_date
299+
MakeDate,
298300
/// translate
299301
Translate,
300302
/// trim
@@ -484,6 +486,7 @@ impl BuiltinScalarFunction {
484486
BuiltinScalarFunction::ToTimestampMicros => Volatility::Immutable,
485487
BuiltinScalarFunction::ToTimestampNanos => Volatility::Immutable,
486488
BuiltinScalarFunction::ToTimestampSeconds => Volatility::Immutable,
489+
BuiltinScalarFunction::MakeDate => Volatility::Immutable,
487490
BuiltinScalarFunction::Translate => Volatility::Immutable,
488491
BuiltinScalarFunction::Trim => Volatility::Immutable,
489492
BuiltinScalarFunction::Upper => Volatility::Immutable,
@@ -834,6 +837,7 @@ impl BuiltinScalarFunction {
834837
}
835838
BuiltinScalarFunction::CurrentDate => Ok(Date32),
836839
BuiltinScalarFunction::CurrentTime => Ok(Time64(Nanosecond)),
840+
BuiltinScalarFunction::MakeDate => Ok(Date32),
837841
BuiltinScalarFunction::Translate => {
838842
utf8_to_str_type(&input_expr_types[0], "translate")
839843
}
@@ -1379,6 +1383,11 @@ impl BuiltinScalarFunction {
13791383
| BuiltinScalarFunction::CurrentTime => {
13801384
Signature::uniform(0, vec![], self.volatility())
13811385
}
1386+
BuiltinScalarFunction::MakeDate => Signature::uniform(
1387+
3,
1388+
vec![Int32, Int64, UInt32, UInt64, Utf8],
1389+
self.volatility(),
1390+
),
13821391
BuiltinScalarFunction::Isnan | BuiltinScalarFunction::Iszero => {
13831392
Signature::one_of(
13841393
vec![Exact(vec![Float32]), Exact(vec![Float64])],
@@ -1523,6 +1532,7 @@ impl BuiltinScalarFunction {
15231532
BuiltinScalarFunction::Now => &["now"],
15241533
BuiltinScalarFunction::CurrentDate => &["current_date", "today"],
15251534
BuiltinScalarFunction::CurrentTime => &["current_time"],
1535+
BuiltinScalarFunction::MakeDate => &["make_date"],
15261536
BuiltinScalarFunction::DateBin => &["date_bin"],
15271537
BuiltinScalarFunction::DateTrunc => &["date_trunc", "datetrunc"],
15281538
BuiltinScalarFunction::DatePart => &["date_part", "datepart"],

datafusion/expr/src/expr_fn.rs

+1
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,7 @@ scalar_expr!(
921921
scalar_expr!(CurrentDate, current_date, ,"returns current UTC date as a [`DataType::Date32`] value");
922922
scalar_expr!(Now, now, ,"returns current timestamp in nanoseconds, using the same value for all instances of now() in same statement");
923923
scalar_expr!(CurrentTime, current_time, , "returns current UTC time as a [`DataType::Time64`] value");
924+
scalar_expr!(MakeDate, make_date, year month day, "make a date from year, month and day component parts");
924925
scalar_expr!(Nanvl, nanvl, x y, "returns x if x is not NaN otherwise returns y");
925926
scalar_expr!(
926927
Isnan,

0 commit comments

Comments
 (0)