Source:
public Void visitJoin(JoinNode node, Set<Symbol> boundSymbols) { node.getLeft().accept(this, boundSymbols); node.getRight().accept(this, boundSymbols); Set<Symbol> leftInputs = createInputs(node.getLeft(), boundSymbols); Set<Symbol> rightInputs = createInputs(node.getRight(), boundSymbols); Set<Symbol> allInputs = ImmutableSet.<Symbol>builder() .addAll(leftInputs) .addAll(rightInputs) .build(); for (JoinNode.EquiJoinClause clause : node.getCriteria()) { checkArgument(leftInputs.contains(clause.getLeft()), "Symbol from join clause (%s) not in left source (%s)", clause.getLeft(), node.getLeft().getOutputSymbols()); checkArgument(rightInputs.contains(clause.getRight()), "Symbol from join clause (%s) not in right source (%s)", clause.getRight(), node.getRight().getOutputSymbols()); } node.getFilter().ifPresent(predicate -> { Set<Symbol> predicateSymbols = SymbolsExtractor.extractUnique(predicate); checkArgument( allInputs.containsAll(predicateSymbols), "Symbol from filter (%s) not in sources (%s)", predicateSymbols, allInputs); }); int leftMaxPosition = Integer.MIN_VALUE; int rightMinPosition = Integer.MAX_VALUE; Set<Symbol> leftSymbols = new HashSet<Symbol>(node.getLeft().getOutputSymbols()); for (int i = 0; i < node.getOutputSymbols().size(); i++) { Symbol symbol = node.getOutputSymbols().get(i); if (leftSymbols.contains(symbol)) { leftMaxPosition = max(i, leftMaxPosition); } else { rightMinPosition = min(i, rightMinPosition); } } checkState(rightMinPosition > leftMaxPosition, "Not all left output symbols are before right output symbols"); if (node.isCrossJoin()) { List<Symbol> allInputsOrdered = ImmutableList.<Symbol>builder() .addAll(node.getLeft().getOutputSymbols()) .addAll(node.getRight().getOutputSymbols()) .build(); checkState(allInputsOrdered.equals(node.getOutputSymbols()), "Outputs symbols (%s) for cross join do not match ordered input symbols (%s)", node.getOutputSymbols(), allInputsOrdered); } return null; }

Target:
public Void visitJoin(JoinNode node, Set<Symbol> boundSymbols) { node.getLeft().accept(this, boundSymbols); node.getRight().accept(this, boundSymbols); Set<Symbol> leftInputs = createInputs(node.getLeft(), boundSymbols); Set<Symbol> rightInputs = createInputs(node.getRight(), boundSymbols); Set<Symbol> allInputs = ImmutableSet.<Symbol>builder() .addAll(leftInputs) .addAll(rightInputs) .build(); for (JoinNode.EquiJoinClause clause : node.getCriteria()) { checkArgument(leftInputs.contains(clause.getLeft()), "Symbol from join clause (%s) not in left source (%s)", clause.getLeft(), node.getLeft().getOutputSymbols()); checkArgument(rightInputs.contains(clause.getRight()), "Symbol from join clause (%s) not in right source (%s)", clause.getRight(), node.getRight().getOutputSymbols()); } node.getFilter().ifPresent(predicate -> { Set<Symbol> predicateSymbols = SymbolsExtractor.extractUnique(predicate); checkArgument( allInputs.containsAll(predicateSymbols), "Symbol from filter (%s) not in sources (%s)", predicateSymbols, allInputs); }); int leftMaxPosition = -1; Optional<Integer> rightMinPosition = Optional.empty(); Set<Symbol> leftSymbols = new HashSet<Symbol>(node.getLeft().getOutputSymbols()); for (int i = 0; i < node.getOutputSymbols().size(); i++) { Symbol symbol = node.getOutputSymbols().get(i); if (leftSymbols.contains(symbol)) { leftMaxPosition = i; } else if (!rightMinPosition.isPresent()) { rightMinPosition = Optional.of(i); } } checkState(!rightMinPosition.isPresent() || rightMinPosition.get() > leftMaxPosition, "Not all left output symbols are before right output symbols"); if (node.isCrossJoin()) { List<Symbol> allInputsOrdered = ImmutableList.<Symbol>builder() .addAll(node.getLeft().getOutputSymbols()) .addAll(node.getRight().getOutputSymbols()) .build(); checkState(allInputsOrdered.equals(node.getOutputSymbols()), "Outputs symbols (%s) for cross join do not match ordered input symbols (%s)", node.getOutputSymbols(), allInputsOrdered); } return null; }