cloud-fan commented on code in PR #57654:
URL: https://github.com/apache/spark/pull/57654#discussion_r3688398916


##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/resolver/ResolutionValidator.scala:
##########
@@ -349,6 +351,36 @@ class ResolutionValidator {
     handleOperatorOutput(join)
   }
 
+  private def validateAsOfJoin(asOfJoin: AsOfJoin): Unit = {
+    // The inner scope keeps the per-child output overwrites done by 
[[handleOperatorOutput]] out

Review Comment:
   This is a line comment, so Scaladoc does not interpret the link syntax.
   
   ```suggestion
       // The inner scope keeps the per-child output overwrites done by 
`handleOperatorOutput` out
   ```



##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/resolver/JoinLikeResolver.scala:
##########
@@ -0,0 +1,274 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.spark.sql.catalyst.analysis.resolver
+
+import java.util.HashSet
+
+import org.apache.spark.sql.catalyst.SQLConfHelper
+import org.apache.spark.sql.catalyst.analysis.{withPosition, AnalysisErrorAt}
+import org.apache.spark.sql.catalyst.expressions.{Attribute, Expression, 
ExprId}
+import org.apache.spark.sql.catalyst.plans.{
+  ExistenceJoin,
+  FullOuter,
+  JoinType,
+  LeftAnti,
+  LeftOuter,
+  LeftSemi,
+  LeftSingle,
+  RightOuter
+}
+import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan
+import org.apache.spark.sql.catalyst.util._
+import org.apache.spark.sql.errors.QueryErrorsBase
+import org.apache.spark.sql.types.BooleanType
+
+/**
+ * Shared resolution mechanics for join-like binary operators, mixed into 
[[JoinResolver]] and
+ * other join-like resolvers: resolving two children in isolated multi-child 
scopes, computing a
+ * combined hidden output, filtering hidden metadata columns by join type, and 
resolving a boolean
+ * join condition. These routines carry subtle scope, CTE, hidden-output, 
metadata-nullability and
+ * [[ExprId]] behavior; keeping them here ensures join-like resolvers stay 
aligned and fixes cannot
+ * drift between them.
+ *
+ * For example, in the following query:
+ *
+ * {{{
+ * SELECT * FROM t1 JOIN t2 ON t1.key = t2.key;
+ * }}}
+ *
+ * the plan is:
+ *
+ * {{{
+ * Project [key#1, key#2]
+ * +- Join Inner, (key#1 = key#2)
+ *    :- SubqueryAlias t1
+ *    :  +- Relation t1[key#1]
+ *    +- SubqueryAlias t2
+ *       +- Relation t2[key#2]
+ * }}}
+ *
+ * `t1` and `t2` are each resolved by [[resolveJoinChild]] in their own 
[[NameScope]], and the
+ * condition `key#1 = key#2` is resolved by [[resolveJoinCondition]] against 
the union of the two
+ * child scopes.
+ */
+trait JoinLikeResolver extends SQLConfHelper with QueryErrorsBase {
+
+  protected val resolver: Resolver
+  protected val expressionResolver: ExpressionResolver
+
+  protected def scopes: NameScopeStack = resolver.getNameScopes
+  protected def cteRegistry: CteRegistry = resolver.getCteRegistry
+  protected def operatorResolutionContextStack: OperatorResolutionContextStack 
=
+    resolver.getOperatorResolutionContextStack
+  protected def expressionIdAssigner: ExpressionIdAssigner =
+    expressionResolver.getExpressionIdAssigner
+
+  /**
+   * Resolves a single join child in the context of a) new [[NameScope]] b) new
+   * [[ExpressionIdAssigner]] mapping c) new [[CteScope]] for the multi-child 
operator. Returns the
+   * resolved child together with its [[NameScope]], which the caller uses to 
compute the join
+   * output.
+   */
+  protected def resolveJoinChild(
+      unresolvedOperator: LogicalPlan,
+      child: LogicalPlan): (LogicalPlan, NameScope) = {
+    expressionIdAssigner.pushMapping()
+    scopes.pushScope()
+    cteRegistry.pushScopeForMultiChildOperator(
+      unresolvedOperator = unresolvedOperator,
+      unresolvedChild = child
+    )
+
+    try {
+      val resolvedChild = resolver.resolve(child)
+      (resolvedChild, scopes.current)
+    } finally {
+      cteRegistry.popScope()
+      scopes.popScope()
+      expressionIdAssigner.popMapping(collectChildMapping = true)
+    }
+  }
+
+  /**
+   * Resolves the join condition by __all__ attributes from child scopes. We 
overwrite the current

Review Comment:
   ```suggestion
      * Resolves the join condition against __all__ attributes from child 
scopes. We overwrite the current
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to