static Optional<ProjectNode> inlineProjections(
      PlannerContext plannerContext,
      ProjectNode parent,
      ProjectNode child,
      SessionInfo sessionInfo,
      TypeProvider types) {
    // squash identity projections
    if (parent.isIdentity() && child.isIdentity()) {
      return Optional.of((ProjectNode) parent.replaceChildren(ImmutableList.of(child.getChild())));
    }

    Set<Symbol> targets = extractInliningTargets(plannerContext, parent, child, sessionInfo, types);
    if (targets.isEmpty()) {
      return Optional.empty();
    }

    // inline the expressions; use LinkedHashMap to keep order
    Assignments assignments = child.getAssignments().filter(targets::contains);
    Map<Symbol, Expression> parentAssignments =
        new LinkedHashMap<>(parent.getAssignments().getMap().size());
    for (Map.Entry<Symbol, Expression> entry : parent.getAssignments().getMap().entrySet()) {
      parentAssignments.put(entry.getKey(), inlineReferences(entry.getValue(), assignments));
    }

    // Synthesize identity assignments for the inputs of expressions that were inlined
    // to place in the child projection.
    Set<Symbol> inputs =
        child.getAssignments().entrySet().stream()
            .filter(entry -> targets.contains(entry.getKey()))
            .map(Map.Entry::getValue)
            .flatMap(entry -> SymbolsExtractor.extractAll(entry).stream())
            .collect(toSet());

    Assignments.Builder newChildAssignmentsBuilder = Assignments.builder();
    for (Map.Entry<Symbol, Expression> assignment : child.getAssignments().entrySet()) {
      if (!targets.contains(assignment.getKey())) {
        newChildAssignmentsBuilder.put(assignment);
        // If this is not an identity assignment, remove the symbol from inputs, as we don't want to
        // reset the expression
        if (!isSymbolReference(assignment.getKey(), assignment.getValue())) {
          inputs.remove(assignment.getKey());
        }
      }
    }
    for (Symbol input : inputs) {
      newChildAssignmentsBuilder.putIdentity(input);
    }

    Assignments newChildAssignments = newChildAssignmentsBuilder.build();
    PlanNode newChild;
    if (newChildAssignments.isIdentity()) {
      newChild = child.getChild();
    } else {
      newChild = new ProjectNode(child.getPlanNodeId(), child.getChild(), newChildAssignments);
    }

    return Optional.of(
        new ProjectNode(parent.getPlanNodeId(), newChild, Assignments.copyOf(parentAssignments)));
  }
Inlines expressions from a child project node into a parent project node as long as they are
simple constants, or they are referenced only once (to avoid introducing duplicate computation)
and the references don't appear within a TRY block (to avoid changing semantics).
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/iterative/rule/InlineProjections.java