Plans a cast between [`SqlScalarType`]s, specifying which types of casts are permitted using [`CastContext`]. # Errors If a cast between the `ScalarExpr`'s base type and the specified type is: - Not possible, e.g. `Bytes` to `Interval` - Not permitted, e.g. implicitly casting from `Float64` to `Float32`. - Not implemented yet
(
ecx: &ExprContext,
ccx: CastContext,
expr: HirScalarExpr,
to: &SqlScalarType,
)
| 1528 | /// - Not permitted, e.g. implicitly casting from `Float64` to `Float32`. |
| 1529 | /// - Not implemented yet |
| 1530 | pub fn plan_cast( |
| 1531 | ecx: &ExprContext, |
| 1532 | ccx: CastContext, |
| 1533 | expr: HirScalarExpr, |
| 1534 | to: &SqlScalarType, |
| 1535 | ) -> Result<HirScalarExpr, PlanError> { |
| 1536 | let from = ecx.scalar_type(&expr); |
| 1537 | |
| 1538 | // Close over `ccx`, `from`, and `to` to simplify error messages in the |
| 1539 | // face of intermediate expressions. |
| 1540 | let cast_inner = |from, to, expr| { |
| 1541 | get_cast(ecx, ccx, from, to) |
| 1542 | .map(|cast| cast(expr)) |
| 1543 | .map_err(|e| e.into_plan_error(ecx.name.into())) |
| 1544 | }; |
| 1545 | |
| 1546 | // Get cast which might include parameter rewrites + generating intermediate |
| 1547 | // expressions. |
| 1548 | // |
| 1549 | // String-like types get special handling to match PostgreSQL. |
| 1550 | // See: https://github.com/postgres/postgres/blob/6b04abdfc/ |
| 1551 | // src/backend/parser/parse_coerce.c#L3205-L3223 |
| 1552 | let from_category = TypeCategory::from_type(&from); |
| 1553 | let to_category = TypeCategory::from_type(to); |
| 1554 | if from_category == TypeCategory::String && to_category != TypeCategory::String { |
| 1555 | // Converting from stringlike to something non-stringlike. Handle as if |
| 1556 | // `from` were a `SqlScalarType::String. |
| 1557 | cast_inner(&SqlScalarType::String, to, expr) |
| 1558 | } else if from_category != TypeCategory::String && to_category == TypeCategory::String { |
| 1559 | // Converting from non-stringlike to something stringlike. Convert to a |
| 1560 | // `SqlScalarType::String` and then to the desired type. |
| 1561 | let expr = cast_inner(&from, &SqlScalarType::String, expr)?; |
| 1562 | cast_inner(&SqlScalarType::String, to, expr) |
| 1563 | } else { |
| 1564 | // Standard cast. |
| 1565 | cast_inner(&from, to, expr) |
| 1566 | } |
| 1567 | } |
| 1568 | |
| 1569 | /// Reports whether it is possible to perform a cast from the specified types. |
| 1570 | pub fn can_cast( |
no test coverage detected