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

richox pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/auron.git


The following commit(s) were added to refs/heads/master by this push:
     new 15391928 [AURON #1518] Implement native function of quarter. (#1519)
15391928 is described below

commit 153919283ef4a3ded80852564c14694544c51f7e
Author: slfan1989 <[email protected]>
AuthorDate: Mon Nov 3 10:53:34 2025 +0800

    [AURON #1518] Implement native function of quarter. (#1519)
    
    * [AURON #1518] Implement native function of quarter.
    
    Signed-off-by: slfan1989 <[email protected]>
    
    * [AURON #1518] Fix CheckStyle Issue.
    
    Signed-off-by: slfan1989 <[email protected]>
    
    ---------
    
    Signed-off-by: slfan1989 <[email protected]>
---
 native-engine/datafusion-ext-functions/src/lib.rs  |  1 +
 .../datafusion-ext-functions/src/spark_dates.rs    | 71 ++++++++++++++++++++++
 .../apache/spark/sql/auron/AuronQuerySuite.scala   | 22 +++++++
 .../apache/spark/sql/auron/NativeConverters.scala  |  1 +
 4 files changed, 95 insertions(+)

diff --git a/native-engine/datafusion-ext-functions/src/lib.rs 
b/native-engine/datafusion-ext-functions/src/lib.rs
index f2311f37..8c2f7560 100644
--- a/native-engine/datafusion-ext-functions/src/lib.rs
+++ b/native-engine/datafusion-ext-functions/src/lib.rs
@@ -60,6 +60,7 @@ pub fn create_spark_ext_function(name: &str) -> 
Result<ScalarFunctionImplementat
         "Year" => Arc::new(spark_dates::spark_year),
         "Month" => Arc::new(spark_dates::spark_month),
         "Day" => Arc::new(spark_dates::spark_day),
+        "Quarter" => Arc::new(spark_dates::spark_quarter),
         "BrickhouseArrayUnion" => 
Arc::new(brickhouse::array_union::array_union),
         "Round" => Arc::new(spark_round::spark_round),
         "NormalizeNanAndZero" => {
diff --git a/native-engine/datafusion-ext-functions/src/spark_dates.rs 
b/native-engine/datafusion-ext-functions/src/spark_dates.rs
index 6bb99555..6221d9ab 100644
--- a/native-engine/datafusion-ext-functions/src/spark_dates.rs
+++ b/native-engine/datafusion-ext-functions/src/spark_dates.rs
@@ -13,7 +13,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+use std::sync::Arc;
+
 use arrow::{
+    array::{ArrayRef, Int32Array},
     compute::{DatePart, date_part},
     datatypes::DataType,
 };
@@ -35,6 +38,33 @@ pub fn spark_day(args: &[ColumnarValue]) -> 
Result<ColumnarValue> {
     Ok(ColumnarValue::Array(date_part(&input, DatePart::Day)?))
 }
 
+/// `spark_quarter(date/timestamp/compatible-string)`
+///
+/// Simulates Spark's `quarter()` function.
+/// Converts the input to `Date32`, extracts the month (1–12),
+/// and computes the quarter as `((month - 1) / 3) + 1`.
+/// Null values are propagated transparently.
+pub fn spark_quarter(args: &[ColumnarValue]) -> Result<ColumnarValue> {
+    // Cast input to Date32 for compatibility with date_part()
+    let input = cast(&args[0].clone().into_array(1)?, &DataType::Date32)?;
+
+    // Extract month (1–12) using Arrow's date_part
+    let month_arr: ArrayRef = date_part(&input, DatePart::Month)?;
+    let month_arr = month_arr
+        .as_any()
+        .downcast_ref::<Int32Array>()
+        .expect("date_part(Month) must return Int32Array");
+
+    // Compute quarter: ((month - 1) / 3) + 1, preserving NULLs
+    let quarter = Int32Array::from_iter(
+        month_arr
+            .iter()
+            .map(|opt_m| opt_m.map(|m| ((m - 1) / 3 + 1) as i32)),
+    );
+
+    Ok(ColumnarValue::Array(Arc::new(quarter)))
+}
+
 #[cfg(test)]
 mod tests {
     use std::sync::Arc;
@@ -100,4 +130,45 @@ mod tests {
             &expected_ret
         );
     }
+
+    #[test]
+    fn test_spark_quarter_basic() {
+        // Date32 days relative to 1970-01-01:
+        //  0   -> 1970-01-01 (Q1)
+        //  40  -> ~1970-02-10 (Q1)
+        // 100  -> ~1970-04-11 (Q2)
+        // 200  -> ~1970-07-20 (Q3)
+        // 300  -> ~1970-10-28 (Q4)
+        let input = Arc::new(Date32Array::from(vec![
+            Some(0),
+            Some(40),
+            Some(100),
+            Some(200),
+            Some(300),
+            None,
+        ]));
+        let args = vec![ColumnarValue::Array(input)];
+        let expected: ArrayRef = Arc::new(Int32Array::from(vec![
+            Some(1),
+            Some(1),
+            Some(2),
+            Some(3),
+            Some(4),
+            None,
+        ]));
+
+        let out = spark_quarter(&args).unwrap().into_array(1).unwrap();
+        assert_eq!(&out, &expected);
+    }
+
+    #[test]
+    fn test_spark_quarter_null_only() {
+        // Ensure NULL propagation
+        let input = Arc::new(Date32Array::from(vec![None, None]));
+        let args = vec![ColumnarValue::Array(input)];
+        let expected: ArrayRef = Arc::new(Int32Array::from(vec![None, None]));
+
+        let out = spark_quarter(&args).unwrap().into_array(1).unwrap();
+        assert_eq!(&out, &expected);
+    }
 }
diff --git 
a/spark-extension-shims-spark/src/test/scala/org/apache/spark/sql/auron/AuronQuerySuite.scala
 
b/spark-extension-shims-spark/src/test/scala/org/apache/spark/sql/auron/AuronQuerySuite.scala
index 4b1fec6e..d36fd096 100644
--- 
a/spark-extension-shims-spark/src/test/scala/org/apache/spark/sql/auron/AuronQuerySuite.scala
+++ 
b/spark-extension-shims-spark/src/test/scala/org/apache/spark/sql/auron/AuronQuerySuite.scala
@@ -287,6 +287,28 @@ class AuronQuerySuite
     }
   }
 
+  test("test filter with quarter function") {
+    withTable("t1") {
+      sql("""
+          |create table t1 using parquet as
+          |select '2024-02-10' as event_time
+          |union all select '2024-04-11'
+          |union all select '2024-07-20'
+          |union all select '2024-12-18'
+          |""".stripMargin)
+
+      checkAnswer(
+        sql("""
+            |select q, count(*)
+            |from (select event_time, quarter(event_time) as q from t1) t
+            |where q <= 3
+            |group by q
+            |order by q
+            |""".stripMargin),
+        Seq(Row(1, 1), Row(2, 1), Row(3, 1)))
+    }
+  }
+
   test("lpad/rpad basic") {
     Seq(
       ("select lpad('abc', 5, '*')", Row("**abc")),
diff --git 
a/spark-extension/src/main/scala/org/apache/spark/sql/auron/NativeConverters.scala
 
b/spark-extension/src/main/scala/org/apache/spark/sql/auron/NativeConverters.scala
index d8418b17..8f0e90e1 100644
--- 
a/spark-extension/src/main/scala/org/apache/spark/sql/auron/NativeConverters.scala
+++ 
b/spark-extension/src/main/scala/org/apache/spark/sql/auron/NativeConverters.scala
@@ -879,6 +879,7 @@ object NativeConverters extends Logging {
       case Year(child) => buildExtScalarFunction("Year", child :: Nil, 
IntegerType)
       case Month(child) => buildExtScalarFunction("Month", child :: Nil, 
IntegerType)
       case DayOfMonth(child) => buildExtScalarFunction("Day", child :: Nil, 
IntegerType)
+      case Quarter(child) => buildExtScalarFunction("Quarter", child :: Nil, 
IntegerType)
 
       case e: Levenshtein =>
         buildScalarFunction(pb.ScalarFunction.Levenshtein, e.children, 
e.dataType)

Reply via email to