This is an automated email from the ASF dual-hosted git repository.
raminqaf pushed a commit to branch release-2.4
in repository https://gitbox.apache.org/repos/asf/flink.git
The following commit(s) were added to refs/heads/release-2.4 by this push:
new 11fc481f799 [FLINK-41330][table] Return NULL for a VARIANT array index
outside the INT range (#29785)
11fc481f799 is described below
commit 11fc481f79985feb0f42d642b897151ea709560f
Author: Ramin Gharib <[email protected]>
AuthorDate: Thu Nov 5 08:13:36 2026 +0100
[FLINK-41330][table] Return NULL for a VARIANT array index outside the INT
range (#29785)
v[i] on an array VARIANT accepts any integer index, BIGINT included, but
the generated code cast the index to int before the lookup. An index outside
the INT range wrapped modulo 2^32 onto an existing element, so v[4294967297]
returned the first element. A BIGINT index is now range-checked as a long
before it is narrowed, and an index outside the INT range returns NULL like any
other out-of-range index. Smaller integer index types keep the int lookup,
since they cannot wrap onto a val [...]
Generated-by: Claude Code 2.1.318 (Claude Opus 5.5)
(cherry picked from commit e4d2b06ff33a6065ac2f1ba10d823ba30cdc0ad9)
---
.../planner/codegen/calls/ScalarOperatorGens.scala | 14 ++++++++++---
.../nodes/exec/stream/VariantSemanticTest.java | 24 ++++++++++++++++++++++
2 files changed, 35 insertions(+), 3 deletions(-)
diff --git
a/flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/codegen/calls/ScalarOperatorGens.scala
b/flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/codegen/calls/ScalarOperatorGens.scala
index 891f9c4b19a..b8f829b2205 100644
---
a/flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/codegen/calls/ScalarOperatorGens.scala
+++
b/flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/codegen/calls/ScalarOperatorGens.scala
@@ -1738,10 +1738,18 @@ object ScalarOperatorGens {
val keyType = key.resultType
val accessCode = if (isIntegerNumeric(keyType)) {
+ val elementAccess = if (keyType.is(BIGINT)) {
+ // Narrowing a BIGINT key to int before the range check would wrap an
out-of-range key
+ // onto an existing element. A smaller key cannot wrap onto a valid
index.
+ s"$keyTerm >= 1L && $keyTerm - 1L <= Integer.MAX_VALUE " +
+ s"? $variantTerm.getElement((int) ($keyTerm - 1L)) : null"
+ } else {
+ s"$variantTerm.getElement((int) $keyTerm - 1)"
+ }
generateIntegerKeyAccess(
variantTerm,
variantTypeTerm,
- keyTerm,
+ elementAccess,
resultTerm,
nullTerm,
tmpValue
@@ -1807,13 +1815,13 @@ object ScalarOperatorGens {
private def generateIntegerKeyAccess(
variantTerm: String,
variantTypeTerm: String,
- keyTerm: String,
+ elementAccess: String,
resultTerm: String,
nullTerm: String,
tmpValue: String): String = {
s"""
| if ($variantTerm.isArray()){
- | $variantTypeTerm $tmpValue = $variantTerm.getElement((int)
$keyTerm - 1);
+ | $variantTypeTerm $tmpValue = $elementAccess;
| if ($tmpValue == null) {
| $nullTerm = true;
| } else {
diff --git
a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/nodes/exec/stream/VariantSemanticTest.java
b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/nodes/exec/stream/VariantSemanticTest.java
index 580201100f4..1b9769f3262 100644
---
a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/nodes/exec/stream/VariantSemanticTest.java
+++
b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/nodes/exec/stream/VariantSemanticTest.java
@@ -520,6 +520,29 @@ public class VariantSemanticTest extends SemanticTestBase {
"sink_t")
.build();
+ static final TableTestProgram
VARIANT_ARRAY_ACCESS_WITH_INDEX_OUTSIDE_INT_RANGE =
+ TableTestProgram.of(
+
"variant-array-access-with-index-outside-int-range",
+ "validates that a BIGINT index outside the INT
range returns NULL")
+ .setupTableSource(
+ SourceTestStep.newBuilder("t")
+ .addSchema("v VARIANT", "i BIGINT")
+ .producedValues(
+ Row.of(
+
BUILDER.array().add(BUILDER.of(1)).build(),
+ 4294967297L),
+ Row.of(
+
BUILDER.array().add(BUILDER.of(1)).build(),
+ -4294967295L))
+ .build())
+ .setupTableSink(
+ SinkTestStep.newBuilder("sink_t")
+ .addSchema("e VARIANT")
+ .consumedValues(new Row(1), new Row(1))
+ .build())
+ .runSql("INSERT INTO sink_t SELECT v[i] FROM t")
+ .build();
+
static final TableTestProgram VARIANT_OBJECT_ACCESS =
TableTestProgram.of(
"variant-object-access",
@@ -697,6 +720,7 @@ public class VariantSemanticTest extends SemanticTestBase {
VARIANT_ARRAY_ACCESS,
VARIANT_ARRAY_ACCESS_WITH_DIFFERENT_INDEX_TYPES,
VARIANT_ARRAY_ACCESS_WITH_NON_LITERAL_INDEX,
+ VARIANT_ARRAY_ACCESS_WITH_INDEX_OUTSIDE_INT_RANGE,
VARIANT_OBJECT_ACCESS,
VARIANT_OBJECT_ACCESS_WITH_NON_LITERAL_KEY,
VARIANT_NESTED_ACCESS,