/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.facebook.presto.sql.planner; import com.facebook.presto.sql.planner.plan.PlanNode; import com.facebook.presto.sql.tree.DefaultExpressionTraversalVisitor; import com.facebook.presto.sql.tree.DefaultTraversalVisitor; import com.facebook.presto.sql.tree.DereferenceExpression; import com.facebook.presto.sql.tree.Expression; import com.facebook.presto.sql.tree.Identifier; import com.facebook.presto.sql.tree.QualifiedName; import com.facebook.presto.sql.tree.SymbolReference; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import java.util.List; import java.util.Set; import static com.facebook.presto.sql.planner.ExpressionExtractor.extractExpressions; import static java.util.Objects.requireNonNull; public final class DependencyExtractor { private DependencyExtractor() {} public static Set<Symbol> extractUnique(PlanNode node) { ImmutableSet.Builder<Symbol> uniqueSymbols = ImmutableSet.builder(); extractExpressions(node).forEach(expression -> uniqueSymbols.addAll(extractUnique(expression))); return uniqueSymbols.build(); } public static Set<Symbol> extractUnique(Expression expression) { return ImmutableSet.copyOf(extractAll(expression)); } public static Set<Symbol> extractUnique(Iterable<? extends Expression> expressions) { ImmutableSet.Builder<Symbol> unique = ImmutableSet.builder(); for (Expression expression : expressions) { unique.addAll(extractAll(expression)); } return unique.build(); } public static List<Symbol> extractAll(Expression expression) { ImmutableList.Builder<Symbol> builder = ImmutableList.builder(); new SymbolBuilderVisitor().process(expression, builder); return builder.build(); } // to extract qualified name with prefix public static Set<QualifiedName> extractNames(Expression expression, Set<Expression> columnReferences) { ImmutableSet.Builder<QualifiedName> builder = ImmutableSet.builder(); new QualifiedNameBuilderVisitor(columnReferences).process(expression, builder); return builder.build(); } private static class SymbolBuilderVisitor extends DefaultExpressionTraversalVisitor<Void, ImmutableList.Builder<Symbol>> { @Override protected Void visitSymbolReference(SymbolReference node, ImmutableList.Builder<Symbol> builder) { builder.add(Symbol.from(node)); return null; } } private static class QualifiedNameBuilderVisitor extends DefaultTraversalVisitor<Void, ImmutableSet.Builder<QualifiedName>> { private final Set<Expression> columnReferences; private QualifiedNameBuilderVisitor(Set<Expression> columnReferences) { this.columnReferences = requireNonNull(columnReferences, "columnReferences is null"); } @Override protected Void visitDereferenceExpression(DereferenceExpression node, ImmutableSet.Builder<QualifiedName> builder) { if (columnReferences.contains(node)) { builder.add(DereferenceExpression.getQualifiedName(node)); } else { process(node.getBase(), builder); } return null; } @Override protected Void visitIdentifier(Identifier node, ImmutableSet.Builder<QualifiedName> builder) { builder.add(QualifiedName.of(node.getName())); return null; } } }