presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/GatherAndMergeWindows.java/ManipulateAdjacentWindowsOverProjects/pullWindowNodeAboveProjects
class ManipulateAdjacentWindowsOverProjects:        protected static Optional<WindowNode> pullWindowNodeAboveProjects(
                WindowNode target,
                List<ProjectNode> projects)
        {
            if (projects.isEmpty()) {
                return Optional.of(target);
            }

            PlanNode targetChild = target.getSource();

            Set<Symbol> targetInputs = ImmutableSet.copyOf(targetChild.getOutputSymbols());
            Set<Symbol> targetOutputs = ImmutableSet.copyOf(target.getOutputSymbols());

            PlanNode newTargetChild = targetChild;

            for (ProjectNode project : projects) {
                Set<Symbol> newTargetChildOutputs = ImmutableSet.copyOf(newTargetChild.getOutputSymbols());

                // The only kind of use of the output of the target that we can safely ignore is a simple identity propagation.
                // The target node, when hoisted above the projections, will provide the symbols directly.
                Map<Symbol, Expression> assignmentsWithoutTargetOutputIdentities = Maps.filterKeys(
                        project.getAssignments().getMap(),
                        output -> !(project.getAssignments().isIdentity(output) && targetOutputs.contains(output)));

                if (targetInputs.stream().anyMatch(assignmentsWithoutTargetOutputIdentities::containsKey)) {
                    // Redefinition of an input to the target -- can't handle this case.
                    return Optional.empty();
                }

                Assignments newAssignments = Assignments.builder()
                        .putAll(assignmentsWithoutTargetOutputIdentities)
                        .putIdentities(targetInputs)
                        .build();

                if (!newTargetChildOutputs.containsAll(SymbolsExtractor.extractUnique(newAssignments.getExpressions()))) {
                    // Projection uses an output of the target -- can't move the target above this projection.
                    return Optional.empty();
                }

                newTargetChild = new ProjectNode(project.getId(), newTargetChild, newAssignments);
            }

            WindowNode newTarget = (WindowNode) target.replaceChildren(ImmutableList.of(newTargetChild));
            Set<Symbol> newTargetOutputs = ImmutableSet.copyOf(newTarget.getOutputSymbols());
            if (!newTargetOutputs.containsAll(projects.get(projects.size() - 1).getOutputSymbols())) {
                // The new target node is hiding some of the projections, which makes this rewrite incorrect.
                return Optional.empty();
            }
            return Optional.of(newTarget);
        }