Omega359 commented on code in PR #8886:
URL: https://github.com/apache/arrow-datafusion/pull/8886#discussion_r1459076364
##########
datafusion/physical-expr/src/datetime_expressions.rs:
##########
@@ -84,7 +172,96 @@ where
array.iter().map(|x| x.map(&op).transpose()).collect()
}
-// given an function that maps a `&str` to a arrow native type,
+/// given a function `op` that maps `&str`, `&str` to the first successful
Result
+/// of an arrow native type, returns a `PrimitiveArray` after the application
of the
+/// function to `args` and the subsequence application of the `op2` function
to any
+/// successful result. This function calls the `op` function with the first
and second
+/// argument and if not successful continues with first and third, first and
fourth,
+/// etc until the result was successful or no more arguments are present.
+/// # Errors
+/// This function errors iff:
+/// * the number of arguments is not > 1 or
+/// * the array arguments are not castable to a `GenericStringArray` or
+/// * the function `op` errors for all input
+pub(crate) fn strings_to_primitive_function<'a, T, O, F, F2>(
+ args: &'a [ColumnarValue],
+ op: F,
+ op2: F2,
+ name: &str,
+) -> Result<PrimitiveArray<O>>
+where
+ O: ArrowPrimitiveType,
+ T: OffsetSizeTrait,
+ F: Fn(&'a str, &'a str) -> Result<O::Native>,
+ F2: Fn(O::Native) -> O::Native,
+{
+ if args.len() < 2 {
+ return internal_err!(
+ "{:?} args were supplied but {} takes 2 or more arguments",
+ args.len(),
+ name
+ );
+ }
+
+ // this will throw the error if any of the array args are not castable to
GenericStringArray
+ let data = args
+ .iter()
+ .map(|a| match a {
+ ColumnarValue::Array(a) => {
+ Ok(Either::Left(as_generic_string_array::<T>(a.as_ref())?))
+ }
+ ColumnarValue::Scalar(s) => match s {
+ ScalarValue::Utf8(a) | ScalarValue::LargeUtf8(a) =>
Ok(Either::Right(a)),
+ other => internal_err!(
+ "Unexpected scalar type encountered '{other}' for function
'{name}'"
+ ),
+ },
+ })
+ .collect::<Result<Vec<Either<&GenericStringArray<T>,
&Option<String>>>>>()?;
+
+ let first_arg = &data.first().unwrap().left().unwrap();
+
+ first_arg
+ .iter()
+ .enumerate()
+ .map(|(pos, x)| {
+ let mut val = None;
+
+ if let Some(x) = x {
+ let param_args = data.iter().skip(1);
+
+ // go through the args and find the first successful result.
Only the last
+ // failure will be returned if no successful result was
received.
+ for param_arg in param_args {
+ // param_arg is an array, use the corresponding index into
the array as the arg
+ // we're currently parsing
+ let p = *param_arg;
+ let r = if p.is_left() {
+ let p = p.left().unwrap();
+ op(x, p.value(pos))
+ }
+ // args is a scalar, use it directly
+ else if let Some(p) = p.right().unwrap() {
+ op(x, p.as_str())
+ } else {
+ continue;
+ };
+
+ if r.is_ok() {
Review Comment:
Sounds good.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]