Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support multi params in promql range function macro #3464

Merged
merged 1 commit into from Mar 19, 2024

Conversation

Taylor-lagrange
Copy link
Contributor

I hereby agree to the terms of the GreptimeDB CLA.

Refer to a related PR or issue link (optional)

What's changed and what's your intention?

Support multi params in promql range function macro

The PromQL's function mark with #[range_fn] will generate code like

#[range_fn(
    name = "MultiparamRunc",
    ret = "Int64Array",
    display_name = "prom_multi_param_func"
)]
pub fn multi_param_func(
    _: &TimestampMillisecondArray,
    _values: &Float64Array,
    _a: &StringArray,
    _b: &Int64Array,
) -> Option<i64> {
    Some(0)
}
pub struct MultiparamRunc {}
impl MultiparamRunc {
    pub const fn name() -> &'static str {
        "prom_multi_param_func"
    }
    pub fn scalar_udf() -> ScalarUDF {
        ScalarUDF {
            name: Self::name().to_string(),
            signature: Signature::new(
                TypeSignature::Exact(Self::input_type()),
                Volatility::Immutable,
            ),
            return_type: Arc::new(|_| Ok(Arc::new(Self::return_type()))),
            fun: Arc::new(Self::calc),
        }
    }
    fn input_type() -> Vec<DataType> {
        <[_]>::into_vec(
            #[rustc_box]
            ::alloc::boxed::Box::new([
                RangeArray::convert_data_type(
                    TimestampMillisecondArray::new_null(0).data_type().clone(),
                ),
                RangeArray::convert_data_type(
                    Float64Array::new_null(0).data_type().clone(),
                ),
                RangeArray::convert_data_type(
                    StringArray::new_null(0).data_type().clone(),
                ),
                RangeArray::convert_data_type(
                    Int64Array::new_null(0).data_type().clone(),
                ),
            ]),
        )
    }
    fn return_type() -> DataType {
        Int64Array::new_null(0).data_type().clone()
    }
}
impl MultiparamRunc {
    fn calc(input: &[ColumnarValue]) -> Result<ColumnarValue, DataFusionError> {
        match (&input.len(), &4usize) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(
                        kind,
                        &*left_val,
                        &*right_val,
                        ::core::option::Option::None,
                    );
                }
            }
        };
        let param_0_range_array = RangeArray::try_new(
            extract_array(&input[0usize])?.to_data().into(),
        )?;
        let param_1_range_array = RangeArray::try_new(
            extract_array(&input[1usize])?.to_data().into(),
        )?;
        let param_2_range_array = RangeArray::try_new(
            extract_array(&input[2usize])?.to_data().into(),
        )?;
        let param_3_range_array = RangeArray::try_new(
            extract_array(&input[3usize])?.to_data().into(),
        )?;
        {
            let len_first = param_0_range_array.len();
            if len_first != param_0_range_array.len() {
                return Err(
                    DataFusionError::Execution({
                        let res = ::alloc::fmt::format(
                            format_args!(
                                "RangeArray have different lengths in PromQL function {0}: array1={1}, array2={2}",
                                MultiparamRunc::name(),
                                len_first,
                                param_0_range_array.len(),
                            ),
                        );
                        res
                    }),
                );
            }
            if len_first != param_1_range_array.len() {
                return Err(
                    DataFusionError::Execution({
                        let res = ::alloc::fmt::format(
                            format_args!(
                                "RangeArray have different lengths in PromQL function {0}: array1={1}, array2={2}",
                                MultiparamRunc::name(),
                                len_first,
                                param_1_range_array.len(),
                            ),
                        );
                        res
                    }),
                );
            }
            if len_first != param_2_range_array.len() {
                return Err(
                    DataFusionError::Execution({
                        let res = ::alloc::fmt::format(
                            format_args!(
                                "RangeArray have different lengths in PromQL function {0}: array1={1}, array2={2}",
                                MultiparamRunc::name(),
                                len_first,
                                param_2_range_array.len(),
                            ),
                        );
                        res
                    }),
                );
            }
            if len_first != param_3_range_array.len() {
                return Err(
                    DataFusionError::Execution({
                        let res = ::alloc::fmt::format(
                            format_args!(
                                "RangeArray have different lengths in PromQL function {0}: array1={1}, array2={2}",
                                MultiparamRunc::name(),
                                len_first,
                                param_3_range_array.len(),
                            ),
                        );
                        res
                    }),
                );
            }
        }
        let mut result_array = Vec::new();
        for index in 0..param_0_range_array.len() {
            let param_0 = param_0_range_array
                .get(index)
                .unwrap()
                .as_any()
                .downcast_ref::<TimestampMillisecondArray>()
                .unwrap()
                .clone();
            let param_1 = param_1_range_array
                .get(index)
                .unwrap()
                .as_any()
                .downcast_ref::<Float64Array>()
                .unwrap()
                .clone();
            let param_2 = param_2_range_array
                .get(index)
                .unwrap()
                .as_any()
                .downcast_ref::<StringArray>()
                .unwrap()
                .clone();
            let param_3 = param_3_range_array
                .get(index)
                .unwrap()
                .as_any()
                .downcast_ref::<Int64Array>()
                .unwrap()
                .clone();
            {
                let len_first = param_0.len();
                if len_first != param_0.len() {
                    return Err(
                        DataFusionError::Execution({
                            let res = ::alloc::fmt::format(
                                format_args!(
                                    "RangeArray\'s element {0} have different lengths in PromQL function {1}: array1={2}, array2={3}",
                                    index,
                                    MultiparamRunc::name(),
                                    len_first,
                                    param_0.len(),
                                ),
                            );
                            res
                        }),
                    );
                }
                if len_first != param_1.len() {
                    return Err(
                        DataFusionError::Execution({
                            let res = ::alloc::fmt::format(
                                format_args!(
                                    "RangeArray\'s element {0} have different lengths in PromQL function {1}: array1={2}, array2={3}",
                                    index,
                                    MultiparamRunc::name(),
                                    len_first,
                                    param_1.len(),
                                ),
                            );
                            res
                        }),
                    );
                }
                if len_first != param_2.len() {
                    return Err(
                        DataFusionError::Execution({
                            let res = ::alloc::fmt::format(
                                format_args!(
                                    "RangeArray\'s element {0} have different lengths in PromQL function {1}: array1={2}, array2={3}",
                                    index,
                                    MultiparamRunc::name(),
                                    len_first,
                                    param_2.len(),
                                ),
                            );
                            res
                        }),
                    );
                }
                if len_first != param_3.len() {
                    return Err(
                        DataFusionError::Execution({
                            let res = ::alloc::fmt::format(
                                format_args!(
                                    "RangeArray\'s element {0} have different lengths in PromQL function {1}: array1={2}, array2={3}",
                                    index,
                                    MultiparamRunc::name(),
                                    len_first,
                                    param_3.len(),
                                ),
                            );
                            res
                        }),
                    );
                }
            }
            let result = multi_param_func(
                &param_0,
                &param_1,
                &param_2,
                &param_3,
            );
            result_array.push(result);
        }
        let result = ColumnarValue::Array(
            Arc::new(Int64Array::from_iter(result_array)),
        );
        Ok(result)
    }
}
fn multi_param_func(
    _: &TimestampMillisecondArray,
    _values: &Float64Array,
    _a: &StringArray,
    _b: &Int64Array,
) -> Option<i64> {
    { Some(0) }
}

Checklist

  • I have written the necessary rustdoc comments.
  • I have added the necessary unit tests and integration tests.
  • This PR does not require documentation updates.

Closes #3454

@github-actions github-actions bot added the docs-not-required This change does not impact docs. label Mar 8, 2024
Copy link

codecov bot commented Mar 8, 2024

Codecov Report

Attention: Patch coverage is 96.96970% with 1 lines in your changes are missing coverage. Please review.

Project coverage is 85.07%. Comparing base (a218f12) to head (9324ab4).
Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3464      +/-   ##
==========================================
- Coverage   85.42%   85.07%   -0.36%     
==========================================
  Files         896      896              
  Lines      147137   147540     +403     
==========================================
- Hits       125696   125519     -177     
- Misses      21441    22021     +580     

@killme2008
Copy link
Contributor

@waynexia Please take a look

Copy link
Contributor

@killme2008 killme2008 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@waynexia waynexia added this pull request to the merge queue Mar 19, 2024
Merged via the queue into GreptimeTeam:main with commit 5b315c2 Mar 19, 2024
18 checks passed
@Taylor-lagrange Taylor-lagrange deleted the feat-range-fn-macro branch March 21, 2024 01:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs-not-required This change does not impact docs.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Extend #[range_fn] macro to support multiple input parameters
3 participants