You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by xu...@apache.org on 2026/09/12 13:07:07 UTC

(calcite) branch main updated: [CALCITE-4596] RelFieldTrimmer#trimFields fails if values row type is empty record

This is an automated email from the ASF dual-hosted git repository.

xuzifu666 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new 3b0444d98a [CALCITE-4596] RelFieldTrimmer#trimFields fails if values row type is empty record
3b0444d98a is described below

commit 3b0444d98ab2708a4de503f63ea70006b7efeb58
Author: Yu Xu <12...@qq.com>
AuthorDate: Tue Sep 8 22:02:54 2026 +0800

    [CALCITE-4596] RelFieldTrimmer#trimFields fails if values row type is empty record
---
 .../org/apache/calcite/sql2rel/RelFieldTrimmer.java   | 14 ++++++++++++--
 .../apache/calcite/sql2rel/RelFieldTrimmerTest.java   | 19 +++++++++++++++++++
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java b/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
index d47adb17b5..b86f02898c 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
@@ -1030,8 +1030,13 @@ public TrimResult trimFields(
 
     // Fennel abhors an empty row type, so pretend that the parent rel
     // wants the last field. (The last field is the least likely to be a
-    // system field.)
+    // system field.) But if the input already has zero columns, there is
+    // no field to give; return it unchanged.
     if (fieldsUsed.isEmpty()) {
+      if (fieldCount == 0) {
+        Mapping mapping = Mappings.createIdentity(fieldCount);
+        return result(setOp, mapping);
+      }
       fieldsUsed = ImmutableBitSet.of(rowType.getFieldCount() - 1);
     }
 
@@ -1301,8 +1306,13 @@ public TrimResult trimFields(
 
     // If they are asking for no fields, we can't give them what they want,
     // because zero-column records are illegal. Give them the last field,
-    // which is unlikely to be a system field.
+    // which is unlikely to be a system field. But if the input already has
+    // zero columns, there is no field to give; return it unchanged.
     if (fieldsUsed.isEmpty()) {
+      if (fieldCount == 0) {
+        Mapping mapping = Mappings.createIdentity(fieldCount);
+        return result(values, mapping);
+      }
       fieldsUsed = ImmutableBitSet.range(fieldCount - 1, fieldCount);
     }
 
diff --git a/core/src/test/java/org/apache/calcite/sql2rel/RelFieldTrimmerTest.java b/core/src/test/java/org/apache/calcite/sql2rel/RelFieldTrimmerTest.java
index 535dc07b16..7e12cac8ed 100644
--- a/core/src/test/java/org/apache/calcite/sql2rel/RelFieldTrimmerTest.java
+++ b/core/src/test/java/org/apache/calcite/sql2rel/RelFieldTrimmerTest.java
@@ -31,7 +31,9 @@
 import org.apache.calcite.rel.hint.HintPredicates;
 import org.apache.calcite.rel.hint.HintStrategyTable;
 import org.apache.calcite.rel.hint.RelHint;
+import org.apache.calcite.rel.logical.LogicalValues;
 import org.apache.calcite.rel.rules.CoreRules;
+import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexCorrelVariable;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.schema.SchemaPlus;
@@ -553,6 +555,23 @@ public static Frameworks.ConfigBuilder config() {
     }
   }
 
+  /** Test case for
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-4596">[CALCITE-4596]
+   * RelFieldTrimmer#trimFields fails if values row type is empty record</a>. */
+  @Test void testTrimEmptyValues() {
+    final RelBuilder builder = RelBuilder.create(config().build());
+    final RelDataType rowType = builder.getTypeFactory().builder().build();
+    final RelNode root = builder.values(rowType).build();
+
+    final RelFieldTrimmer fieldTrimmer = new RelFieldTrimmer(null, builder);
+    final RelNode trimmed = fieldTrimmer.trim(root);
+
+    final String expected = ""
+        + "LogicalValues(tuples=[[]])\n";
+    assertThat(trimmed, instanceOf(LogicalValues.class));
+    assertThat(trimmed, hasTree(expected));
+  }
+
   @Test void testUnionFieldTrimmer() {
     final RelBuilder builder = RelBuilder.create(config().build());
     final RelNode root =