This is an automated email from the ASF dual-hosted git repository.
asolimando 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 c425a5fa09 [CALCITE-7843] RelMdExpressionLineage should support Window
c425a5fa09 is described below
commit c425a5fa096c723a8c669df1c7cf2d92aa6bfd61
Author: Alessandro Solimando <[email protected]>
AuthorDate: Thu Oct 8 16:52:09 2026 +0200
[CALCITE-7843] RelMdExpressionLineage should support Window
---
.../rel/metadata/RelMdExpressionLineage.java | 17 ++++++++++++
.../org/apache/calcite/test/RelMetadataTest.java | 30 ++++++++++++++++++++++
...GeneratedMetadata_ExpressionLineageHandler.java | 2 ++
3 files changed, 49 insertions(+)
diff --git
a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExpressionLineage.java
b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExpressionLineage.java
index 3025ee1d4a..7ff467d1a7 100644
---
a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExpressionLineage.java
+++
b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExpressionLineage.java
@@ -32,6 +32,7 @@
import org.apache.calcite.rel.core.TableModify;
import org.apache.calcite.rel.core.TableScan;
import org.apache.calcite.rel.core.Union;
+import org.apache.calcite.rel.core.Window;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rex.RexBuilder;
@@ -440,6 +441,22 @@ protected RelMdExpressionLineage() {}
return mq.getExpressionLineage(rel.getInput(), outputExpression);
}
+ /**
+ * Expression lineage from {@link Window}.
+ *
+ * <p>If the expression references window function results, we cannot extract
+ * the lineage and we return null.
+ */
+ public @Nullable Set<RexNode> getExpressionLineage(Window rel,
+ RelMetadataQuery mq, RexNode outputExpression) {
+ final int inputFieldCount = rel.getInput().getRowType().getFieldCount();
+ final ImmutableBitSet inputFieldsUsed = extractInputRefs(outputExpression);
+ if (inputFieldsUsed.nextSetBit(inputFieldCount) >= 0) {
+ return null;
+ }
+ return mq.getExpressionLineage(rel.getInput(), outputExpression);
+ }
+
/**
* Expression lineage from Calc.
*/
diff --git a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
index 76ad8bf50e..daa4fc66c7 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -59,6 +59,7 @@
import org.apache.calcite.rel.core.TableScan;
import org.apache.calcite.rel.core.Union;
import org.apache.calcite.rel.core.Values;
+import org.apache.calcite.rel.core.Window;
import org.apache.calcite.rel.hint.RelHint;
import org.apache.calcite.rel.logical.LogicalAggregate;
import org.apache.calcite.rel.logical.LogicalExchange;
@@ -95,6 +96,7 @@
import org.apache.calcite.rel.rules.CoreRules;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexCall;
import org.apache.calcite.rex.RexCorrelVariable;
@@ -4574,6 +4576,34 @@ private void assertExpressionLineage(
assertThat(resultString, is("+([CATALOG, SALES, EMP].#0.$5, 1)"));
}
+ /** Test case for <a
href="https://issues.apache.org/jira/browse/CALCITE-7843">[CALCITE-7843]
+ * RelMdExpressionLineage should support Window</a>. */
+ @Test void testExpressionLineageWindow() {
+ final RelNode rel =
+ sql("select empno, row_number() over (order by sal) from emp").toRel();
+ final HepProgram program = new HepProgramBuilder()
+ .addRuleInstance(CoreRules.PROJECT_TO_LOGICAL_PROJECT_AND_WINDOW)
+ .build();
+ final HepPlanner planner = new HepPlanner(program);
+ planner.setRoot(rel);
+ final RelNode window = planner.findBestExp().getInput(0);
+ assertThat(window, instanceOf(Window.class));
+ final RelMetadataQuery mq = window.getCluster().getMetadataQuery();
+ final List<RelDataTypeField> fields = window.getRowType().getFieldList();
+
+ // empno is column 0 of the Window input
+ final Set<RexNode> r1 =
+ mq.getExpressionLineage(window, RexInputRef.of(0, fields));
+ assertThat(r1, hasSize(1));
+ final String resultString = r1.iterator().next().toString();
+ assertThat(resultString, is("[CATALOG, SALES, EMP].#0.$0"));
+
+ // row_number() is the last column, computed by the Window
+ final Set<RexNode> r2 =
+ mq.getExpressionLineage(window, RexInputRef.of(fields.size() - 1,
fields));
+ assertNull(r2);
+ }
+
/** Test case for <a
href="https://issues.apache.org/jira/browse/CALCITE-7070">[CALCITE-7070]
* FILTER_REDUCE_EXPRESSIONS crashes on expression BETWEEN ( NULL) AND
X</a>. */
@Test void testJoinCrash() {
diff --git
a/core/src/test/resources/org/apache/calcite/rel/metadata/janino/GeneratedMetadata_ExpressionLineageHandler.java
b/core/src/test/resources/org/apache/calcite/rel/metadata/janino/GeneratedMetadata_ExpressionLineageHandler.java
index 5e0c668348..e56f3c6c60 100644
---
a/core/src/test/resources/org/apache/calcite/rel/metadata/janino/GeneratedMetadata_ExpressionLineageHandler.java
+++
b/core/src/test/resources/org/apache/calcite/rel/metadata/janino/GeneratedMetadata_ExpressionLineageHandler.java
@@ -88,6 +88,8 @@ private java.util.Set getExpressionLineage_(
return
provider0.getExpressionLineage((org.apache.calcite.rel.core.TableScan) r, mq,
a2);
} else if (r instanceof org.apache.calcite.rel.core.Union) {
return
provider0.getExpressionLineage((org.apache.calcite.rel.core.Union) r, mq, a2);
+ } else if (r instanceof org.apache.calcite.rel.core.Window) {
+ return
provider0.getExpressionLineage((org.apache.calcite.rel.core.Window) r, mq, a2);
} else if (r instanceof org.apache.calcite.rel.RelNode) {
return provider0.getExpressionLineage((org.apache.calcite.rel.RelNode)
r, mq, a2);
} else {