zzwqqq commented on code in PR #5211:
URL: https://github.com/apache/calcite/pull/5211#discussion_r3880960666


##########
core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableModifyRule.java:
##########
@@ -44,18 +93,89 @@ protected EnumerableTableModifyRule(Config config) {
 
   @Override public @Nullable RelNode convert(RelNode rel) {
     final TableModify modify = (TableModify) rel;
+    final RelOptCluster cluster = modify.getCluster();
     final ModifiableTable modifiableTable =
         modify.getTable().unwrap(ModifiableTable.class);
     if (modifiableTable == null) {
       return null;
     }
     final RelTraitSet traitSet =
         modify.getTraitSet().replace(EnumerableConvention.INSTANCE);
+    RelNode input = convert(modify.getInput(), traitSet);
+    if (modify.isInsert() || modify.isUpdate()) {
+      // INSERT assigns stored columns; UPDATE assigns columns in the SET list.
+      RelDataType assignmentType = modify.isInsert()
+          ? RelOptTableImpl.realRowType(modify.getTable())
+          : modify.getCatalogReader().createTypeFromProjection(
+              modify.getTable().getRowType(),
+              requireNonNull(modify.getUpdateColumnList(), 
"updateColumnList"));
+      if (modify.isFlattened()) {
+        // TableModify flattens its input, so flatten the target fields too.
+        assignmentType =
+            SqlTypeUtil.flattenRecordType(cluster.getTypeFactory(), 
assignmentType, null);
+      }
+
+      final RexBuilder rexBuilder = cluster.getRexBuilder();
+      final List<RexNode> projects =
+          new ArrayList<>(rexBuilder.identityProjects(input.getRowType()));
+      final List<RexNode> checks = new ArrayList<>();
+      // UPDATE appends SET values to the old row; INSERT has only new values.
+      final int assignmentOffset = projects.size() - 
assignmentType.getFieldCount();
+      for (RelDataTypeField field : assignmentType.getFieldList()) {
+        final int sourceOrdinal = assignmentOffset + field.getIndex();
+        final RexNode source = projects.get(sourceOrdinal);
+        final RelDataType targetType = field.getType();
+        final SqlTypeName targetName = targetType.getSqlTypeName();
+        if (SqlTypeUtil.inCharOrBinaryFamilies(targetType)) {
+          if (targetType.getPrecision() < 0) {
+            continue;
+          }
+          // Check character and binary lengths because their casts may 
truncate.

Review Comment:
   Understood. I’ll summarize the alternatives in JIRA so we can discuss the 
extension point there before changing the PR.



-- 
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]

Reply via email to