@@ -338,7 +338,7 @@ class Analyzer(
338338
339339 // When resolve `SortOrder`s in Sort based on child, don't report errors as
340340 // we still have chance to resolve it based on grandchild
341- case s @ Sort (ordering, global, child) =>
341+ case s @ Sort (ordering, global, child) if child.resolved && ! s.resolved =>
342342 val newOrdering = resolveSortOrders(ordering, child, throws = false )
343343 Sort (newOrdering, global, child)
344344
@@ -382,8 +382,9 @@ class Analyzer(
382382 private def resolveSortOrders (ordering : Seq [SortOrder ], plan : LogicalPlan , throws : Boolean ) = {
383383 ordering.map { order =>
384384 // Resolve SortOrder in one round.
385- // if throws == false, fail and return the origin one.
386- // else, throw exception.
385+ // If throws == false or the desired attribute doesn't exist
386+ // (like try to resolve `a.b` but `a` doesn't exist), fail and return the origin one.
387+ // Else, throw exception.
387388 try {
388389 val newOrder = order transformUp {
389390 case u @ UnresolvedAttribute (nameParts) =>
@@ -408,13 +409,13 @@ class Analyzer(
408409 def apply (plan : LogicalPlan ): LogicalPlan = plan transformUp {
409410 case s @ Sort (ordering, global, p @ Project (projectList, child))
410411 if ! s.resolved && p.resolved =>
411- val (resolvedOrdering , missing) = resolveAndFindMissing(ordering, p, child)
412+ val (newOrdering , missing) = resolveAndFindMissing(ordering, p, child)
412413
413414 // If this rule was not a no-op, return the transformed plan, otherwise return the original.
414415 if (missing.nonEmpty) {
415416 // Add missing attributes and then project them away after the sort.
416417 Project (p.output,
417- Sort (resolvedOrdering , global,
418+ Sort (newOrdering , global,
418419 Project (projectList ++ missing, child)))
419420 } else {
420421 logDebug(s " Failed to find $missing in ${p.output.mkString(" , " )}" )
@@ -429,35 +430,34 @@ class Analyzer(
429430 )
430431
431432 // Find sort attributes that are projected away so we can temporarily add them back in.
432- val (resolvedOrdering, unresolved ) = resolveAndFindMissing(ordering, a, groupingRelation)
433+ val (newOrdering, missingAttr ) = resolveAndFindMissing(ordering, a, groupingRelation)
433434
434435 // Find aggregate expressions and evaluate them early, since they can't be evaluated in a
435436 // Sort.
436- val (withAggsRemoved, aliasedAggregateList) = resolvedOrdering .map {
437+ val (withAggsRemoved, aliasedAggregateList) = newOrdering.filter(_.resolved) .map {
437438 case aggOrdering if aggOrdering.collect { case a : AggregateExpression => a }.nonEmpty =>
438439 val aliased = Alias (aggOrdering.child, " _aggOrdering" )()
439- (aggOrdering.copy(child = aliased.toAttribute), aliased :: Nil )
440+ (aggOrdering.copy(child = aliased.toAttribute), Some ( aliased) )
440441
441- case other => (other, Nil )
442+ case other => (other, None )
442443 }.unzip
443444
444- val missing = unresolved ++ aliasedAggregateList.flatten
445+ val missing = missingAttr ++ aliasedAggregateList.flatten
445446
446447 if (missing.nonEmpty) {
447448 // Add missing grouping exprs and then project them away after the sort.
448449 Project (a.output,
449450 Sort (withAggsRemoved, global,
450451 Aggregate (grouping, aggs ++ missing, child)))
451452 } else {
452- logDebug(s " Failed to find $missing in ${a.output.mkString(" , " )}" )
453453 s // Nothing we can do here. Return original plan.
454454 }
455455 }
456456
457457 /**
458- * Given a child and a grandchild that are present beneath a sort operator, returns
459- * a resolved sort ordering and a list of attributes that are missing from the child
460- * but are present in the grandchild.
458+ * Given a child and a grandchild that are present beneath a sort operator, try to resolve
459+ * the sort ordering and returns it with a list of attributes that are missing from the
460+ * child but are present in the grandchild.
461461 */
462462 def resolveAndFindMissing (
463463 ordering : Seq [SortOrder ],
0 commit comments