Skip to content

Commit 9fd678c

Browse files
committed
[AURON #2485] Support last_day function natively
1 parent e906842 commit 9fd678c

4 files changed

Lines changed: 56 additions & 0 deletions

File tree

native-engine/datafusion-ext-functions/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ pub fn create_auron_ext_function(
9494
"Spark_DayOfWeek" => shared_function!(spark_dates::spark_dayofweek),
9595
"Spark_WeekOfYear" => shared_function!(spark_dates::spark_weekofyear),
9696
"Spark_Quarter" => shared_function!(spark_dates::spark_quarter),
97+
"Spark_LastDay" => shared_function!(spark_dates::spark_last_day),
9798
"Spark_MakeDate" => shared_function!(spark_dates::spark_make_date),
9899
"Spark_Hour" => shared_function!(spark_dates::spark_hour),
99100
"Spark_Minute" => shared_function!(spark_dates::spark_minute),

native-engine/datafusion-ext-functions/src/spark_dates.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,18 @@ pub fn spark_day(args: &[ColumnarValue]) -> Result<ColumnarValue> {
277277
)?))
278278
}
279279

280+
pub fn spark_last_day(args: &[ColumnarValue]) -> Result<ColumnarValue> {
281+
let input = resolve_local_date32(args)?;
282+
let last_day = Date32Array::from_iter(input.iter().map(|opt_days| {
283+
opt_days
284+
.and_then(NaiveDate::from_epoch_days)
285+
.and_then(|date| date.with_day(days_in_month(date.year(), date.month())))
286+
.map(|date| date.to_epoch_days())
287+
}));
288+
289+
Ok(ColumnarValue::Array(Arc::new(last_day)))
290+
}
291+
280292
pub fn spark_make_date(args: &[ColumnarValue]) -> Result<ColumnarValue> {
281293
if args.len() != 4 {
282294
return Err(DataFusionError::Execution(
@@ -595,6 +607,32 @@ mod tests {
595607
Ok(())
596608
}
597609

610+
#[test]
611+
fn test_spark_last_day() -> Result<()> {
612+
let date = |year, month, day| {
613+
NaiveDate::from_ymd_opt(year, month, day)
614+
.expect("test date must be valid")
615+
.to_epoch_days()
616+
};
617+
let input = Arc::new(Date32Array::from(vec![
618+
Some(date(2009, 1, 12)),
619+
Some(date(2024, 2, 10)),
620+
Some(date(2023, 2, 10)),
621+
Some(date(1969, 12, 1)),
622+
None,
623+
]));
624+
let args = vec![ColumnarValue::Array(input)];
625+
let expected_ret: ArrayRef = Arc::new(Date32Array::from(vec![
626+
Some(date(2009, 1, 31)),
627+
Some(date(2024, 2, 29)),
628+
Some(date(2023, 2, 28)),
629+
Some(date(1969, 12, 31)),
630+
None,
631+
]));
632+
assert_eq!(&spark_last_day(&args)?.into_array(1)?, &expected_ret);
633+
Ok(())
634+
}
635+
598636
#[test]
599637
fn test_spark_make_date_null_and_invalid_inputs() -> Result<()> {
600638
let result = spark_make_date(&[

spark-extension-shims-spark/src/test/scala/org/apache/auron/AuronFunctionSuite.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,21 @@ class AuronFunctionSuite extends AuronQueryTest with BaseAuronSQLSuite {
170170
}
171171
}
172172

173+
test("last_day function") {
174+
withTable("t1") {
175+
sql("create table t1(c1 date) using parquet")
176+
sql("""insert into t1 values
177+
| (date'2009-01-12'),
178+
| (date'2024-02-10'),
179+
| (date'2023-02-10'),
180+
| (date'1969-12-01'),
181+
| (null)
182+
|""".stripMargin)
183+
184+
checkSparkAnswerAndOperator("select last_day(c1) from t1")
185+
}
186+
}
187+
173188
test("date-part functions with non-UTC timezone") {
174189
withTable("t1") {
175190
sql("create table t1(c1 timestamp) using parquet")

spark-extension/src/main/scala/org/apache/spark/sql/auron/NativeConverters.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,8 @@ object NativeConverters extends Logging {
998998
buildTimePartExt("Spark_WeekOfYear", child, isPruningExpr, fallback)
999999
case Quarter(child) =>
10001000
buildTimePartExt("Spark_Quarter", child, isPruningExpr, fallback)
1001+
case e: LastDay =>
1002+
buildExtScalarFunction("Spark_LastDay", e.children, e.dataType)
10011003

10021004
case e: Levenshtein =>
10031005
buildScalarFunction(pb.ScalarFunction.Levenshtein, e.children, e.dataType)

0 commit comments

Comments
 (0)