diff --git a/presto-hive/src/test/java/com/facebook/presto/hive/TestHiveIntegrationSmokeTest.java b/presto-hive/src/test/java/com/facebook/presto/hive/TestHiveIntegrationSmokeTest.java index 51a0c7807eb22..0018dcf180516 100644 --- a/presto-hive/src/test/java/com/facebook/presto/hive/TestHiveIntegrationSmokeTest.java +++ b/presto-hive/src/test/java/com/facebook/presto/hive/TestHiveIntegrationSmokeTest.java @@ -6061,7 +6061,7 @@ public void testRefreshMaterializedView() assertQueryFails("REFRESH MATERIALIZED VIEW test_customer_view_5 WHERE nationname = 'UNITED STATES'", ".*Refresh materialized view by column nationname is not supported.*"); assertQueryFails("REFRESH MATERIALIZED VIEW test_customer_view_5 WHERE regionkey = 1 OR nationkey = 24", ".*Only logical AND is supported in WHERE clause.*"); assertQueryFails("REFRESH MATERIALIZED VIEW test_customer_view_5 WHERE regionkey + nationkey = 25", ".*Only columns specified on literals are supported in WHERE clause.*"); - assertQueryFails("REFRESH MATERIALIZED VIEW test_customer_view_5", ".*mismatched input ''\\. Expecting: '\\.', 'WHERE'.*"); + assertQueryFails("REFRESH MATERIALIZED VIEW test_customer_view_5", ".*Refresh Materialized View without predicates is not supported."); } @Test diff --git a/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java b/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java index 2e7c907f34118..eb2dc037dcf46 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java +++ b/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java @@ -864,7 +864,10 @@ protected Scope visitRefreshMaterializedView(RefreshMaterializedView node, Optio // Use AllowAllAccessControl; otherwise Analyzer will check SELECT permission on the materialized view, which is not necessary. StatementAnalyzer viewAnalyzer = new StatementAnalyzer(analysis, metadata, sqlParser, new AllowAllAccessControl(), session, warningCollector); Scope viewScope = viewAnalyzer.analyze(node.getTarget(), scope); - Map tablePredicates = extractTablePredicates(viewName, node.getWhere(), viewScope, metadata, session); + if (!node.getWhere().isPresent()) { + throw new SemanticException(NOT_SUPPORTED, node, "Refresh Materialized View without predicates is not supported."); + } + Map tablePredicates = extractTablePredicates(viewName, node.getWhere().get(), viewScope, metadata, session); Query viewQuery = parseView(view.getOriginalSql(), viewName, node); Query refreshQuery = tablePredicates.containsKey(toSchemaTableName(viewName)) ? @@ -907,7 +910,10 @@ private Optional analyzeBaseTableForRefreshMaterializedView(Table // Use AllowAllAccessControl; otherwise Analyzer will check SELECT permission on the materialized view, which is not necessary. StatementAnalyzer viewAnalyzer = new StatementAnalyzer(analysis, metadata, sqlParser, new AllowAllAccessControl(), session, warningCollector); Scope viewScope = viewAnalyzer.analyze(refreshMaterializedView.getTarget(), scope); - Map tablePredicates = extractTablePredicates(viewName, refreshMaterializedView.getWhere(), viewScope, metadata, session); + if (!refreshMaterializedView.getWhere().isPresent()) { + throw new SemanticException(NOT_SUPPORTED, "Refresh Materialized View without predicates is not supported."); + } + Map tablePredicates = extractTablePredicates(viewName, refreshMaterializedView.getWhere().get(), viewScope, metadata, session); SchemaTableName baseTableName = toSchemaTableName(createQualifiedObjectName(session, baseTable, baseTable.getName(), metadata)); if (tablePredicates.containsKey(baseTableName)) { diff --git a/presto-main-base/src/main/java/com/facebook/presto/sql/rewrite/DefaultTreeRewriter.java b/presto-main-base/src/main/java/com/facebook/presto/sql/rewrite/DefaultTreeRewriter.java index 2b3009a64dde9..6cfd9ccb60f53 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/sql/rewrite/DefaultTreeRewriter.java +++ b/presto-main-base/src/main/java/com/facebook/presto/sql/rewrite/DefaultTreeRewriter.java @@ -480,12 +480,12 @@ select && sameElement(node.getFrom(), from) && sameElement(node.getWhere(), wher protected Node visitRefreshMaterializedView(RefreshMaterializedView node, C context) { Node table = process(node.getTarget(), context); - Node where = process(node.getWhere(), context); - if (node.getTarget() == table && node.getWhere() == where) { + Optional where = process(node.getWhere(), context); + if (node.getTarget() == table && sameElement(node.getWhere(), where)) { return node; } - return new RefreshMaterializedView((Table) table, (Expression) where); + return new RefreshMaterializedView((Table) table, where); } @Override diff --git a/presto-parser/src/main/antlr4/com/facebook/presto/sql/parser/SqlBase.g4 b/presto-parser/src/main/antlr4/com/facebook/presto/sql/parser/SqlBase.g4 index 6989c565d242f..10b5f2b9d9360 100644 --- a/presto-parser/src/main/antlr4/com/facebook/presto/sql/parser/SqlBase.g4 +++ b/presto-parser/src/main/antlr4/com/facebook/presto/sql/parser/SqlBase.g4 @@ -81,7 +81,8 @@ statement (COMMENT string)? (WITH properties)? AS (query | '('query')') #createMaterializedView | DROP MATERIALIZED VIEW (IF EXISTS)? qualifiedName #dropMaterializedView - | REFRESH MATERIALIZED VIEW qualifiedName WHERE booleanExpression #refreshMaterializedView + | REFRESH MATERIALIZED VIEW qualifiedName + (WHERE where=booleanExpression)? #refreshMaterializedView | CREATE (OR REPLACE)? TEMPORARY? FUNCTION functionName=qualifiedName '(' (sqlParameterDeclaration (',' sqlParameterDeclaration)*)? ')' RETURNS returnType=type diff --git a/presto-parser/src/main/java/com/facebook/presto/sql/SqlFormatter.java b/presto-parser/src/main/java/com/facebook/presto/sql/SqlFormatter.java index ec0e4cc94a19e..6817db94aacc1 100644 --- a/presto-parser/src/main/java/com/facebook/presto/sql/SqlFormatter.java +++ b/presto-parser/src/main/java/com/facebook/presto/sql/SqlFormatter.java @@ -914,9 +914,12 @@ protected Void visitDropMaterializedView(DropMaterializedView node, Integer cont protected Void visitRefreshMaterializedView(RefreshMaterializedView node, Integer context) { builder.append("REFRESH MATERIALIZED VIEW ") - .append(formatName(node.getTarget().getName())) - .append(" WHERE ") - .append(formatExpression(node.getWhere(), parameters)); + .append(formatName(node.getTarget().getName())); + + if (node.getWhere().isPresent()) { + builder.append(" WHERE ") + .append(formatExpression(node.getWhere().get(), parameters)); + } return null; } diff --git a/presto-parser/src/main/java/com/facebook/presto/sql/parser/AstBuilder.java b/presto-parser/src/main/java/com/facebook/presto/sql/parser/AstBuilder.java index 8b85c6b822cd0..ca44373fddb82 100644 --- a/presto-parser/src/main/java/com/facebook/presto/sql/parser/AstBuilder.java +++ b/presto-parser/src/main/java/com/facebook/presto/sql/parser/AstBuilder.java @@ -425,7 +425,7 @@ public Node visitRefreshMaterializedView(SqlBaseParser.RefreshMaterializedViewCo return new RefreshMaterializedView( getLocation(context), new Table(getLocation(context), getQualifiedName(context.qualifiedName())), - (Expression) visit(context.booleanExpression())); + visitIfPresent(context.booleanExpression(), Expression.class)); } @Override diff --git a/presto-parser/src/main/java/com/facebook/presto/sql/tree/DefaultTraversalVisitor.java b/presto-parser/src/main/java/com/facebook/presto/sql/tree/DefaultTraversalVisitor.java index 9a545cf0df160..f5cb09c635f4d 100644 --- a/presto-parser/src/main/java/com/facebook/presto/sql/tree/DefaultTraversalVisitor.java +++ b/presto-parser/src/main/java/com/facebook/presto/sql/tree/DefaultTraversalVisitor.java @@ -560,7 +560,7 @@ protected R visitCreateMaterializedView(CreateMaterializedView node, C context) protected R visitRefreshMaterializedView(RefreshMaterializedView node, C context) { process(node.getTarget(), context); - process(node.getWhere(), context); + node.getWhere().ifPresent(where -> process(where, context)); return null; } diff --git a/presto-parser/src/main/java/com/facebook/presto/sql/tree/RefreshMaterializedView.java b/presto-parser/src/main/java/com/facebook/presto/sql/tree/RefreshMaterializedView.java index fbc4988ea7024..38c10ddb6766a 100644 --- a/presto-parser/src/main/java/com/facebook/presto/sql/tree/RefreshMaterializedView.java +++ b/presto-parser/src/main/java/com/facebook/presto/sql/tree/RefreshMaterializedView.java @@ -26,19 +26,19 @@ public class RefreshMaterializedView extends Statement { private final Table target; - private final Expression where; + private final Optional where; - public RefreshMaterializedView(Table target, Expression where) + public RefreshMaterializedView(Table target, Optional where) { this(Optional.empty(), target, where); } - public RefreshMaterializedView(NodeLocation location, Table target, Expression where) + public RefreshMaterializedView(NodeLocation location, Table target, Optional where) { this(Optional.of(location), target, where); } - private RefreshMaterializedView(Optional location, Table target, Expression where) + private RefreshMaterializedView(Optional location, Table target, Optional where) { super(location); this.target = requireNonNull(target, "target is null"); @@ -50,7 +50,7 @@ public Table getTarget() return target; } - public Expression getWhere() + public Optional getWhere() { return where; } @@ -64,7 +64,10 @@ public R accept(AstVisitor visitor, C context) @Override public List getChildren() { - return ImmutableList.of(where); + ImmutableList.Builder nodes = ImmutableList.builder(); + nodes.add(target); + where.ifPresent(nodes::add); + return nodes.build(); } @Override diff --git a/presto-parser/src/test/java/com/facebook/presto/sql/parser/TestSqlParser.java b/presto-parser/src/test/java/com/facebook/presto/sql/parser/TestSqlParser.java index 5b5632c3e16cb..b8b4489648654 100644 --- a/presto-parser/src/test/java/com/facebook/presto/sql/parser/TestSqlParser.java +++ b/presto-parser/src/test/java/com/facebook/presto/sql/parser/TestSqlParser.java @@ -1569,13 +1569,21 @@ public void testRefreshMaterializedView() assertStatement( "REFRESH MATERIALIZED VIEW a WHERE p = 'x'", new RefreshMaterializedView( - table(QualifiedName.of("a")), - new ComparisonExpression(ComparisonExpression.Operator.EQUAL, new Identifier("p"), new StringLiteral("x")))); + table(QualifiedName.of("a")), Optional.of( + new ComparisonExpression(ComparisonExpression.Operator.EQUAL, + new Identifier("p"), + new StringLiteral("x"))))); assertStatement( "REFRESH MATERIALIZED VIEW a.b WHERE p = 'x'", new RefreshMaterializedView( - table(QualifiedName.of("a", "b")), - new ComparisonExpression(ComparisonExpression.Operator.EQUAL, new Identifier("p"), new StringLiteral("x")))); + table(QualifiedName.of("a", "b")), Optional.of( + new ComparisonExpression(ComparisonExpression.Operator.EQUAL, + new Identifier("p"), + new StringLiteral("x"))))); + + assertStatement( + "REFRESH MATERIALIZED VIEW mv", + new RefreshMaterializedView(table(QualifiedName.of("mv")), Optional.empty())); } @Test diff --git a/presto-verifier/src/main/java/com/facebook/presto/verifier/rewrite/DefaultTreeRewriter.java b/presto-verifier/src/main/java/com/facebook/presto/verifier/rewrite/DefaultTreeRewriter.java index 630d5099b71e8..4730020f02114 100644 --- a/presto-verifier/src/main/java/com/facebook/presto/verifier/rewrite/DefaultTreeRewriter.java +++ b/presto-verifier/src/main/java/com/facebook/presto/verifier/rewrite/DefaultTreeRewriter.java @@ -465,12 +465,12 @@ select && sameElement(node.getFrom(), from) && sameElement(node.getWhere(), wher protected Node visitRefreshMaterializedView(RefreshMaterializedView node, C context) { Node table = process(node.getTarget(), context); - Node where = process(node.getWhere(), context); - if (node.getTarget() == table && node.getWhere() == where) { + Optional where = process(node.getWhere(), context); + if (node.getTarget() == table && sameElement(node.getWhere(), where)) { return node; } - return new RefreshMaterializedView((Table) table, (Expression) where); + return new RefreshMaterializedView((Table) table, where); } @Override