raminqaf opened a new pull request, #29688:
URL: https://github.com/apache/flink/pull/29688
## What is the purpose of the change
Adds the infix cast operator `expr::type`, a shorthand for `CAST(expr AS
type)` that users know from PostgreSQL. It is most useful with VARIANT, where
every field access ends in a cast:
```sql
SELECT payload['user']['id']::BIGINT, payload['tags']::ARRAY<STRING>
FROM events
```
On master this fails to parse, e.g. `a::INT` gives `Encountered ":" at line
1, column 2.` With this PR:
| Input | Parses to |
|----------------------|----------------------------------|
| `a::INT + 1` | `CAST(a AS INT) + 1` |
| `a + b::INT` | `a + CAST(b AS INT)` |
| `-a::INT` | `-CAST(a AS INT)` |
| `m['k']::INT` | `CAST(m['k'] AS INT)` |
| `v::INT::STRING` | `CAST(CAST(v AS INT) AS STRING)` |
| `(v::ARRAY<INT>)[1]` | `CAST(v AS ARRAY<INT>)[1]` |
| `v::ARRAY<INT>[1]` | Parse error, see below |
`v::ARRAY<INT>[1]` fails with: `'[' cannot follow the target type of '::'.
Use (x::ARRAY<INT>)[1] to access an element of the result, or ARRAY<INT> to
name an array type.`
Decisions worth a look:
- **The parser turns `::` into a plain `CAST` call.** Validation, planning,
codegen and unparsed or persisted query text all see `CAST(...)`, so nothing
after the parser changes. Calcite's `INFIX_CAST` lives in the Babel parser,
which Flink doesn't use. Reusing its operator would print `a :: INT` into
persisted query text, and Calcite changed that output in 1.42 (CALCITE-7475).
The production plugs into the existing `binaryOperatorsTokens` and
`extraBinaryExpressions` hooks in `Parser.tdd`, so `Parser.jj` is untouched.
- **`x::T[i]` is rejected.** Calcite 1.42 reads it as element access on the
result, PostgreSQL reads `T[i]` as an array type. Rejecting it keeps both
options open, and parentheses work today.
- **Known limits.** `x::INTERVAL DAY` isn't supported, since `DataType()`
has no interval qualifiers. Babel has the same limit. JavaCC reports one new
choice conflict: in `a::INT MULTISET UNION b`, `INT MULTISET` is read as the
type, so that needs parentheses. Flink doesn't register `MULTISET UNION`.
- **Out of scope, as in the ticket.** Table API, a `TRY_CAST` counterpart
and postfix access after `::`.
## Brief change log
- `SqlInfixCastOperator` and an `InfixCast` parser production that
desugars to `CAST`
- Docs: `value::type` added to the CAST entry
- Second commit: the VARIANT cases in `CastFunctionITCase` use `::`
instead of `CAST(... AS ...)`
## Verifying this change
This change added tests and can be verified as follows:
- `FlinkSqlParserImplTest#testInfixCast` covers precedence against
arithmetic, comparison, unary minus, item and field access, chaining,
sub-queries and the `[` rejection. `FlinkSqlUnParserTest` re-parses the
unparsed `CAST(...)` output.
- The VARIANT specs in `CastFunctionITCase` now write their casts as
`x::T`, about 100 cases through validation, planning and execution. `TRY_CAST`
cases keep their syntax.
## Does this pull request potentially affect one of the following parts:
- Dependencies (does it add or upgrade a dependency): no
- The public API, i.e., is any changed class annotated with
`@Public(Evolving)`: no
- The serializers: no
- The runtime per-record code paths (performance sensitive): no
- Anything that affects deployment or recovery: JobManager (and its
components), Checkpointing, Kubernetes/Yarn, ZooKeeper: no
- The S3 file system connector: no
## Documentation
- Does this pull request introduce a new feature? yes
- If yes, how is the feature documented? docs
---
##### Was generative AI tooling used to co-author this PR?
- [X] Yes (please specify the tool below)
Generated-by: Claude Code 2.1.314 (Claude Opus 5.5)
--
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]