### 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/ql/src/test/java/org/elasticsearch/xpack/ql/plan/QueryPlanTests.java
LogicalPlan transformed = project.transformExpressionsOnly(
            NamedExpression.class,
            n -> n.name().equals("one") ? new FieldAttribute(EMPTY, "changed", one.field()) : n
        );
        assertEquals(Project.class, transformed.getClass());
        Project p = (Project) transformed;
        assertEquals(2, p.projections().size());
        assertSame(two, p.projections().get(1));
        NamedExpression o = p.projections().get(0);
        assertEquals("changed", o.name());
    }
    public void testForEachWithExpressionTopLevel() throws Exception {
        Alias one = new Alias(EMPTY, "one", of(42));
        FieldAttribute two = fieldAttribute();
        Project project = new Project(EMPTY, relation(), asList(one, two));
        List<Object> list = new ArrayList<>();
        project.forEachExpression(Literal.class, l -> {
            if (l.fold().equals(42)) {
                list.add(l.fold());
            }
        });
        assertEquals(singletonList(one.child().fold()), list);
    }
    public void testForEachWithExpressionTree() throws Exception {
        Limit limit = new Limit(EMPTY, of(42), relation());
        OrderBy o = new OrderBy(EMPTY, limit, emptyList());
        List<Object> list = new ArrayList<>();
        o.forEachExpressionDown(Literal.class, l -> {
            if (l.fold().equals(42)) {
                list.add(l.fold());