Source:
public PlanNode visitTableScan(TableScanNode node, RewriteContext<Void> context) { if (subfieldPaths.isEmpty()) { return node; } Assignments.Builder projections = Assignments.builder(); ImmutableMap.Builder<Symbol, ColumnHandle> newAssignments = ImmutableMap.builder(); ImmutableMap.Builder<Symbol, Symbol> symbolMapBuilder = ImmutableMap.builder(); for (Map.Entry<Symbol, ColumnHandle> entry : node.getAssignments().entrySet()) { if (fullColumnUses.contains(entry.getKey())) { newAssignments.put(entry); projections.putIdentity(entry.getKey()); continue; } List<SubfieldPath> subfields = new ArrayList(); for (SubfieldPath path : subfieldPaths) { if (path.getColumnName().equals(entry.getKey().getName())) { subfields.add(path); } } if (subfields.isEmpty()) { newAssignments.put(entry); projections.putIdentity(entry.getKey()); continue; } List<SubfieldPath> leafPaths = new ArrayList(); for (SubfieldPath path : subfields) { if (!prefixExists(path, subfields)) { leafPaths.add(path); } } Symbol newSymbol = symbolAllocator.newSymbol(entry.getKey()); projections.put(entry.getKey(), new FunctionCall( FILTER_BY_SUBSCRIPT_PATHS, ImmutableList.of( newSymbol.toSymbolReference(), new ArrayConstructor(leafPaths.stream() .map(p -> new StringLiteral(p.getPath())) .collect(toImmutableList()))))); newAssignments.put(newSymbol, entry.getValue()); symbolMapBuilder.put(entry.getKey(), newSymbol); } Map<Symbol, Symbol> symbolMap = symbolMapBuilder.build(); if (symbolMap.isEmpty()) { return node; } ProjectNode projectNode = new ProjectNode( idAllocator.getNextId(), new TableScanNode( node.getId(), node.getTable(), node.getOutputSymbols().stream() .map(s -> symbolMap.getOrDefault(s, s)) .collect(toImmutableList()), newAssignments.build(), node.getLayout(), node.getCurrentConstraint(), node.getEnforcedConstraint()), projections.build()); return projectNode; }

Target:
public PlanNode visitTableScan(TableScanNode node, RewriteContext<Void> context) { if (subfieldPaths.isEmpty()) { return node; } Assignments.Builder projections = Assignments.builder(); ImmutableMap.Builder<Symbol, ColumnHandle> newAssignments = ImmutableMap.builder(); ImmutableMap.Builder<Symbol, Symbol> symbolMapBuilder = ImmutableMap.builder(); for (Map.Entry<Symbol, ColumnHandle> entry : node.getAssignments().entrySet()) { if (fullColumnUses.contains(entry.getKey())) { newAssignments.put(entry); projections.putIdentity(entry.getKey()); continue; } List<SubfieldPath> subfields = new ArrayList(); for (SubfieldPath path : subfieldPaths) { if (path.getColumnName().equals(entry.getKey().getName())) { subfields.add(path); } } if (subfields.isEmpty()) { newAssignments.put(entry); projections.putIdentity(entry.getKey()); continue; } List<SubfieldPath> leafPaths = new ArrayList(); for (SubfieldPath path : subfields) { if (!prefixExists(path, subfields)) { leafPaths.add(path); } } Symbol newSymbol = symbolAllocator.newSymbol(entry.getKey()); projections.put(entry.getKey(), new FunctionCall( FILTER_BY_SUBSCRIPT_PATHS, ImmutableList.of( newSymbol.toSymbolReference(), new ArrayConstructor(leafPaths.stream() .map(p -> new StringLiteral(p.getPath())) .collect(toImmutableList()))))); newAssignments.put(newSymbol, entry.getValue()); symbolMapBuilder.put(entry.getKey(), newSymbol); } Map<Symbol, Symbol> symbolMap = symbolMapBuilder.build(); if (symbolMap.isEmpty()) { return node; } TableScanNode tableScanNode = new TableScanNode( node.getId(), node.getTable(), node.getOutputSymbols().stream() .map(s -> symbolMap.getOrDefault(s, s)) .collect(toImmutableList()), newAssignments.build(), node.getLayout(), node.getCurrentConstraint(), node.getEnforcedConstraint()); return new ProjectNode(idAllocator.getNextId(), tableScanNode, projections.build()); }