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

mihaibudiu 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 36c4df140a [CALCITE-7819] RelMdTableReferences returns null for 
TableFunctionScan with relational inputs
36c4df140a is described below

commit 36c4df140a7bcd30e67c8569b73f467e72a75381
Author: Dongsheng He <[email protected]>
AuthorDate: Thu Sep 24 14:47:35 2026 +0800

    [CALCITE-7819] RelMdTableReferences returns null for TableFunctionScan with 
relational inputs
---
 .../calcite/rel/metadata/RelMdTableReferences.java | 23 +++++++++-
 .../org/apache/calcite/test/RelMetadataTest.java   | 51 ++++++++++++++++++++++
 .../GeneratedMetadata_TableReferencesHandler.java  |  2 +
 3 files changed, 75 insertions(+), 1 deletion(-)

diff --git 
a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdTableReferences.java 
b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdTableReferences.java
index ebcbdc187d..96691863f4 100644
--- 
a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdTableReferences.java
+++ 
b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdTableReferences.java
@@ -27,6 +27,7 @@
 import org.apache.calcite.rel.core.Sample;
 import org.apache.calcite.rel.core.SetOp;
 import org.apache.calcite.rel.core.Sort;
+import org.apache.calcite.rel.core.TableFunctionScan;
 import org.apache.calcite.rel.core.TableModify;
 import org.apache.calcite.rel.core.TableScan;
 import org.apache.calcite.rel.core.Window;
@@ -159,11 +160,31 @@ public Set<RelTableRef> getTableReferences(TableScan rel, 
RelMetadataQuery mq) {
    * references.
    */
   public @Nullable Set<RelTableRef> getTableReferences(SetOp rel, 
RelMetadataQuery mq) {
+    return getTableReferences(rel.getInputs(), mq);
+  }
+
+  /**
+   * Table references from the relational inputs of a TableFunctionScan.
+   *
+   * <p>Returns an empty set if there are no inputs, and {@code null} if the 
table
+   * references of any input cannot be determined. Tables accessed internally
+   * by the table function are not included.
+   */
+  public @Nullable Set<RelTableRef> getTableReferences(TableFunctionScan rel,
+      RelMetadataQuery mq) {
+    return getTableReferences(rel.getInputs(), mq);
+  }
+
+  /** Returns the union of the table references of {@code inputs}, assigning
+   * distinct entity numbers to repeated references to the same table, or 
{@code null}
+   * if the references of any input cannot be determined. */
+  private static @Nullable Set<RelTableRef> getTableReferences(
+      List<RelNode> inputs, RelMetadataQuery mq) {
     final Set<RelTableRef> result = new HashSet<>();
 
     // Infer column origin expressions for given references
     final Multimap<List<String>, RelTableRef> qualifiedNamesToRefs = 
HashMultimap.create();
-    for (RelNode input : rel.getInputs()) {
+    for (RelNode input : inputs) {
       final Map<RelTableRef, RelTableRef> currentTablesMapping = new 
HashMap<>();
       final Set<RelTableRef> inputTableRefs = mq.getTableReferences(input);
       if (inputTableRefs == null) {
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 b6625ab0b3..6123696154 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -163,6 +163,7 @@
 import static org.hamcrest.CoreMatchers.startsWith;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.closeTo;
+import static org.hamcrest.Matchers.empty;
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.hasToString;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -4928,6 +4929,56 @@ public void checkAllPredicatesAndTableSetOp(String sql) {
     assertNull(tableReferences);
   }
 
+  @Test void testTableReferencesTableFunctionScanSameTableInputs() {
+    final RelNode rel = fixture()
+        .withRelFn(builder ->
+            builder.scan("EMP")
+                .scan("EMP")
+                .functionScan(new MockSqlOperatorTable.DedupFunction(), 2,
+                    builder.cursor(2, 0), builder.cursor(2, 1))
+                .build())
+        .toRel();
+    final RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
+    assertThat(mq.getTableReferences(rel),
+        sortsAs("[[scott, EMP].#0, [scott, EMP].#1]"));
+  }
+
+  @Test void testTableReferencesTumbleTableFunction() {
+    final RelNode rel = sql("select * from table(tumble(table emp, "
+        + "descriptor(hiredate), interval '1' hour))").toRel();
+    final RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
+    assertThat(mq.getTableReferences(rel),
+        sortsAs("[[CATALOG, SALES, EMP].#0]"));
+  }
+
+  @Test void testTableReferencesTableFunctionScanZeroInputs() {
+    final RelNode rel = fixture()
+        .withRelFn(builder ->
+            builder.functionScan(new MockSqlOperatorTable.RampFunction(), 0,
+                    builder.literal(3))
+                .build())
+        .toRel();
+    final RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
+    assertThat(mq.getTableReferences(rel), empty());
+  }
+
+  @Test void testTableReferencesTableFunctionScanUnknownInput() {
+    final RelNode rel = fixture()
+        .withRelFn(builder -> {
+          final RelNode scan = builder.scan("EMP").build();
+          final RelNode unknown =
+              new DummyRelNode(scan.getCluster(), scan.getTraitSet(), scan);
+          return builder.push(unknown)
+              .push(scan)
+              .functionScan(new MockSqlOperatorTable.DedupFunction(), 2,
+                  builder.cursor(2, 0), builder.cursor(2, 1))
+              .build();
+        })
+        .toRel();
+    final RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
+    assertNull(mq.getTableReferences(rel));
+  }
+
   @Test void testNodeTypeCountEmp() {
     final String sql = "select * from emp";
     sql(sql)
diff --git 
a/core/src/test/resources/org/apache/calcite/rel/metadata/janino/GeneratedMetadata_TableReferencesHandler.java
 
b/core/src/test/resources/org/apache/calcite/rel/metadata/janino/GeneratedMetadata_TableReferencesHandler.java
index 6544dc4a69..85e36d9c7d 100644
--- 
a/core/src/test/resources/org/apache/calcite/rel/metadata/janino/GeneratedMetadata_TableReferencesHandler.java
+++ 
b/core/src/test/resources/org/apache/calcite/rel/metadata/janino/GeneratedMetadata_TableReferencesHandler.java
@@ -80,6 +80,8 @@ private java.util.Set getTableReferences_(
       return provider0.getTableReferences((org.apache.calcite.rel.core.SetOp) 
r, mq);
     } else if (r instanceof org.apache.calcite.rel.core.Sort) {
       return provider0.getTableReferences((org.apache.calcite.rel.core.Sort) 
r, mq);
+    } else if (r instanceof org.apache.calcite.rel.core.TableFunctionScan) {
+      return 
provider0.getTableReferences((org.apache.calcite.rel.core.TableFunctionScan) r, 
mq);
     } else if (r instanceof org.apache.calcite.rel.core.TableModify) {
       return 
provider0.getTableReferences((org.apache.calcite.rel.core.TableModify) r, mq);
     } else if (r instanceof org.apache.calcite.rel.core.TableScan) {

Reply via email to