This is an automated email from the ASF dual-hosted git repository.
snuyanzin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git
The following commit(s) were added to refs/heads/master by this push:
new 213cea73caa [FLINK-40937][table] `UPDATE` fails with
`IndexOutOfBoundsException` when a `SET` value's type doesn't match the column
213cea73caa is described below
commit 213cea73caab8c6145b16a8e3186dd5e5e0192ed
Author: Sergey Nuyanzin <[email protected]>
AuthorDate: Wed Oct 7 13:13:06 2026 +0200
[FLINK-40937][table] `UPDATE` fails with `IndexOutOfBoundsException` when a
`SET` value's type doesn't match the column
---
.../calcite/sql/validate/SqlValidatorImpl.java | 30 ++++++++++++++--------
.../operations/SqlDmlToOperationConverterTest.java | 21 +++++++++++++++
2 files changed, 40 insertions(+), 11 deletions(-)
diff --git
a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
index e8e9320718a..39c4e83d285 100644
---
a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
+++
b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
@@ -200,25 +200,25 @@ import static org.apache.calcite.util.Util.first;
*
* <p>Lines 2729 ~ 2747, set the correct scope for VECTOR_SEARCH.
*
- * <p>Lines 4320 ~ 4324, 7175 ~ 7181 Flink improves Optimize the retrieval of
sub-operands in
+ * <p>Lines 4320 ~ 4324, 7183 ~ 7189 Flink improves Optimize the retrieval of
sub-operands in
* SqlCall when using NamedParameters at {@link SqlValidatorImpl#checkRollUp}.
*
- * <p>Lines 5905 ~ 5911, FLINK-24352 Add null check for temporal table check
on SqlSnapshot.
+ * <p>Lines 5913 ~ 5919, FLINK-24352 Add null check for temporal table check
on SqlSnapshot.
*
- * <p>Lines 6322-6337, CALCITE-7538 should be removed after upgrading Calcite
to 1.42.0.
+ * <p>Lines 6330-6345, CALCITE-7538 should be removed after upgrading Calcite
to 1.42.0.
*
- * <p>Lines 6347-6349, CALCITE-7466 should be removed after upgrading Calcite
to 1.42.0.
+ * <p>Lines 6355-6357, CALCITE-7466 should be removed after upgrading Calcite
to 1.42.0.
*
- * <p>Lines 6403-6405, CALCITE-7470 should be removed after upgrading Calcite
to 1.42.0.
+ * <p>Lines 6411-6413, CALCITE-7470 should be removed after upgrading Calcite
to 1.42.0.
*
- * <p>Lines 7266-7274, Added in FLINK-39695 (backport of CALCITE-6764):
propagate parent record
+ * <p>Lines 7274-7282, Added in FLINK-39695 (backport of CALCITE-6764):
propagate parent record
* nullability to nested fields.
*
- * <p>Lines 8142-8165, CALCITE-7486 should be removed after upgrading Calcite
to 1.42.0.
+ * <p>Lines 8150-8173, CALCITE-7486 should be removed after upgrading Calcite
to 1.42.0.
*
- * <p>Lines 8212-8229, CALCITE-7486 should be removed after upgrading Calcite
to 1.42.0.
+ * <p>Lines 8220-8237, CALCITE-7486 should be removed after upgrading Calcite
to 1.42.0.
*
- * <p>Lines 8274-8282, CALCITE-7486 should be removed after upgrading Calcite
to 1.42.0.
+ * <p>Lines 8282-8290, CALCITE-7486 should be removed after upgrading Calcite
to 1.42.0.
*/
public class SqlValidatorImpl implements SqlValidatorWithHints {
// ~ Static fields/initializers
---------------------------------------------
@@ -5730,8 +5730,16 @@ public class SqlValidatorImpl implements
SqlValidatorWithHints {
}
} else if (query instanceof SqlUpdate) {
SqlUpdate update = (SqlUpdate) query;
- if (update.getSourceExpressionList() != null) {
- return update.getSourceExpressionList().get(ordinal);
+ // FLINK MODIFICATION BEGIN
+ final SqlNodeList sourceExpressionList =
update.getSourceExpressionList();
+ if (sourceExpressionList != null) {
+ // SET expressions occupy the last positions of the row type.
+ final int exprOrdinal = ordinal - (sourceCount -
sourceExpressionList.size());
+ if (exprOrdinal < 0 || exprOrdinal >=
sourceExpressionList.size()) {
+ return query; // give up
+ }
+ return sourceExpressionList.get(exprOrdinal);
+ // FLINK MODIFICATION END
} else {
return getNthExpr(
SqlNonNullableAccessors.getSourceSelect(update),
ordinal, sourceCount);
diff --git
a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/operations/SqlDmlToOperationConverterTest.java
b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/operations/SqlDmlToOperationConverterTest.java
index 89d2ee48822..a13a05fa8d6 100644
---
a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/operations/SqlDmlToOperationConverterTest.java
+++
b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/operations/SqlDmlToOperationConverterTest.java
@@ -23,6 +23,7 @@ import org.apache.flink.table.api.DataTypes;
import org.apache.flink.table.api.ExplainDetail;
import org.apache.flink.table.api.Schema;
import org.apache.flink.table.api.SqlDialect;
+import org.apache.flink.table.api.ValidationException;
import org.apache.flink.table.catalog.CatalogTable;
import org.apache.flink.table.catalog.ObjectIdentifier;
import org.apache.flink.table.expressions.ResolvedExpression;
@@ -351,6 +352,26 @@ class SqlDmlToOperationConverterTest extends
SqlNodeToOperationConversionTestBas
.isEqualTo(ObjectIdentifier.of("builtin", "default", "t1"));
}
+ @Test
+ void testUpdateTypeMismatch() {
+ Map<String, String> options = new HashMap<>();
+ options.put("connector", TestUpdateDeleteTableFactory.IDENTIFIER);
+ CatalogTable catalogTable =
+ CatalogTable.newBuilder()
+ .schema(Schema.newBuilder().column("a",
DataTypes.INT().notNull()).build())
+ .options(options)
+ .build();
+ ObjectIdentifier tableIdentifier =
+ ObjectIdentifier.of("builtin", "default",
"test_update_mismatch");
+ catalogManager.createTable(catalogTable, tableIdentifier, false);
+
+ // CALCITE-7830: a SET value type mismatch must be reported, not throw
+ // IndexOutOfBoundsException.
+ assertThatThrownBy(() -> parse("UPDATE test_update_mismatch SET a =
true"))
+ .isInstanceOf(ValidationException.class)
+ .hasMessageContaining("Cannot assign to target field 'a'");
+ }
+
private void checkExplainSql(String sql) {
FlinkPlannerImpl planner = getPlannerBySqlDialect(SqlDialect.DEFAULT);
CalciteParser parser = getParserBySqlDialect(SqlDialect.DEFAULT);