Plans an `ARRAY` expression.
(
ecx: &ExprContext,
exprs: &[Expr<Aug>],
type_hint: Option<&SqlScalarType>,
)
| 4943 | |
| 4944 | /// Plans an `ARRAY` expression. |
| 4945 | fn plan_array( |
| 4946 | ecx: &ExprContext, |
| 4947 | exprs: &[Expr<Aug>], |
| 4948 | type_hint: Option<&SqlScalarType>, |
| 4949 | ) -> Result<CoercibleScalarExpr, PlanError> { |
| 4950 | // Plan each element expression. |
| 4951 | let mut out = vec![]; |
| 4952 | for expr in exprs { |
| 4953 | out.push(match expr { |
| 4954 | // Special case nested ARRAY expressions so we can plumb |
| 4955 | // the type hint through. |
| 4956 | Expr::Array(exprs) => plan_array(ecx, exprs, type_hint.clone())?, |
| 4957 | _ => plan_expr(ecx, expr)?, |
| 4958 | }); |
| 4959 | } |
| 4960 | |
| 4961 | // Attempt to make use of the type hint. |
| 4962 | let type_hint = match type_hint { |
| 4963 | // The user has provided an explicit cast to an array type. We know the |
| 4964 | // element type to coerce to. Need to be careful, though: if there's |
| 4965 | // evidence that any of the array elements are themselves arrays, we |
| 4966 | // want to coerce to the array type, not the element type. |
| 4967 | Some(SqlScalarType::Array(elem_type)) => { |
| 4968 | let multidimensional = out.iter().any(|e| { |
| 4969 | matches!( |
| 4970 | ecx.scalar_type(e), |
| 4971 | CoercibleScalarType::Coerced(SqlScalarType::Array(_)) |
| 4972 | ) |
| 4973 | }); |
| 4974 | if multidimensional { |
| 4975 | type_hint |
| 4976 | } else { |
| 4977 | Some(&**elem_type) |
| 4978 | } |
| 4979 | } |
| 4980 | // The user provided an explicit cast to a non-array type. We'll have to |
| 4981 | // guess what the correct type for the array. Our caller will then |
| 4982 | // handle converting that array type to the desired non-array type. |
| 4983 | Some(_) => None, |
| 4984 | // No type hint. We'll have to guess the correct type for the array. |
| 4985 | None => None, |
| 4986 | }; |
| 4987 | |
| 4988 | // Coerce all elements to the same type. |
| 4989 | let (elem_type, exprs) = if exprs.is_empty() { |
| 4990 | if let Some(elem_type) = type_hint { |
| 4991 | (elem_type.clone(), vec![]) |
| 4992 | } else { |
| 4993 | sql_bail!("cannot determine type of empty array"); |
| 4994 | } |
| 4995 | } else { |
| 4996 | let out = coerce_homogeneous_exprs(&ecx.with_name("ARRAY"), out, type_hint)?; |
| 4997 | (ecx.scalar_type(&out[0]), out) |
| 4998 | }; |
| 4999 | |
| 5000 | // Arrays of `char` type are disallowed due to a known limitation: |
| 5001 | // https://github.com/MaterializeInc/database-issues/issues/2360. |
| 5002 | // |
no test coverage detected