Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * 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.analyzer;
 
 
 
 import java.util.List;
 
 import static com.facebook.presto.sql.analyzer.SemanticErrorCode.MUST_BE_AGGREGATE_OR_GROUP_BY;
 import static com.facebook.presto.sql.analyzer.SemanticErrorCode.NESTED_AGGREGATION;
 import static com.facebook.presto.sql.analyzer.SemanticErrorCode.NESTED_WINDOW;
 import static com.facebook.presto.sql.analyzer.SemanticErrorCode.NOT_SUPPORTED;
 import static com.facebook.presto.util.ImmutableCollectors.toImmutableList;
 import static com.google.common.base.Predicates.equalTo;
 import static com.google.common.base.Predicates.instanceOf;

Checks whether an expression is constant with respect to the group
 
 public class AggregationAnalyzer
 {
     // fields and expressions in the group by clause
     private final List<IntegerfieldIndexes;
     private final List<Expressionexpressions;
 
     private final Metadata metadata;
 
     private final TupleDescriptor tupleDescriptor;
 
     public AggregationAnalyzer(List<FieldOrExpressiongroupByExpressionsMetadata metadataTupleDescriptor tupleDescriptor)
     {
         Preconditions.checkNotNull(groupByExpressions"groupByExpressions is null");
         Preconditions.checkNotNull(metadata"metadata is null");
         Preconditions.checkNotNull(tupleDescriptor"tupleDescriptor is null");
 
         this. = tupleDescriptor;
         this. = metadata;
 
         this. = groupByExpressions.stream()
                 .filter(FieldOrExpression::isExpression)
                 .map(FieldOrExpression::getExpression)
                 .collect(toImmutableList());
 
         ImmutableList.Builder<IntegerfieldIndexes = ImmutableList.builder();
 
         fieldIndexes.addAll(groupByExpressions.stream()
                 .filter(FieldOrExpression::isFieldReference)
                 .map(FieldOrExpression::getFieldIndex)
                 .iterator());
        // For a query like "SELECT * FROM T GROUP BY a", groupByExpressions will contain "a",
        // and the '*' will be expanded to Field references. Therefore we translate all simple name expressions
        // in the group by clause to fields they reference so that the expansion from '*' can be matched against them
        for (Expression expression : Iterables.filter(instanceOf(QualifiedNameReference.class))) {
            QualifiedName name = ((QualifiedNameReferenceexpression).getName();
            List<Fieldfields = tupleDescriptor.resolveFields(name);
            Preconditions.checkState(fields.size() <= 1, "Found more than one field for name '%s': %s"namefields);
            if (fields.size() == 1) {
                Field field = Iterables.getOnlyElement(fields);
                fieldIndexes.add(tupleDescriptor.indexOf(field));
            }
        }
        this. = fieldIndexes.build();
    }
    public boolean analyze(int fieldIndex)
    {
        return Iterables.any(equalTo(fieldIndex));
    }
    public void analyze(Expression expression)
    {
        Visitor visitor = new Visitor();
        if (!visitor.process(expressionnull)) {
            throw new SemanticException(expression"'%s' must be an aggregate expression or appear in GROUP BY clause"expression);
        }
    }
    private class Visitor
            extends AstVisitor<BooleanVoid>
    {
        @Override
        protected Boolean visitExpression(Expression nodeVoid context)
        {
            throw new UnsupportedOperationException("aggregation analysis not yet implemented for: " + node.getClass().getName());
        }
        @Override
        protected Boolean visitSubqueryExpression(SubqueryExpression nodeVoid context)
        {
            throw new SemanticException(node"Scalar subqueries not yet supported");
        }
        @Override
        protected Boolean visitSubscriptExpression(SubscriptExpression nodeVoid context)
        {
            return process(node.getBase(), context) &&
                    process(node.getIndex(), context);
        }
        @Override
        protected Boolean visitArrayConstructor(ArrayConstructor nodeVoid context)
        {
            return node.getValues().stream().allMatch(expression -> process(expressioncontext));
        }
        @Override
        protected Boolean visitCast(Cast nodeVoid context)
        {
            return process(node.getExpression(), context);
        }
        @Override
        protected Boolean visitCoalesceExpression(CoalesceExpression nodeVoid context)
        {
            return node.getOperands().stream().allMatch(expression -> process(expressioncontext));
        }
        @Override
        protected Boolean visitNullIfExpression(NullIfExpression nodeVoid context)
        {
            return process(node.getFirst(), context) && process(node.getSecond(), context);
        }
        @Override
        protected Boolean visitExtract(Extract nodeVoid context)
        {
            return process(node.getExpression(), context);
        }
        @Override
        protected Boolean visitBetweenPredicate(BetweenPredicate nodeVoid context)
        {
            return process(node.getMin(), context) &&
                    process(node.getValue(), context) &&
                    process(node.getMax(), context);
        }
        @Override
        protected Boolean visitCurrentTime(CurrentTime nodeVoid context)
        {
            return true;
        }
        @Override
        protected Boolean visitArithmeticBinary(ArithmeticBinaryExpression nodeVoid context)
        {
            return process(node.getLeft(), context) && process(node.getRight(), context);
        }
        @Override
        protected Boolean visitComparisonExpression(ComparisonExpression nodeVoid context)
        {
            return process(node.getLeft(), context) && process(node.getRight(), context);
        }
        @Override
        protected Boolean visitLiteral(Literal nodeVoid context)
        {
            return true;
        }
        @Override
        protected Boolean visitIsNotNullPredicate(IsNotNullPredicate nodeVoid context)
        {
            return process(node.getValue(), context);
        }
        @Override
        protected Boolean visitIsNullPredicate(IsNullPredicate nodeVoid context)
        {
            return process(node.getValue(), context);
        }
        @Override
        protected Boolean visitLikePredicate(LikePredicate nodeVoid context)
        {
            return process(node.getValue(), context) && process(node.getPattern(), context);
        }
        @Override
        protected Boolean visitInListExpression(InListExpression nodeVoid context)
        {
            return node.getValues().stream().allMatch(expression -> process(expressioncontext));
        }
        @Override
        protected Boolean visitInPredicate(InPredicate nodeVoid context)
        {
            return process(node.getValue(), context) && process(node.getValueList(), context);
        }
        @Override
        protected Boolean visitFunctionCall(FunctionCall nodeVoid context)
        {
            if (!node.getWindow().isPresent() && .isAggregationFunction(node.getName())) {
                AggregateExtractor aggregateExtractor = new AggregateExtractor();
                WindowFunctionExtractor windowExtractor = new WindowFunctionExtractor();
                for (Expression argument : node.getArguments()) {
                    aggregateExtractor.process(argumentnull);
                    windowExtractor.process(argumentnull);
                }
                if (!aggregateExtractor.getAggregates().isEmpty()) {
                    throw new SemanticException(,
                            node,
                            "Cannot nest aggregations inside aggregation '%s': %s",
                            node.getName(),
                            aggregateExtractor.getAggregates());
                }
                if (!windowExtractor.getWindowFunctions().isEmpty()) {
                    throw new SemanticException(,
                            node,
                            "Cannot nest window functions inside aggregation '%s': %s",
                            node.getName(),
                            windowExtractor.getWindowFunctions());
                }
                return true;
            }
            if (node.getWindow().isPresent() && !process(node.getWindow().get(), context)) {
                return false;
            }
            return node.getArguments().stream().allMatch(expression -> process(expressioncontext));
        }
        @Override
        public Boolean visitWindow(Window nodeVoid context)
        {
            for (Expression expression : node.getPartitionBy()) {
                if (!process(expressioncontext)) {
                    throw new SemanticException(,
                            expression,
                            "PARTITION BY expression '%s' must be an aggregate expression or appear in GROUP BY clause",
                            expression);
                }
            }
            for (SortItem sortItem : node.getOrderBy()) {
                Expression expression = sortItem.getSortKey();
                if (!process(expressioncontext)) {
                    throw new SemanticException(,
                            expression,
                            "ORDER BY expression '%s' must be an aggregate expression or appear in GROUP BY clause",
                            expression);
                }
            }
            if (node.getFrame().isPresent()) {
                process(node.getFrame().get(), context);
            }
            return true;
        }
        @Override
        public Boolean visitWindowFrame(WindowFrame nodeVoid context)
        {
            Optional<Expressionstart = node.getStart().getValue();
            if (start.isPresent()) {
                if (!process(start.get(), context)) {
                    throw new SemanticException(start.get(), "Window frame start must be an aggregate expression or appear in GROUP BY clause");
                }
            }
            if (node.getEnd().isPresent() && node.getEnd().get().getValue().isPresent()) {
                Expression endValue = node.getEnd().get().getValue().get();
                if (!process(endValuecontext)) {
                    throw new SemanticException(endValue"Window frame end must be an aggregate expression or appear in GROUP BY clause");
                }
            }
            return true;
        }
        @Override
        protected Boolean visitQualifiedNameReference(QualifiedNameReference nodeVoid context)
        {
            QualifiedName name = node.getName();
            List<Fieldfields = .resolveFields(name);
            Preconditions.checkState(!fields.isEmpty(), "No fields for name '%s'"name);
            Preconditions.checkState(fields.size() <= 1, "Found more than one field for name '%s': %s"namefields);
            Field field = Iterables.getOnlyElement(fields);
            return .contains(.indexOf(field));
        }
        @Override
        protected Boolean visitArithmeticUnary(ArithmeticUnaryExpression nodeVoid context)
        {
            return process(node.getValue(), context);
        }
        @Override
        protected Boolean visitNotExpression(NotExpression nodeVoid context)
        {
            return process(node.getValue(), context);
        }
        @Override
        protected Boolean visitLogicalBinaryExpression(LogicalBinaryExpression nodeVoid context)
        {
            return process(node.getLeft(), context) && process(node.getRight(), context);
        }
        @Override
        protected Boolean visitIfExpression(IfExpression nodeVoid context)
        {
            ImmutableList.Builder<Expressionexpressions = ImmutableList.<Expression>builder()
                    .add(node.getCondition())
                    .add(node.getTrueValue());
            if (node.getFalseValue().isPresent()) {
                expressions.add(node.getFalseValue().get());
            }
            return expressions.build().stream().allMatch(expression -> process(expressioncontext));
        }
        @Override
        protected Boolean visitSimpleCaseExpression(SimpleCaseExpression nodeVoid context)
        {
            if (!process(node.getOperand(), context)) {
                return false;
            }
            for (WhenClause whenClause : node.getWhenClauses()) {
                if (!process(whenClause.getOperand(), context) || !process(whenClause.getResult(), context)) {
                    return false;
                }
            }
            if (node.getDefaultValue().isPresent() && !process(node.getDefaultValue().get(), context)) {
                return false;
            }
            return true;
        }
        @Override
        protected Boolean visitSearchedCaseExpression(SearchedCaseExpression nodeVoid context)
        {
            for (WhenClause whenClause : node.getWhenClauses()) {
                if (!process(whenClause.getOperand(), context) || !process(whenClause.getResult(), context)) {
                    return false;
                }
            }
            if (node.getDefaultValue().isPresent() && !process(node.getDefaultValue().get(), context)) {
                return false;
            }
            return true;
        }
        @Override
        public Boolean process(Node node, @Nullable Void context)
        {
            if (.stream().anyMatch(node::equals)) {
                return true;
            }
            return super.process(nodecontext);
        }
    }
New to GrepCode? Check out our FAQ X