Source:
<code>public PlanNode visitFilter(FilterNode filter, Void context) { if (!(filter.getSource() instanceof TableScanNode)) { <START> return new FilterNode(filter.getId(), filter.getSource().accept(this, null), filter.getPredicate()); <END> } TableScanNode tableScan = (TableScanNode) filter.getSource(); if (!isPushdownFilterSupported(session, tableScan.getTable())) { return filter; } RowExpression expression = filter.getPredicate(); HiveMetadata hiveMetadata = getMetadata(tableScan.getTable()); BiMap<VariableReferenceExpression, VariableReferenceExpression> symbolToColumnMapping = tableScan.getAssignments().entrySet().stream() .collect(toImmutableBiMap( Map.Entry::getKey, entry -> new VariableReferenceExpression(getColumnName(session, hiveMetadata, tableScan.getTable().getConnectorHandle(), entry.getValue()), entry.getKey().getType()))); RowExpression replacedExpression = replaceExpression(expression, symbolToColumnMapping); if (FALSE_CONSTANT.equals(replacedExpression)) { return new ValuesNode(idAllocator.getNextId(), tableScan.getOutputVariables(), ImmutableList.of()); } ConnectorPushdownFilterResult pushdownFilterResult = pushdownFilter(session, hiveMetadata, tableScan.getTable().getConnectorHandle(), replacedExpression, tableScan.getTable().getLayout()); ConnectorTableLayout layout = pushdownFilterResult.getLayout(); if (layout.getPredicate().isNone()) { return new ValuesNode(idAllocator.getNextId(), tableScan.getOutputVariables(), ImmutableList.of()); } TableHandle handle = tableScan.getTable(); TableScanNode node = new TableScanNode( tableScan.getId(), new TableHandle(handle.getConnectorId(), handle.getConnectorHandle(), handle.getTransaction(), Optional.of(pushdownFilterResult.getLayout().getHandle())), tableScan.getOutputVariables(), tableScan.getAssignments(), layout.getPredicate(), TupleDomain.all()); RowExpression unenforcedFilter = pushdownFilterResult.getUnenforcedConstraint(); if (!TRUE_CONSTANT.equals(unenforcedFilter)) { return new FilterNode(idAllocator.getNextId(), node, replaceExpression(unenforcedFilter, symbolToColumnMapping.inverse())); } return node; }</code><technical_language>need create new object if source change; perhaps, call visitPlan: return visitPlan(filter, context);</technical_language>

Target:
public PlanNode visitFilter(FilterNode filter, Void context) { if (!(filter.getSource() instanceof TableScanNode)) { return visitPlan(filter, context); } TableScanNode tableScan = (TableScanNode) filter.getSource(); if (!isPushdownFilterSupported(session, tableScan.getTable())) { return filter; } RowExpression expression = filter.getPredicate(); TableHandle handle = tableScan.getTable(); HiveMetadata hiveMetadata = getMetadata(handle); BiMap<VariableReferenceExpression, VariableReferenceExpression> symbolToColumnMapping = tableScan.getAssignments().entrySet().stream() .collect(toImmutableBiMap( Map.Entry::getKey, entry -> new VariableReferenceExpression(getColumnName(session, hiveMetadata, handle.getConnectorHandle(), entry.getValue()), entry.getKey().getType()))); RowExpression replacedExpression = replaceExpression(expression, symbolToColumnMapping); if (FALSE_CONSTANT.equals(replacedExpression)) { return new ValuesNode(idAllocator.getNextId(), tableScan.getOutputVariables(), ImmutableList.of()); } ConnectorPushdownFilterResult pushdownFilterResult = pushdownFilter( session, hiveMetadata, handle.getConnectorHandle(), replacedExpression, handle.getLayout()); ConnectorTableLayout layout = pushdownFilterResult.getLayout(); if (layout.getPredicate().isNone()) { return new ValuesNode(idAllocator.getNextId(), tableScan.getOutputVariables(), ImmutableList.of()); } TableScanNode node = new TableScanNode( tableScan.getId(), new TableHandle(handle.getConnectorId(), handle.getConnectorHandle(), handle.getTransaction(), Optional.of(pushdownFilterResult.getLayout().getHandle())), tableScan.getOutputVariables(), tableScan.getAssignments(), layout.getPredicate(), TupleDomain.all()); RowExpression unenforcedFilter = pushdownFilterResult.getUnenforcedConstraint(); if (!TRUE_CONSTANT.equals(unenforcedFilter)) { return new FilterNode(idAllocator.getNextId(), node, replaceExpression(unenforcedFilter, symbolToColumnMapping.inverse())); } return node; }