fn gen_range_date()

in datafusion/functions-nested/src/range.rs [439:509]


fn gen_range_date(args: &[ArrayRef], include_upper_bound: bool) -> Result<ArrayRef> {
    let [start, stop, step] = take_function_args("range", args)?;

    let (start_array, stop_array, step_array) = (
        Some(as_date32_array(start)?),
        as_date32_array(stop)?,
        Some(as_interval_mdn_array(step)?),
    );

    // values are date32s
    let values_builder = Date32Builder::new();
    let mut list_builder = ListBuilder::new(values_builder);

    for idx in 0..stop_array.len() {
        if stop_array.is_null(idx) {
            list_builder.append_null();
            continue;
        }
        let mut stop = stop_array.value(idx);

        let start = if let Some(start_array_values) = start_array {
            if start_array_values.is_null(idx) {
                list_builder.append_null();
                continue;
            }
            start_array_values.value(idx)
        } else {
            list_builder.append_null();
            continue;
        };

        let step = if let Some(step) = step_array {
            if step.is_null(idx) {
                list_builder.append_null();
                continue;
            }
            step.value(idx)
        } else {
            list_builder.append_null();
            continue;
        };

        let (months, days, _) = IntervalMonthDayNanoType::to_parts(step);

        if months == 0 && days == 0 {
            return exec_err!("Cannot generate date range less than 1 day.");
        }

        let neg = months < 0 || days < 0;
        if !include_upper_bound {
            stop = Date32Type::subtract_month_day_nano(stop, step);
        }
        let mut new_date = start;

        let values = from_fn(|| {
            if (neg && new_date < stop) || (!neg && new_date > stop) {
                None
            } else {
                let current_date = new_date;
                new_date = Date32Type::add_month_day_nano(new_date, step);
                Some(Some(current_date))
            }
        });

        list_builder.append_value(values);
    }

    let arr = Arc::new(list_builder.finish());

    Ok(arr)
}