pratham76 commented on code in PR #58656:
URL: https://github.com/apache/spark/pull/58656#discussion_r4072209586


##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/subquery.scala:
##########
@@ -414,7 +433,8 @@ object RewritePredicateSubquery extends Rule[LogicalPlan] 
with PredicateHelper {
               existenceJoin, newCondition, subHint)
           introducedAttrs += exists
           exists
-        case Not(InSubquery(values, ListQuery(sub, _, _, _, conditions, 
subHint))) =>
+        case sq @ Not(InSubquery(values, ListQuery(sub, _, _, _, conditions, 
subHint)))
+            if canRewrite(sq) =>
           val exists = AttributeReference("exists", BooleanType, nullable = 
false)()
           // Deduplicate conflicting attributes if any.
           val newSub = dedupSubqueryOnSelfJoin(newPlan, sub, Some(values))

Review Comment:
   Confirmed, and the asymmetry is real. Building the state directly in a 
Catalyst test -- the analyzer's `DeduplicateRelations` removes it from every 
SQL query I could write, which is why no existing test covers it a nested 
sub-query that references only the sub-query it is nested in is reported as 
referencing both plans:
   ```
   
UNSUPPORTED_SUBQUERY_EXPRESSION_CATEGORY.NESTED_SUBQUERY_REFERENCING_OUTER_AND_INNER_QUERY
   ```
   exactly as you predicted, because the single shared attribute satisfies both 
sides of the classification.
   
   I did not move `dedupSubqueryOnSelfJoin` ahead of the routing. Doing that 
hits the risk in your own note -- "Moving deduplication without rewriting 
correlated condition references can create ambiguous or stale join expressions" 
-- and here it is not hypothetical. Deduplication aliases the sub-query plan's 
`a` to a new ExprId, while the hoisted condition still says `a`. The semi 
join's left side is the outer plan, which still produces `a`, so the condition 
would silently bind to the outer attribute instead of the sub-query's: a 
correlated predicate quietly turned into a self-reference, with no error. The 
IN arms avoid this only because they rebuild `inConditions` from
   `dedupSub.output`; the hoisted `conditions` they pass through have the same 
exposure. So the classification is made collision-proof instead. 
`effectivelyReferencesPlanOnly` attributes an attribute that *both* plans 
produce to the sub-query plan, on the grounds that a nested sub-query resolves 
in the scope of the sub-query it sits in, so a shared ExprId is that 
sub-query's own. The routing then matches what the IN arms get from a 
deduplicated plan, without touching deduplication or the error it raises.
   
   A second finding while testing this: in that state the rewrite cannot 
complete either way. `buildJoin` passes the semi join condition to 
`dedupSubqueryOnSelfJoin`, which has always rejected a condition naming a 
duplicated attribute, so the query ends at `_LEGACY_ERROR_TEMP_1212` 
(`conflictingAttributesInJoinConditionError`) -- the pre-existing behaviour you 
describe in the comment on the dedup anchor. A correlated EXISTS's hoisted 
condition always names sub-plan attributes, so any shared ExprId the condition 
mentions lands there. The routing fix therefore changes *which* error a user 
sees, from a new 0A000 that misdescribes the query to the long-standing 
conflict error that names the duplicated attribute, rather than making the 
query work. The new test in `RewriteSubquerySuite` pins that: it asserts the 
conflict error, and fails with 
`NESTED_SUBQUERY_REFERENCING_OUTER_AND_INNER_QUERY` if the classification is 
reverted. I have not tried to make that shape succeed. That needs dedupl
 ication that rewrites the hoisted condition along with the plan, which is your 
"single preparation step" and changes a pre-existing error path for all four 
arms. Happy to take it on, here or separately, if you want it in scope.



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