@Override
  protected Optional<PlanNode> pushDownProjectOff(
      Context context, JoinNode joinNode, Set<Symbol> referencedOutputs) {
    return Optional.of(
        new JoinNode(
            joinNode.getPlanNodeId(),
            joinNode.getJoinType(),
            joinNode.getLeftChild(),
            joinNode.getRightChild(),
            joinNode.getCriteria(),
            joinNode.getAsofCriteria(),
            filteredCopy(joinNode.getLeftOutputSymbols(), referencedOutputs::contains),
            filteredCopy(joinNode.getRightOutputSymbols(), referencedOutputs::contains),
            joinNode.getFilter(),
            joinNode.isSpillable()));
  }
Joins support output symbol selection, so absorb any project-off into the node.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/iterative/rule/PruneJoinColumns.java