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