From 45ff89e704eecd54880ff499ac0d24552f86afd7 Mon Sep 17 00:00:00 2001 From: xuzifu666 Date: Thu, 6 Nov 2025 16:31:30 +0800 Subject: [PATCH 1/2] [CALCITE-6947] Support LogicalSnapshot in RelShuttle --- .../calcite/rel/RelHomogeneousShuttle.java | 5 +++++ .../org/apache/calcite/rel/RelShuttle.java | 3 +++ .../apache/calcite/rel/RelShuttleImpl.java | 5 +++++ .../calcite/rel/logical/LogicalSnapshot.java | 6 ++++++ .../calcite/test/SqlHintsConverterTest.java | 8 +++++++ .../calcite/test/SqlToRelConverterTest.java | 21 +++++++++++++++++++ site/_docs/history.md | 5 +++++ 7 files changed, 53 insertions(+) diff --git a/core/src/main/java/org/apache/calcite/rel/RelHomogeneousShuttle.java b/core/src/main/java/org/apache/calcite/rel/RelHomogeneousShuttle.java index d38f39649cfe..72c4e8af2918 100644 --- a/core/src/main/java/org/apache/calcite/rel/RelHomogeneousShuttle.java +++ b/core/src/main/java/org/apache/calcite/rel/RelHomogeneousShuttle.java @@ -29,6 +29,7 @@ import org.apache.calcite.rel.logical.LogicalMinus; import org.apache.calcite.rel.logical.LogicalProject; import org.apache.calcite.rel.logical.LogicalRepeatUnion; +import org.apache.calcite.rel.logical.LogicalSnapshot; import org.apache.calcite.rel.logical.LogicalSort; import org.apache.calcite.rel.logical.LogicalTableModify; import org.apache.calcite.rel.logical.LogicalUnion; @@ -91,6 +92,10 @@ public class RelHomogeneousShuttle extends RelShuttleImpl { return visit((RelNode) sort); } + @Override public RelNode visit(LogicalSnapshot snapshot) { + return visit((RelNode) snapshot); + } + @Override public RelNode visit(LogicalExchange exchange) { return visit((RelNode) exchange); } diff --git a/core/src/main/java/org/apache/calcite/rel/RelShuttle.java b/core/src/main/java/org/apache/calcite/rel/RelShuttle.java index f9203058cbda..3143c734d5f0 100644 --- a/core/src/main/java/org/apache/calcite/rel/RelShuttle.java +++ b/core/src/main/java/org/apache/calcite/rel/RelShuttle.java @@ -30,6 +30,7 @@ import org.apache.calcite.rel.logical.LogicalMinus; import org.apache.calcite.rel.logical.LogicalProject; import org.apache.calcite.rel.logical.LogicalRepeatUnion; +import org.apache.calcite.rel.logical.LogicalSnapshot; import org.apache.calcite.rel.logical.LogicalSort; import org.apache.calcite.rel.logical.LogicalTableModify; import org.apache.calcite.rel.logical.LogicalUnion; @@ -67,6 +68,8 @@ public interface RelShuttle { RelNode visit(LogicalSort sort); + RelNode visit(LogicalSnapshot snapshot); + RelNode visit(LogicalExchange exchange); RelNode visit(LogicalTableModify modify); diff --git a/core/src/main/java/org/apache/calcite/rel/RelShuttleImpl.java b/core/src/main/java/org/apache/calcite/rel/RelShuttleImpl.java index 1c0d0dd5ee55..c5fea931fff8 100644 --- a/core/src/main/java/org/apache/calcite/rel/RelShuttleImpl.java +++ b/core/src/main/java/org/apache/calcite/rel/RelShuttleImpl.java @@ -31,6 +31,7 @@ import org.apache.calcite.rel.logical.LogicalMinus; import org.apache.calcite.rel.logical.LogicalProject; import org.apache.calcite.rel.logical.LogicalRepeatUnion; +import org.apache.calcite.rel.logical.LogicalSnapshot; import org.apache.calcite.rel.logical.LogicalSort; import org.apache.calcite.rel.logical.LogicalTableModify; import org.apache.calcite.rel.logical.LogicalUnion; @@ -131,6 +132,10 @@ protected RelNode visitChildren(RelNode rel) { return visitChildren(sort); } + @Override public RelNode visit(LogicalSnapshot snapshot) { + return visitChildren(snapshot); + } + @Override public RelNode visit(LogicalExchange exchange) { return visitChildren(exchange); } diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalSnapshot.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalSnapshot.java index d03293ee3420..e030414316fc 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalSnapshot.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalSnapshot.java @@ -23,6 +23,7 @@ import org.apache.calcite.rel.RelDistributionTraitDef; import org.apache.calcite.rel.RelInput; import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.RelShuttle; import org.apache.calcite.rel.core.Snapshot; import org.apache.calcite.rel.hint.RelHint; import org.apache.calcite.rel.metadata.RelMdCollation; @@ -103,4 +104,9 @@ public static LogicalSnapshot create(RelNode input, RexNode period) { @Override public RelNode withHints(final List hintList) { return new LogicalSnapshot(getCluster(), traitSet, hintList, input, getPeriod()); } + + @Override public RelNode accept(RelShuttle shuttle) { + return shuttle.visit(this); + } + } diff --git a/core/src/test/java/org/apache/calcite/test/SqlHintsConverterTest.java b/core/src/test/java/org/apache/calcite/test/SqlHintsConverterTest.java index 9a75c50ada20..28469512e8a6 100644 --- a/core/src/test/java/org/apache/calcite/test/SqlHintsConverterTest.java +++ b/core/src/test/java/org/apache/calcite/test/SqlHintsConverterTest.java @@ -54,6 +54,7 @@ import org.apache.calcite.rel.logical.LogicalJoin; import org.apache.calcite.rel.logical.LogicalMinus; import org.apache.calcite.rel.logical.LogicalProject; +import org.apache.calcite.rel.logical.LogicalSnapshot; import org.apache.calcite.rel.logical.LogicalSort; import org.apache.calcite.rel.logical.LogicalUnion; import org.apache.calcite.rel.logical.LogicalValues; @@ -919,6 +920,13 @@ private static class HintCollector extends RelShuttleImpl { return super.visit(sort); } + @Override public RelNode visit(LogicalSnapshot snapshot) { + if (!snapshot.getHints().isEmpty()) { + this.hintsCollect.add("Snapshot:" + snapshot.getHints()); + } + return super.visit(snapshot); + } + @Override public RelNode visit(LogicalValues values) { if (!values.getHints().isEmpty()) { this.hintsCollect.add("Values:" + values.getHints()); diff --git a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java index e0477c650121..8188a05f1b40 100644 --- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java +++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java @@ -41,6 +41,7 @@ import org.apache.calcite.rel.logical.LogicalCalc; import org.apache.calcite.rel.logical.LogicalFilter; import org.apache.calcite.rel.logical.LogicalRepeatUnion; +import org.apache.calcite.rel.logical.LogicalSnapshot; import org.apache.calcite.rel.logical.LogicalSort; import org.apache.calcite.rel.logical.LogicalTableModify; import org.apache.calcite.rel.rules.CoreRules; @@ -3086,6 +3087,26 @@ void checkCorrelatedMapSubQuery(boolean expand) { assertThat(rels.get(0), instanceOf(LogicalCalc.class)); } + /** Test case for + * [CALCITE-6947] + * Support LogicalSnapshot in RelShuttle. */ + @Test void testRelShuttleForLogicalSnapshot() { + final String sql = "select * from products_temporal " + + "for system_time as of TIMESTAMP '2011-01-02 00:00:00'"; + final RelNode rel = sql(sql).toRel(); + final List rels = new ArrayList<>(); + final RelShuttleImpl visitor = new RelShuttleImpl() { + @Override public RelNode visit(LogicalSnapshot modify) { + RelNode visitedRel = super.visit(modify); + rels.add(visitedRel); + return visitedRel; + } + }; + rel.accept(visitor); + assertThat(rels, hasSize(1)); + assertThat(rels.get(0), instanceOf(LogicalSnapshot.class)); + } + @Test void testRelShuttleForLogicalTableModify() { final String sql = "insert into emp select * from emp"; final RelNode rel = sql(sql).toRel(); diff --git a/site/_docs/history.md b/site/_docs/history.md index 0066dde468e2..434098044f33 100644 --- a/site/_docs/history.md +++ b/site/_docs/history.md @@ -49,6 +49,11 @@ other software versions as specified in gradle.properties. #### Breaking Changes {: #breaking-1-42-0} +* [CALCITE-6947] +The feature support LogicalSnapshot in RelShuttle. please note that If there’s a class X that extends LogicalSnapshot +and a class Y extends Snapshot, but not LogicalSnapshot, then X will call RelShuttle.visit(LogicalSnapshot) +and Y will call RelShuttle.visit(RelNode other) + #### New features {: #new-features-1-42-0} From 5cd9a37aef8f7cdc4802daac051943f177b5fd06 Mon Sep 17 00:00:00 2001 From: xuzifu666 Date: Tue, 18 Nov 2025 11:00:23 +0800 Subject: [PATCH 2/2] Addressed --- .../org/apache/calcite/test/SqlToRelConverterTest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java index 8188a05f1b40..d99d3d0aeef9 100644 --- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java +++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java @@ -3095,14 +3095,24 @@ void checkCorrelatedMapSubQuery(boolean expand) { + "for system_time as of TIMESTAMP '2011-01-02 00:00:00'"; final RelNode rel = sql(sql).toRel(); final List rels = new ArrayList<>(); + final List otherRels = new ArrayList<>(); final RelShuttleImpl visitor = new RelShuttleImpl() { @Override public RelNode visit(LogicalSnapshot modify) { RelNode visitedRel = super.visit(modify); rels.add(visitedRel); return visitedRel; } + + @Override public RelNode visit(RelNode other) { + if (other instanceof LogicalSnapshot) { + otherRels.add(other); + } + RelNode visitedRel = super.visit(other); + return visitedRel; + } }; rel.accept(visitor); + assertThat(otherRels, hasSize(0)); assertThat(rels, hasSize(1)); assertThat(rels.get(0), instanceOf(LogicalSnapshot.class)); }