1515import org .apache .calcite .rex .RexSubQuery ;
1616import org .apache .calcite .rex .RexUtil .SubQueryCollector ;
1717
18- /** Resolve correlated variable and get Depth map for RexFieldAccess */
19- // See OuterReferenceResolver.md for explanation how the Depth map is computed.
18+ /**
19+ * Resolve correlated variables and compute a depth map for {@link RexFieldAccess}.
20+ *
21+ * <p>Traverses a {@link RelNode} tree and:
22+ *
23+ * <ul>
24+ * <li>Tracks nesting depth of {@link CorrelationId}s across filters, projects, subqueries, and
25+ * correlates
26+ * <li>Computes "steps out" for each {@link RexFieldAccess} referencing a {@link
27+ * RexCorrelVariable}
28+ * </ul>
29+ *
30+ * See OuterReferenceResolver.md for details on how the depth map is computed.
31+ */
2032public class OuterReferenceResolver extends RelNodeVisitor <RelNode , RuntimeException > {
2133
2234 private final Map <CorrelationId , Integer > nestedDepth ;
2335 private final Map <RexFieldAccess , Integer > fieldAccessDepthMap ;
2436
2537 private final RexVisitor rexVisitor = new RexVisitor (this );
2638
39+ /** Creates a new resolver with empty depth tracking maps. */
2740 public OuterReferenceResolver () {
2841 nestedDepth = new HashMap <>();
2942 fieldAccessDepthMap = new IdentityHashMap <>();
3043 }
3144
45+ /**
46+ * Applies the resolver to a {@link RelNode} tree, computing the depth map.
47+ *
48+ * @param r the root relational node
49+ * @return the same node after traversal
50+ * @throws RuntimeException if the visitor encounters an unrecoverable condition
51+ */
3252 public Map <RexFieldAccess , Integer > apply (RelNode r ) {
3353 reverseAccept (r );
3454 return fieldAccessDepthMap ;
3555 }
3656
57+ /**
58+ * Visits a {@link Filter}, registering any correlation variables and visiting its condition.
59+ *
60+ * @param filter the filter node
61+ * @return the result of {@link RelNodeVisitor#visit(Filter)}
62+ * @throws RuntimeException if traversal fails
63+ */
3764 @ Override
3865 public RelNode visit (Filter filter ) throws RuntimeException {
3966 for (CorrelationId id : filter .getVariablesSet ()) {
@@ -43,6 +70,16 @@ public RelNode visit(Filter filter) throws RuntimeException {
4370 return super .visit (filter );
4471 }
4572
73+ /**
74+ * Visits a {@link Correlate}, handling correlation depth for both sides.
75+ *
76+ * <p>Special case: the right side is a correlated subquery in the rel tree (not a REX), so we
77+ * manually adjust depth before/after visiting it.
78+ *
79+ * @param correlate the correlate (correlated join) node
80+ * @return the correlate node
81+ * @throws RuntimeException if traversal fails
82+ */
4683 @ Override
4784 public RelNode visit (Correlate correlate ) throws RuntimeException {
4885 for (CorrelationId id : correlate .getVariablesSet ()) {
@@ -63,6 +100,13 @@ public RelNode visit(Correlate correlate) throws RuntimeException {
63100 return correlate ;
64101 }
65102
103+ /**
104+ * Visits a generic {@link RelNode}, applying the resolver to all the node inputs.
105+ *
106+ * @param other the node to visit
107+ * @return the node
108+ * @throws RuntimeException if traversal fails
109+ */
66110 @ Override
67111 public RelNode visitOther (RelNode other ) throws RuntimeException {
68112 for (RelNode child : other .getInputs ()) {
@@ -71,6 +115,14 @@ public RelNode visitOther(RelNode other) throws RuntimeException {
71115 return other ;
72116 }
73117
118+ /**
119+ * Visits a {@link Project}, registering correlation variables and visiting any subqueries within
120+ * its expressions.
121+ *
122+ * @param project the project node
123+ * @return the result of {@link RelNodeVisitor#visit(Project)}
124+ * @throws RuntimeException if traversal fails
125+ */
74126 @ Override
75127 public RelNode visit (Project project ) throws RuntimeException {
76128 for (CorrelationId id : project .getVariablesSet ()) {
@@ -84,13 +136,25 @@ public RelNode visit(Project project) throws RuntimeException {
84136 return super .visit (project );
85137 }
86138
139+ /** Rex visitor used to track correlation depth within expressions and subqueries. */
87140 private static class RexVisitor extends RexShuttle {
88141 final OuterReferenceResolver referenceResolver ;
89142
143+ /**
144+ * Creates a new Rex visitor bound to the given reference resolver.
145+ *
146+ * @param referenceResolver the parent resolver maintaining depth maps
147+ */
90148 RexVisitor (OuterReferenceResolver referenceResolver ) {
91149 this .referenceResolver = referenceResolver ;
92150 }
93151
152+ /**
153+ * Increments correlation depth when entering a subquery and decrements when exiting.
154+ *
155+ * @param subQuery the subquery expression
156+ * @return the same subquery
157+ */
94158 @ Override
95159 public RexNode visitSubQuery (RexSubQuery subQuery ) {
96160 referenceResolver .nestedDepth .replaceAll ((k , v ) -> v + 1 );
@@ -101,6 +165,12 @@ public RexNode visitSubQuery(RexSubQuery subQuery) {
101165 return subQuery ;
102166 }
103167
168+ /**
169+ * Records depth for {@link RexFieldAccess} referencing a {@link RexCorrelVariable}.
170+ *
171+ * @param fieldAccess the field access expression
172+ * @return the same field access
173+ */
104174 @ Override
105175 public RexNode visitFieldAccess (RexFieldAccess fieldAccess ) {
106176 if (fieldAccess .getReferenceExpr () instanceof RexCorrelVariable ) {
0 commit comments