Cast a relation from one type to another using the specified type of cast. The length of `target_types` must match the arity of `expr`.
(
qcx: &QueryContext,
ccx: CastContext,
expr: HirRelationExpr,
target_types: I,
)
| 951 | /// |
| 952 | /// The length of `target_types` must match the arity of `expr`. |
| 953 | pub(crate) fn cast_relation<'a, I>( |
| 954 | qcx: &QueryContext, |
| 955 | ccx: CastContext, |
| 956 | expr: HirRelationExpr, |
| 957 | target_types: I, |
| 958 | ) -> Result<HirRelationExpr, CastRelationError> |
| 959 | where |
| 960 | I: IntoIterator<Item = &'a SqlScalarType>, |
| 961 | { |
| 962 | let ecx = &ExprContext { |
| 963 | qcx, |
| 964 | name: "values", |
| 965 | scope: &Scope::empty(), |
| 966 | relation_type: &qcx.relation_type(&expr), |
| 967 | allow_aggregates: false, |
| 968 | allow_subqueries: true, |
| 969 | allow_parameters: true, |
| 970 | allow_windows: false, |
| 971 | }; |
| 972 | let mut map_exprs = vec![]; |
| 973 | let mut project_key = vec![]; |
| 974 | for (i, target_typ) in target_types.into_iter().enumerate() { |
| 975 | let expr = HirScalarExpr::column(i); |
| 976 | // We plan every cast and check the evaluated expressions rather than |
| 977 | // checking the types directly because of some complex casting rules |
| 978 | // between types not expressed in `SqlScalarType` equality. |
| 979 | match typeconv::plan_cast(ecx, ccx, expr.clone(), target_typ) { |
| 980 | Ok(cast_expr) => { |
| 981 | if expr == cast_expr { |
| 982 | // Cast between types was unnecessary |
| 983 | project_key.push(i); |
| 984 | } else { |
| 985 | // Cast between types required |
| 986 | project_key.push(ecx.relation_type.arity() + map_exprs.len()); |
| 987 | map_exprs.push(cast_expr); |
| 988 | } |
| 989 | } |
| 990 | Err(_) => { |
| 991 | return Err(CastRelationError { |
| 992 | column: i, |
| 993 | source_type: ecx.scalar_type(&expr), |
| 994 | target_type: target_typ.clone(), |
| 995 | }); |
| 996 | } |
| 997 | } |
| 998 | } |
| 999 | Ok(expr.map(map_exprs).project(project_key)) |
| 1000 | } |
| 1001 | |
| 1002 | /// Plans an expression in the AS OF position of a `SELECT` or `SUBSCRIBE`, or `CREATE MATERIALIZED |
| 1003 | /// VIEW` statement. |