@Override
    public PlanNode visitIndexSource(IndexSourceNode node, RewriteContext<Set<Symbol>> context) {
      List<Symbol> newOutputSymbols =
          node.getOutputSymbols()
              .stream()
              .filter(context.get()::contains)
              .collect(toImmutableList());

      Set<Symbol> newLookupSymbols =
          node.getLookupSymbols()
              .stream()
              .filter(context.get()::contains)
              .collect(toImmutableSet());

      Set<Symbol> requiredAssignmentSymbols = context.get();
      if (!node.getEffectiveTupleDomain().isNone()) {
        Set<Symbol> requiredSymbols =
            Maps.filterValues(
                    node.getAssignments(),
                    in(node.getEffectiveTupleDomain().getDomains().get().keySet()))
                .keySet();
        requiredAssignmentSymbols = Sets.union(context.get(), requiredSymbols);
      }
      Map<Symbol, ColumnHandle> newAssignments =
          Maps.filterKeys(node.getAssignments(), in(requiredAssignmentSymbols));

      return new IndexSourceNode(
          node.getId(),
          node.getIndexHandle(),
          node.getTableHandle(),
          newLookupSymbols,
          newOutputSymbols,
          newAssignments,
          node.getEffectiveTupleDomain());
    }
 @Override
 public Map<Symbol, Symbol> visitIndexSource(IndexSourceNode node, Set<Symbol> lookupSymbols) {
   checkState(
       node.getLookupSymbols().equals(lookupSymbols),
       "lookupSymbols must be the same as IndexSource lookup symbols");
   return lookupSymbols.stream().collect(toImmutableMap(identity(), identity()));
 }
 @Override
 public Void visitIndexSource(IndexSourceNode node, Void context) {
   printNode(
       node,
       format("IndexSource[%s]", node.getIndexHandle()),
       NODE_COLORS.get(NodeType.INDEX_SOURCE));
   return null;
 }