Search in sources :

Example 1 with GroupBy

use of com.facebook.presto.sql.tree.GroupBy in project presto by prestodb.

the class MaterializedViewQueryOptimizer method visitQuerySpecification.

@Override
protected Node visitQuerySpecification(QuerySpecification node, Void context) {
    if (!node.getFrom().isPresent()) {
        throw new IllegalStateException("Query with no From clause is not rewritable by materialized view");
    }
    Relation relation = node.getFrom().get();
    if (relation instanceof AliasedRelation) {
        removablePrefix = Optional.of(((AliasedRelation) relation).getAlias());
        relation = ((AliasedRelation) relation).getRelation();
    }
    if (!(relation instanceof Table)) {
        throw new SemanticException(NOT_SUPPORTED, node, "Relation other than Table is not supported in query optimizer");
    }
    Table baseTable = (Table) relation;
    if (!removablePrefix.isPresent()) {
        removablePrefix = Optional.of(new Identifier(baseTable.getName().toString()));
    }
    if (node.getGroupBy().isPresent()) {
        ImmutableSet.Builder<Expression> expressionsInGroupByBuilder = ImmutableSet.builder();
        for (GroupingElement element : node.getGroupBy().get().getGroupingElements()) {
            element = removeGroupingElementPrefix(element, removablePrefix);
            Optional<Set<Expression>> groupByOfMaterializedView = materializedViewInfo.getGroupBy();
            if (groupByOfMaterializedView.isPresent()) {
                for (Expression expression : element.getExpressions()) {
                    if (!groupByOfMaterializedView.get().contains(expression) || !materializedViewInfo.getBaseToViewColumnMap().containsKey(expression)) {
                        throw new IllegalStateException(format("Grouping element %s is not present in materialized view groupBy field", element));
                    }
                }
            }
            expressionsInGroupByBuilder.addAll(element.getExpressions());
        }
        expressionsInGroupBy = Optional.of(expressionsInGroupByBuilder.build());
    }
    // TODO: Add HAVING validation to the validator https://github.com/prestodb/presto/issues/16406
    if (node.getHaving().isPresent()) {
        throw new SemanticException(NOT_SUPPORTED, node, "Having clause is not supported in query optimizer");
    }
    if (materializedViewInfo.getWhereClause().isPresent()) {
        if (!node.getWhere().isPresent()) {
            throw new IllegalStateException("Query with no where clause is not rewritable by materialized view with where clause");
        }
        QualifiedObjectName baseTableName = createQualifiedObjectName(session, baseTable, baseTable.getName());
        Optional<TableHandle> tableHandle = metadata.getTableHandle(session, baseTableName);
        if (!tableHandle.isPresent()) {
            throw new SemanticException(MISSING_TABLE, node, "Table does not exist");
        }
        ImmutableList.Builder<Field> fields = ImmutableList.builder();
        for (ColumnHandle columnHandle : metadata.getColumnHandles(session, tableHandle.get()).values()) {
            ColumnMetadata columnMetadata = metadata.getColumnMetadata(session, tableHandle.get(), columnHandle);
            fields.add(Field.newUnqualified(materializedViewInfo.getWhereClause().get().getLocation(), columnMetadata.getName(), columnMetadata.getType()));
        }
        Scope scope = Scope.builder().withRelationType(RelationId.anonymous(), new RelationType(fields.build())).build();
        // Given base query's filter condition and materialized view's filter condition, the goal is to check if MV's filters contain Base's filters (Base implies MV).
        // Let base query's filter condition be A, and MV's filter condition be B.
        // One way to evaluate A implies B is to evaluate logical expression A^~B and check if the output domain is none.
        // If the resulting domain is none, then A^~B is false. Thus A implies B.
        // For more information and examples: https://fb.quip.com/WwmxA40jLMxR
        // TODO: Implement method that utilizes external SAT solver libraries. https://github.com/prestodb/presto/issues/16536
        RowExpression materializedViewWhereCondition = convertToRowExpression(materializedViewInfo.getWhereClause().get(), scope);
        RowExpression baseQueryWhereCondition = convertToRowExpression(node.getWhere().get(), scope);
        RowExpression rewriteLogicExpression = and(baseQueryWhereCondition, call(baseQueryWhereCondition.getSourceLocation(), "not", new FunctionResolution(metadata.getFunctionAndTypeManager()).notFunction(), materializedViewWhereCondition.getType(), materializedViewWhereCondition));
        RowExpression disjunctiveNormalForm = logicalRowExpressions.convertToDisjunctiveNormalForm(rewriteLogicExpression);
        ExtractionResult<VariableReferenceExpression> result = domainTranslator.fromPredicate(session.toConnectorSession(), disjunctiveNormalForm, BASIC_COLUMN_EXTRACTOR);
        if (!result.getTupleDomain().equals(TupleDomain.none())) {
            throw new IllegalStateException("View filter condition does not contain base query's filter condition");
        }
    }
    return new QuerySpecification((Select) process(node.getSelect(), context), node.getFrom().map(from -> (Relation) process(from, context)), node.getWhere().map(where -> (Expression) process(where, context)), node.getGroupBy().map(groupBy -> (GroupBy) process(groupBy, context)), node.getHaving().map(having -> (Expression) process(having, context)), node.getOrderBy().map(orderBy -> (OrderBy) process(orderBy, context)), node.getOffset(), node.getLimit());
}
Also used : FunctionAndTypeManager(com.facebook.presto.metadata.FunctionAndTypeManager) WarningCollector(com.facebook.presto.spi.WarningCollector) RowExpressionDomainTranslator(com.facebook.presto.sql.relational.RowExpressionDomainTranslator) AliasedRelation(com.facebook.presto.sql.tree.AliasedRelation) SqlToRowExpressionTranslator(com.facebook.presto.sql.relational.SqlToRowExpressionTranslator) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) ExpressionUtils.removeExpressionPrefix(com.facebook.presto.sql.ExpressionUtils.removeExpressionPrefix) SelectItem(com.facebook.presto.sql.tree.SelectItem) QualifiedObjectName(com.facebook.presto.common.QualifiedObjectName) ExpressionUtils.removeGroupingElementPrefix(com.facebook.presto.sql.ExpressionUtils.removeGroupingElementPrefix) FunctionCall(com.facebook.presto.sql.tree.FunctionCall) ImmutableSet(com.google.common.collect.ImmutableSet) Query(com.facebook.presto.sql.tree.Query) QueryBody(com.facebook.presto.sql.tree.QueryBody) QuerySpecification(com.facebook.presto.sql.tree.QuerySpecification) ImmutableMap(com.google.common.collect.ImmutableMap) Node(com.facebook.presto.sql.tree.Node) Set(java.util.Set) NOT_SUPPORTED(com.facebook.presto.sql.analyzer.SemanticErrorCode.NOT_SUPPORTED) GroupingElement(com.facebook.presto.sql.tree.GroupingElement) SortItem(com.facebook.presto.sql.tree.SortItem) String.format(java.lang.String.format) SqlParser(com.facebook.presto.sql.parser.SqlParser) LogicalBinaryExpression(com.facebook.presto.sql.tree.LogicalBinaryExpression) ColumnMetadata(com.facebook.presto.spi.ColumnMetadata) Optional(java.util.Optional) ExpressionUtils.removeSortItemPrefix(com.facebook.presto.sql.ExpressionUtils.removeSortItemPrefix) Select(com.facebook.presto.sql.tree.Select) ExtractionResult(com.facebook.presto.spi.relation.DomainTranslator.ExtractionResult) QualifiedName(com.facebook.presto.sql.tree.QualifiedName) ExpressionUtils.removeSingleColumnPrefix(com.facebook.presto.sql.ExpressionUtils.removeSingleColumnPrefix) Logger(com.facebook.airlift.log.Logger) Table(com.facebook.presto.sql.tree.Table) RowExpressionDeterminismEvaluator(com.facebook.presto.sql.relational.RowExpressionDeterminismEvaluator) Expressions.call(com.facebook.presto.sql.relational.Expressions.call) SingleColumn(com.facebook.presto.sql.tree.SingleColumn) Identifier(com.facebook.presto.sql.tree.Identifier) ImmutableList(com.google.common.collect.ImmutableList) LogicalRowExpressions(com.facebook.presto.expressions.LogicalRowExpressions) BASIC_COLUMN_EXTRACTOR(com.facebook.presto.spi.relation.DomainTranslator.BASIC_COLUMN_EXTRACTOR) Objects.requireNonNull(java.util.Objects.requireNonNull) TableHandle(com.facebook.presto.spi.TableHandle) FunctionResolution(com.facebook.presto.sql.relational.FunctionResolution) AllColumns(com.facebook.presto.sql.tree.AllColumns) SimpleGroupBy(com.facebook.presto.sql.tree.SimpleGroupBy) MaterializedViewInfo(com.facebook.presto.sql.analyzer.MaterializedViewInformationExtractor.MaterializedViewInfo) RowExpression(com.facebook.presto.spi.relation.RowExpression) GroupBy(com.facebook.presto.sql.tree.GroupBy) OrderBy(com.facebook.presto.sql.tree.OrderBy) Relation(com.facebook.presto.sql.tree.Relation) MISSING_TABLE(com.facebook.presto.sql.analyzer.SemanticErrorCode.MISSING_TABLE) Session(com.facebook.presto.Session) LogicalRowExpressions.and(com.facebook.presto.expressions.LogicalRowExpressions.and) AstVisitor(com.facebook.presto.sql.tree.AstVisitor) ComparisonExpression(com.facebook.presto.sql.tree.ComparisonExpression) TupleDomain(com.facebook.presto.common.predicate.TupleDomain) Expression(com.facebook.presto.sql.tree.Expression) ColumnHandle(com.facebook.presto.spi.ColumnHandle) MetadataUtil.createQualifiedObjectName(com.facebook.presto.metadata.MetadataUtil.createQualifiedObjectName) ArithmeticBinaryExpression(com.facebook.presto.sql.tree.ArithmeticBinaryExpression) Metadata(com.facebook.presto.metadata.Metadata) AccessControl(com.facebook.presto.security.AccessControl) ColumnMetadata(com.facebook.presto.spi.ColumnMetadata) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) ImmutableList(com.google.common.collect.ImmutableList) FunctionResolution(com.facebook.presto.sql.relational.FunctionResolution) QuerySpecification(com.facebook.presto.sql.tree.QuerySpecification) AliasedRelation(com.facebook.presto.sql.tree.AliasedRelation) Relation(com.facebook.presto.sql.tree.Relation) Identifier(com.facebook.presto.sql.tree.Identifier) ImmutableSet(com.google.common.collect.ImmutableSet) OrderBy(com.facebook.presto.sql.tree.OrderBy) ColumnHandle(com.facebook.presto.spi.ColumnHandle) Table(com.facebook.presto.sql.tree.Table) SimpleGroupBy(com.facebook.presto.sql.tree.SimpleGroupBy) GroupBy(com.facebook.presto.sql.tree.GroupBy) RowExpression(com.facebook.presto.spi.relation.RowExpression) QualifiedObjectName(com.facebook.presto.common.QualifiedObjectName) MetadataUtil.createQualifiedObjectName(com.facebook.presto.metadata.MetadataUtil.createQualifiedObjectName) GroupingElement(com.facebook.presto.sql.tree.GroupingElement) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) LogicalBinaryExpression(com.facebook.presto.sql.tree.LogicalBinaryExpression) RowExpression(com.facebook.presto.spi.relation.RowExpression) ComparisonExpression(com.facebook.presto.sql.tree.ComparisonExpression) Expression(com.facebook.presto.sql.tree.Expression) ArithmeticBinaryExpression(com.facebook.presto.sql.tree.ArithmeticBinaryExpression) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) TableHandle(com.facebook.presto.spi.TableHandle) AliasedRelation(com.facebook.presto.sql.tree.AliasedRelation)

Example 2 with GroupBy

use of com.facebook.presto.sql.tree.GroupBy in project presto by prestodb.

the class TestSqlParser method testSelectWithGroupBy.

@Test
public void testSelectWithGroupBy() {
    assertStatement("SELECT * FROM table1 GROUP BY a", new Query(Optional.empty(), new QuerySpecification(selectList(new AllColumns()), Optional.of(new Table(QualifiedName.of("table1"))), Optional.empty(), Optional.of(new GroupBy(false, ImmutableList.of(new SimpleGroupBy(ImmutableList.of(new Identifier("a")))))), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()), Optional.empty(), Optional.empty(), Optional.empty()));
    assertStatement("SELECT * FROM table1 GROUP BY a, b", new Query(Optional.empty(), new QuerySpecification(selectList(new AllColumns()), Optional.of(new Table(QualifiedName.of("table1"))), Optional.empty(), Optional.of(new GroupBy(false, ImmutableList.of(new SimpleGroupBy(ImmutableList.of(new Identifier("a"))), new SimpleGroupBy(ImmutableList.of(new Identifier("b")))))), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()), Optional.empty(), Optional.empty(), Optional.empty()));
    assertStatement("SELECT * FROM table1 GROUP BY ()", new Query(Optional.empty(), new QuerySpecification(selectList(new AllColumns()), Optional.of(new Table(QualifiedName.of("table1"))), Optional.empty(), Optional.of(new GroupBy(false, ImmutableList.of(new SimpleGroupBy(ImmutableList.of())))), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()), Optional.empty(), Optional.empty(), Optional.empty()));
    assertStatement("SELECT * FROM table1 GROUP BY GROUPING SETS (a)", new Query(Optional.empty(), new QuerySpecification(selectList(new AllColumns()), Optional.of(new Table(QualifiedName.of("table1"))), Optional.empty(), Optional.of(new GroupBy(false, ImmutableList.of(new GroupingSets(ImmutableList.of(ImmutableList.of(new Identifier("a"))))))), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()), Optional.empty(), Optional.empty(), Optional.empty()));
    assertStatement("SELECT a, b, GROUPING(a, b) FROM table1 GROUP BY GROUPING SETS ((a), (b))", new Query(Optional.empty(), new QuerySpecification(selectList(DereferenceExpression.from(QualifiedName.of("a")), DereferenceExpression.from(QualifiedName.of("b")), new GroupingOperation(Optional.empty(), ImmutableList.of(QualifiedName.of("a"), QualifiedName.of("b")))), Optional.of(new Table(QualifiedName.of("table1"))), Optional.empty(), Optional.of(new GroupBy(false, ImmutableList.of(new GroupingSets(ImmutableList.of(ImmutableList.of(new Identifier("a")), ImmutableList.of(new Identifier("b"))))))), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()), Optional.empty(), Optional.empty(), Optional.empty()));
    assertStatement("SELECT * FROM table1 GROUP BY ALL GROUPING SETS ((a, b), (a), ()), CUBE (c), ROLLUP (d)", new Query(Optional.empty(), new QuerySpecification(selectList(new AllColumns()), Optional.of(new Table(QualifiedName.of("table1"))), Optional.empty(), Optional.of(new GroupBy(false, ImmutableList.of(new GroupingSets(ImmutableList.of(ImmutableList.of(new Identifier("a"), new Identifier("b")), ImmutableList.of(new Identifier("a")), ImmutableList.of())), new Cube(ImmutableList.of(new Identifier("c"))), new Rollup(ImmutableList.of(new Identifier("d")))))), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()), Optional.empty(), Optional.empty(), Optional.empty()));
    assertStatement("SELECT * FROM table1 GROUP BY DISTINCT GROUPING SETS ((a, b), (a), ()), CUBE (c), ROLLUP (d)", new Query(Optional.empty(), new QuerySpecification(selectList(new AllColumns()), Optional.of(new Table(QualifiedName.of("table1"))), Optional.empty(), Optional.of(new GroupBy(true, ImmutableList.of(new GroupingSets(ImmutableList.of(ImmutableList.of(new Identifier("a"), new Identifier("b")), ImmutableList.of(new Identifier("a")), ImmutableList.of())), new Cube(ImmutableList.of(new Identifier("c"))), new Rollup(ImmutableList.of(new Identifier("d")))))), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()), Optional.empty(), Optional.empty(), Optional.empty()));
}
Also used : GroupingSets(com.facebook.presto.sql.tree.GroupingSets) QuerySpecification(com.facebook.presto.sql.tree.QuerySpecification) SimpleGroupBy(com.facebook.presto.sql.tree.SimpleGroupBy) CreateTable(com.facebook.presto.sql.tree.CreateTable) DropTable(com.facebook.presto.sql.tree.DropTable) Table(com.facebook.presto.sql.tree.Table) RenameTable(com.facebook.presto.sql.tree.RenameTable) SimpleGroupBy(com.facebook.presto.sql.tree.SimpleGroupBy) GroupBy(com.facebook.presto.sql.tree.GroupBy) Identifier(com.facebook.presto.sql.tree.Identifier) QueryUtil.quotedIdentifier(com.facebook.presto.sql.QueryUtil.quotedIdentifier) Query(com.facebook.presto.sql.tree.Query) QueryUtil.simpleQuery(com.facebook.presto.sql.QueryUtil.simpleQuery) WithQuery(com.facebook.presto.sql.tree.WithQuery) Rollup(com.facebook.presto.sql.tree.Rollup) Cube(com.facebook.presto.sql.tree.Cube) AllColumns(com.facebook.presto.sql.tree.AllColumns) GroupingOperation(com.facebook.presto.sql.tree.GroupingOperation) Test(org.testng.annotations.Test)

Aggregations

AllColumns (com.facebook.presto.sql.tree.AllColumns)2 GroupBy (com.facebook.presto.sql.tree.GroupBy)2 Identifier (com.facebook.presto.sql.tree.Identifier)2 Query (com.facebook.presto.sql.tree.Query)2 QuerySpecification (com.facebook.presto.sql.tree.QuerySpecification)2 SimpleGroupBy (com.facebook.presto.sql.tree.SimpleGroupBy)2 Table (com.facebook.presto.sql.tree.Table)2 Logger (com.facebook.airlift.log.Logger)1 Session (com.facebook.presto.Session)1 QualifiedObjectName (com.facebook.presto.common.QualifiedObjectName)1 TupleDomain (com.facebook.presto.common.predicate.TupleDomain)1 LogicalRowExpressions (com.facebook.presto.expressions.LogicalRowExpressions)1 LogicalRowExpressions.and (com.facebook.presto.expressions.LogicalRowExpressions.and)1 FunctionAndTypeManager (com.facebook.presto.metadata.FunctionAndTypeManager)1 Metadata (com.facebook.presto.metadata.Metadata)1 MetadataUtil.createQualifiedObjectName (com.facebook.presto.metadata.MetadataUtil.createQualifiedObjectName)1 AccessControl (com.facebook.presto.security.AccessControl)1 ColumnHandle (com.facebook.presto.spi.ColumnHandle)1 ColumnMetadata (com.facebook.presto.spi.ColumnMetadata)1 TableHandle (com.facebook.presto.spi.TableHandle)1