### Description

As we have more rules doing analysis across plans, a number of methods are useful to add to the `QueryPlan` class itself, mainly around expressions:

```
- expressions() - return the expressions declared by this plan
- references() - return the references from the expressions above
```
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java
@Override
        protected LogicalPlan rule(Enrich re) {
            LogicalPlan child = re.child();
            if (child instanceof OrderBy orderBy) {
                return orderBy.replaceChild(re.replaceChild(orderBy.child()));
            } else if (child instanceof Project) {
                var projectWithChild = pushDownPastProject(re);
                var attrs = asAttributes(re.enrichFields());
                return projectWithChild.withProjections(mergeOutputExpressions(attrs, projectWithChild.projections()));
            }
            return re;
        }
    }
    protected static class PushDownAndCombineOrderBy extends OptimizerRules.OptimizerRule<OrderBy> {
        @Override
        protected LogicalPlan rule(OrderBy orderBy) {
            LogicalPlan child = orderBy.child();
            if (child instanceof OrderBy childOrder) {
                
                return new OrderBy(orderBy.source(), childOrder.child(), CollectionUtils.combine(orderBy.order(), childOrder.order()));
            } else if (child instanceof Project) {
                return pushDownPastProject(orderBy);
            }
            return orderBy;
        }
    }
    /**
     * Remove unused columns created in the plan, in fields inside eval or aggregations inside stats.
     */
    static class PruneColumns extends Rule<LogicalPlan, LogicalPlan> {