private Pair<List<SortOrder>, Set<Attribute>> resolveAndFindMissing(
                List<SortOrder> ordering,
                LogicalPlan child,
                LogicalPlan grandchild) {
            List<SortOrder> newOrdering = resolveSortOrders(ordering, grandchild);
            // Construct a set that contains all of the attributes that we need to evaluate the
            // ordering.
            Set<Attribute> requiredAttributes = filterToSet(Expression.getReferences(newOrdering), Expression::resolved);
            // Figure out which ones are missing from the projection, so that we can add them and
            // remove them after the sort.
            requiredAttributes.removeAll(child.output());
            // It is important to return the new SortOrders here, instead of waiting for the standard
            // resolving process as adding attributes to the project below can actually introduce
            // ambiguity that was not present before.
            return new Pair<>(newOrdering, requiredAttributes);
        }
Given a child and a grandchild that are present beneath a sort operator, try to resolve
the sort ordering and returns it with a list of attributes that are missing from the
child but are present in the grandchild.
indexr-query-opt/src/main/java/io/indexr/query/Analyzer.java