MCPcopy Create free account
hub / github.com/apache/datafusion / plan_binary_op

Method plan_binary_op

datafusion/functions-nested/src/planner.rs:50–99  ·  view source on GitHub ↗
(
        &self,
        expr: RawBinaryExpr,
        schema: &DFSchema,
    )

Source from the content-addressed store, hash-verified

48
49impl ExprPlanner for NestedFunctionPlanner {
50 fn plan_binary_op(
51 &self,
52 expr: RawBinaryExpr,
53 schema: &DFSchema,
54 ) -> Result<PlannerResult<RawBinaryExpr>> {
55 let RawBinaryExpr { op, left, right } = expr;
56
57 if op == BinaryOperator::StringConcat {
58 let left_type = left.get_type(schema)?;
59 let right_type = right.get_type(schema)?;
60 let left_list_ndims = list_ndims(&left_type);
61 let right_list_ndims = list_ndims(&right_type);
62
63 // Rewrite string concat operator to function based on types
64 // if we get list || list then we rewrite it to array_concat()
65 // if we get list || non-list then we rewrite it to array_append()
66 // if we get non-list || list then we rewrite it to array_prepend()
67 // if we get string || string then we rewrite it to concat()
68
69 // We determine the target function to rewrite based on the list n-dimension, the check is not exact but sufficient.
70 // The exact validity check is handled in the actual function, so even if there is 3d list appended with 1d list, it is also fine to rewrite.
71 if left_list_ndims + right_list_ndims == 0 {
72 // TODO: concat function ignore null, but string concat takes null into consideration
73 // we can rewrite it to concat if we can configure the behaviour of concat function to the one like `string concat operator`
74 } else if left_list_ndims == right_list_ndims {
75 return Ok(PlannerResult::Planned(array_concat(vec![left, right])));
76 } else if left_list_ndims > right_list_ndims {
77 return Ok(PlannerResult::Planned(array_append(left, right)));
78 } else if left_list_ndims < right_list_ndims {
79 return Ok(PlannerResult::Planned(array_prepend(left, right)));
80 }
81 } else if matches!(op, BinaryOperator::AtArrow | BinaryOperator::ArrowAt) {
82 let left_type = left.get_type(schema)?;
83 let right_type = right.get_type(schema)?;
84 let left_list_ndims = list_ndims(&left_type);
85 let right_list_ndims = list_ndims(&right_type);
86 // if both are list
87 if left_list_ndims > 0 && right_list_ndims > 0 {
88 if op == BinaryOperator::AtArrow {
89 // array1 @> array2 -> array_has_all(array1, array2)
90 return Ok(PlannerResult::Planned(array_has_all(left, right)));
91 } else {
92 // array1 <@ array2 -> array_has_all(array2, array1)
93 return Ok(PlannerResult::Planned(array_has_all(right, left)));
94 }
95 }
96 }
97
98 Ok(PlannerResult::Original(RawBinaryExpr { op, left, right }))
99 }
100
101 fn plan_array_literal(
102 &self,

Callers

nothing calls this directly

Calls 2

list_ndimsFunction · 0.85
get_typeMethod · 0.45

Tested by

no test coverage detected