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

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


The following commit(s) were added to refs/heads/main by this push:
     new 73cfa6c266 feat: Add `Date32`/`Date64`  in aggregate fuzz testing 
(#13041)
73cfa6c266 is described below

commit 73cfa6c266763b3db15942e3f331f3d5274169c1
Author: Leslie Su <[email protected]>
AuthorDate: Sat Oct 26 18:29:37 2024 +0800

    feat: Add `Date32`/`Date64`  in aggregate fuzz testing (#13041)
    
    * refactor PrimitiveArrayGenerator.
    
    * support Date32/Date64 type in data generator.
    
    * fix format.
    
    * remove unnecessary type para in PrimitiveArrayGenerator.
    
    * introduce FromNative trait and replace the unsafe.
---
 datafusion/core/tests/fuzz_cases/aggregate_fuzz.rs |   2 +
 .../aggregation_fuzzer/data_generator.rs           |  46 +++++--
 test-utils/src/array_gen/primitive.rs              | 134 ++++++++++++++-------
 3 files changed, 126 insertions(+), 56 deletions(-)

diff --git a/datafusion/core/tests/fuzz_cases/aggregate_fuzz.rs 
b/datafusion/core/tests/fuzz_cases/aggregate_fuzz.rs
index 1035fa31da..28901b14b5 100644
--- a/datafusion/core/tests/fuzz_cases/aggregate_fuzz.rs
+++ b/datafusion/core/tests/fuzz_cases/aggregate_fuzz.rs
@@ -164,6 +164,8 @@ fn baseline_config() -> DatasetGeneratorConfig {
         ColumnDescr::new("u16", DataType::UInt16),
         ColumnDescr::new("u32", DataType::UInt32),
         ColumnDescr::new("u64", DataType::UInt64),
+        ColumnDescr::new("date32", DataType::Date32),
+        ColumnDescr::new("date64", DataType::Date64),
         // TODO: date/time columns
         // todo decimal columns
         // begin string columns
diff --git 
a/datafusion/core/tests/fuzz_cases/aggregation_fuzzer/data_generator.rs 
b/datafusion/core/tests/fuzz_cases/aggregation_fuzzer/data_generator.rs
index 44f96d5a1a..ef9b5a7f35 100644
--- a/datafusion/core/tests/fuzz_cases/aggregation_fuzzer/data_generator.rs
+++ b/datafusion/core/tests/fuzz_cases/aggregation_fuzzer/data_generator.rs
@@ -17,6 +17,10 @@
 
 use std::sync::Arc;
 
+use arrow::datatypes::{
+    Date32Type, Date64Type, Float32Type, Float64Type, Int16Type, Int32Type, 
Int64Type,
+    Int8Type, UInt16Type, UInt32Type, UInt64Type, UInt8Type,
+};
 use arrow_array::{ArrayRef, RecordBatch};
 use arrow_schema::{DataType, Field, Schema};
 use datafusion_common::{arrow_datafusion_err, DataFusionError, Result};
@@ -222,7 +226,7 @@ macro_rules! generate_string_array {
 }
 
 macro_rules! generate_primitive_array {
-    ($SELF:ident, $NUM_ROWS:ident, $BATCH_GEN_RNG:ident, $ARRAY_GEN_RNG:ident, 
$DATA_TYPE:ident) => {
+    ($SELF:ident, $NUM_ROWS:ident, $BATCH_GEN_RNG:ident, $ARRAY_GEN_RNG:ident, 
$ARROW_TYPE:ident) => {
         paste::paste! {{
             let null_pct_idx = 
$BATCH_GEN_RNG.gen_range(0..$SELF.candidate_null_pcts.len());
             let null_pct = $SELF.candidate_null_pcts[null_pct_idx];
@@ -239,7 +243,7 @@ macro_rules! generate_primitive_array {
                 rng: $ARRAY_GEN_RNG,
             };
 
-            generator.[< gen_data_ $DATA_TYPE >]()
+            generator.gen_data::<$ARROW_TYPE>()
     }}}
 }
 
@@ -297,7 +301,7 @@ impl RecordBatchGenerator {
                     num_rows,
                     batch_gen_rng,
                     array_gen_rng,
-                    i8
+                    Int8Type
                 )
             }
             DataType::Int16 => {
@@ -306,7 +310,7 @@ impl RecordBatchGenerator {
                     num_rows,
                     batch_gen_rng,
                     array_gen_rng,
-                    i16
+                    Int16Type
                 )
             }
             DataType::Int32 => {
@@ -315,7 +319,7 @@ impl RecordBatchGenerator {
                     num_rows,
                     batch_gen_rng,
                     array_gen_rng,
-                    i32
+                    Int32Type
                 )
             }
             DataType::Int64 => {
@@ -324,7 +328,7 @@ impl RecordBatchGenerator {
                     num_rows,
                     batch_gen_rng,
                     array_gen_rng,
-                    i64
+                    Int64Type
                 )
             }
             DataType::UInt8 => {
@@ -333,7 +337,7 @@ impl RecordBatchGenerator {
                     num_rows,
                     batch_gen_rng,
                     array_gen_rng,
-                    u8
+                    UInt8Type
                 )
             }
             DataType::UInt16 => {
@@ -342,7 +346,7 @@ impl RecordBatchGenerator {
                     num_rows,
                     batch_gen_rng,
                     array_gen_rng,
-                    u16
+                    UInt16Type
                 )
             }
             DataType::UInt32 => {
@@ -351,7 +355,7 @@ impl RecordBatchGenerator {
                     num_rows,
                     batch_gen_rng,
                     array_gen_rng,
-                    u32
+                    UInt32Type
                 )
             }
             DataType::UInt64 => {
@@ -360,7 +364,7 @@ impl RecordBatchGenerator {
                     num_rows,
                     batch_gen_rng,
                     array_gen_rng,
-                    u64
+                    UInt64Type
                 )
             }
             DataType::Float32 => {
@@ -369,7 +373,7 @@ impl RecordBatchGenerator {
                     num_rows,
                     batch_gen_rng,
                     array_gen_rng,
-                    f32
+                    Float32Type
                 )
             }
             DataType::Float64 => {
@@ -378,7 +382,25 @@ impl RecordBatchGenerator {
                     num_rows,
                     batch_gen_rng,
                     array_gen_rng,
-                    f64
+                    Float64Type
+                )
+            }
+            DataType::Date32 => {
+                generate_primitive_array!(
+                    self,
+                    num_rows,
+                    batch_gen_rng,
+                    array_gen_rng,
+                    Date32Type
+                )
+            }
+            DataType::Date64 => {
+                generate_primitive_array!(
+                    self,
+                    num_rows,
+                    batch_gen_rng,
+                    array_gen_rng,
+                    Date64Type
                 )
             }
             DataType::Utf8 => {
diff --git a/test-utils/src/array_gen/primitive.rs 
b/test-utils/src/array_gen/primitive.rs
index f70ebf6686..0581862d63 100644
--- a/test-utils/src/array_gen/primitive.rs
+++ b/test-utils/src/array_gen/primitive.rs
@@ -15,14 +15,45 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use arrow::array::{ArrayRef, PrimitiveArray, UInt32Array};
-use arrow::datatypes::{
-    Float32Type, Float64Type, Int16Type, Int32Type, Int64Type, Int8Type, 
UInt16Type,
-    UInt32Type, UInt64Type, UInt8Type,
-};
+use arrow::array::{ArrayRef, ArrowPrimitiveType, PrimitiveArray, UInt32Array};
+use arrow::datatypes::DataType;
+use rand::distributions::Standard;
+use rand::prelude::Distribution;
 use rand::rngs::StdRng;
 use rand::Rng;
 
+/// Trait for converting type safely from a native type T impl this trait.
+pub trait FromNative: std::fmt::Debug + Send + Sync + Copy + Default {
+    /// Convert native type from i64.
+    fn from_i64(_: i64) -> Option<Self> {
+        None
+    }
+}
+
+macro_rules! native_type {
+    ($t: ty $(, $from:ident)*) => {
+        impl FromNative for $t {
+            $(
+                #[inline]
+                fn $from(v: $t) -> Option<Self> {
+                    Some(v)
+                }
+            )*
+        }
+    };
+}
+
+native_type!(i8);
+native_type!(i16);
+native_type!(i32);
+native_type!(i64, from_i64);
+native_type!(u8);
+native_type!(u16);
+native_type!(u32);
+native_type!(u64);
+native_type!(f32);
+native_type!(f64);
+
 /// Randomly generate primitive array
 pub struct PrimitiveArrayGenerator {
     /// the total number of strings in the output
@@ -35,46 +66,61 @@ pub struct PrimitiveArrayGenerator {
     pub rng: StdRng,
 }
 
-macro_rules! impl_gen_data {
-    ($NATIVE_TYPE:ty, $ARROW_TYPE:ident) => {
-        paste::paste! {
-            pub fn [< gen_data_ $NATIVE_TYPE >](&mut self) -> ArrayRef {
-                    // table of strings from which to draw
-                    let distinct_primitives: PrimitiveArray<$ARROW_TYPE> = 
(0..self.num_distinct_primitives)
-                    .map(|_| Some(self.rng.gen::<$NATIVE_TYPE>()))
-                    .collect();
+// TODO: support generating more primitive arrays
+impl PrimitiveArrayGenerator {
+    pub fn gen_data<A>(&mut self) -> ArrayRef
+    where
+        A: ArrowPrimitiveType,
+        A::Native: FromNative,
+        Standard: Distribution<<A as ArrowPrimitiveType>::Native>,
+    {
+        // table of primitives from which to draw
+        let distinct_primitives: PrimitiveArray<A> = 
(0..self.num_distinct_primitives)
+            .map(|_| {
+                Some(match A::DATA_TYPE {
+                    DataType::Int8
+                    | DataType::Int16
+                    | DataType::Int32
+                    | DataType::Int64
+                    | DataType::UInt8
+                    | DataType::UInt16
+                    | DataType::UInt32
+                    | DataType::UInt64
+                    | DataType::Float32
+                    | DataType::Float64
+                    | DataType::Date32 => self.rng.gen::<A::Native>(),
 
-                // pick num_strings randomly from the distinct string table
-                let indicies: UInt32Array = (0..self.num_primitives)
-                    .map(|_| {
-                        if self.rng.gen::<f64>() < self.null_pct {
-                            None
-                        } else if self.num_distinct_primitives > 1 {
-                            let range = 1..(self.num_distinct_primitives as 
u32);
-                            Some(self.rng.gen_range(range))
-                        } else {
-                            Some(0)
-                        }
-                    })
-                    .collect();
+                    DataType::Date64 => {
+                        // TODO: constrain this range to valid dates if 
necessary
+                        let date_value = 
self.rng.gen_range(i64::MIN..=i64::MAX);
+                        let millis_per_day = 86_400_000;
+                        let adjusted_value = date_value - (date_value % 
millis_per_day);
+                        A::Native::from_i64(adjusted_value).unwrap()
+                    }
 
-                let options = None;
-                arrow::compute::take(&distinct_primitives, &indicies, 
options).unwrap()
-            }
-        }
-    };
-}
+                    _ => {
+                        let arrow_type = A::DATA_TYPE;
+                        panic!("Unsupported arrow data type: {arrow_type}")
+                    }
+                })
+            })
+            .collect();
 
-// TODO: support generating more primitive arrays
-impl PrimitiveArrayGenerator {
-    impl_gen_data!(i8, Int8Type);
-    impl_gen_data!(i16, Int16Type);
-    impl_gen_data!(i32, Int32Type);
-    impl_gen_data!(i64, Int64Type);
-    impl_gen_data!(u8, UInt8Type);
-    impl_gen_data!(u16, UInt16Type);
-    impl_gen_data!(u32, UInt32Type);
-    impl_gen_data!(u64, UInt64Type);
-    impl_gen_data!(f32, Float32Type);
-    impl_gen_data!(f64, Float64Type);
+        // pick num_primitves randomly from the distinct string table
+        let indicies: UInt32Array = (0..self.num_primitives)
+            .map(|_| {
+                if self.rng.gen::<f64>() < self.null_pct {
+                    None
+                } else if self.num_distinct_primitives > 1 {
+                    let range = 1..(self.num_distinct_primitives as u32);
+                    Some(self.rng.gen_range(range))
+                } else {
+                    Some(0)
+                }
+            })
+            .collect();
+
+        let options = None;
+        arrow::compute::take(&distinct_primitives, &indicies, options).unwrap()
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to