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);

Reply via email to