diff --git a/src/main/java/net/sf/jsqlparser/statement/refresh/RefreshMaterializedViewStatement.java b/src/main/java/net/sf/jsqlparser/statement/refresh/RefreshMaterializedViewStatement.java index 6519cfe5c3..ee3d2c44c2 100644 --- a/src/main/java/net/sf/jsqlparser/statement/refresh/RefreshMaterializedViewStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/refresh/RefreshMaterializedViewStatement.java @@ -9,6 +9,7 @@ */ package net.sf.jsqlparser.statement.refresh; +import java.util.function.Consumer; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; @@ -60,34 +61,24 @@ public void setConcurrently(boolean concurrently) { this.concurrently = concurrently; } - @SuppressWarnings("PMD.SwitchStmtsShouldHaveDefault") - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); + public StringBuilder appendTo(StringBuilder builder, Consumer tablePrinter) { builder.append("REFRESH MATERIALIZED VIEW "); - if (this.refreshMode == null) { - if (concurrently) { - builder.append("CONCURRENTLY "); - } - builder.append(view); - return builder.toString(); + if (concurrently) { + builder.append("CONCURRENTLY "); } - switch (this.refreshMode) { - case WITH_DATA: - if (concurrently) { - builder.append("CONCURRENTLY "); - } - builder.append(view); - builder.append(" WITH DATA"); - break; - case WITH_NO_DATA: - builder.append(view); - if (!concurrently) { - builder.append(" WITH NO DATA"); - } - break; + tablePrinter.accept(view); + if (refreshMode == RefreshMode.WITH_DATA) { + builder.append(" WITH DATA"); + } else if (refreshMode == RefreshMode.WITH_NO_DATA) { + builder.append(" WITH NO DATA"); } - return builder.toString(); + return builder; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + return appendTo(builder, builder::append).toString(); } @Override diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/RefreshMaterializedViewStatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/RefreshMaterializedViewStatementDeParser.java index 444279ee6a..6c20b72cdb 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/RefreshMaterializedViewStatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/RefreshMaterializedViewStatementDeParser.java @@ -9,6 +9,8 @@ */ package net.sf.jsqlparser.util.deparser; +import java.util.function.Consumer; +import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement; /** @@ -18,36 +20,22 @@ public class RefreshMaterializedViewStatementDeParser extends AbstractDeParser { + private final Consumer
tablePrinter; + public RefreshMaterializedViewStatementDeParser(StringBuilder buffer) { super(buffer); + this.tablePrinter = table -> builder.append(table); + } + + public RefreshMaterializedViewStatementDeParser(StringBuilder buffer, + Consumer
tablePrinter) { + super(buffer); + this.tablePrinter = tablePrinter; } - @SuppressWarnings("PMD.SwitchStmtsShouldHaveDefault") @Override public void deParse(RefreshMaterializedViewStatement view) { - builder.append("REFRESH MATERIALIZED VIEW "); - if (view.getRefreshMode() == null) { - if (view.isConcurrently()) { - builder.append("CONCURRENTLY "); - } - builder.append(view.getView()); - return; - } - switch (view.getRefreshMode()) { - case WITH_DATA: - if (view.isConcurrently()) { - builder.append("CONCURRENTLY "); - } - builder.append(view.getView()); - builder.append(" WITH DATA"); - break; - case WITH_NO_DATA: - builder.append(view.getView()); - if (view.isConcurrently()) { - builder.append(" WITH NO DATA"); - } - break; - } + view.appendTo(builder, tablePrinter); } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java index 8516e51dc8..de9fc62d0e 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java @@ -215,7 +215,9 @@ public StringBuilder visit(CreateView createView, S context) { @Override public StringBuilder visit(RefreshMaterializedViewStatement materializedViewStatement, S context) { - new RefreshMaterializedViewStatementDeParser(builder).deParse(materializedViewStatement); + selectDeParser.setBuilder(builder); + new RefreshMaterializedViewStatementDeParser(builder, + table -> table.accept(selectDeParser, context)).deParse(materializedViewStatement); return builder; } diff --git a/src/test/java/net/sf/jsqlparser/statement/RefreshMaterializedViewStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/RefreshMaterializedViewStatementTest.java index 4ebba56c7f..ad0561352b 100644 --- a/src/test/java/net/sf/jsqlparser/statement/RefreshMaterializedViewStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/RefreshMaterializedViewStatementTest.java @@ -10,9 +10,21 @@ package net.sf.jsqlparser.statement; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement; +import net.sf.jsqlparser.statement.refresh.RefreshMode; +import net.sf.jsqlparser.util.deparser.ExpressionDeParser; +import net.sf.jsqlparser.util.deparser.RefreshMaterializedViewStatementDeParser; +import net.sf.jsqlparser.util.deparser.SelectDeParser; +import net.sf.jsqlparser.util.deparser.StatementDeParser; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; /** * @@ -21,8 +33,83 @@ public class RefreshMaterializedViewStatementTest { + @ParameterizedTest + @ValueSource(strings = {"REFRESH MATERIALIZED VIEW my_view", + "REFRESH MATERIALIZED VIEW my_view WITH DATA", + "REFRESH MATERIALIZED VIEW my_view WITH NO DATA", + "REFRESH MATERIALIZED VIEW CONCURRENTLY my_view", + "REFRESH MATERIALIZED VIEW CONCURRENTLY my_view WITH DATA"}) + public void testRefreshModes(String sql) throws JSQLParserException { + RefreshMaterializedViewStatement statement = + (RefreshMaterializedViewStatement) assertSqlCanBeParsedAndDeparsed(sql); + StringBuilder output = new StringBuilder(); + new RefreshMaterializedViewStatementDeParser(output).deParse(statement); + assertEquals(sql, output.toString()); + assertEquals(2, CCJSqlParserUtil.parseStatements(sql + "; SELECT 1").size()); + } + + @Test + void preservesModeWhenVisitingViewName() throws JSQLParserException { + RefreshMaterializedViewStatement statement = + (RefreshMaterializedViewStatement) CCJSqlParserUtil + .parse("REFRESH MATERIALIZED VIEW old_schema.mv WITH NO DATA"); + StringBuilder output = new StringBuilder(); + ExpressionDeParser expressions = new ExpressionDeParser(); + SelectDeParser selects = new SelectDeParser(expressions, output) { + @Override + public StringBuilder visit(Table table, S context) { + assertEquals("context", context); + getBuilder().append("new_schema.\"renamed view\""); + return getBuilder(); + } + }; + StringBuilder original = new StringBuilder(); + StatementDeParser deparser = new StatementDeParser(expressions, selects, original); + deparser.setBuilder(output); + assertSame(output, statement.accept(deparser, "context")); + assertEquals("", original.toString()); + assertEquals("REFRESH MATERIALIZED VIEW new_schema.\"renamed view\" WITH NO DATA", + output.toString()); + RefreshMaterializedViewStatement reparsed = + (RefreshMaterializedViewStatement) CCJSqlParserUtil.parse(output.toString()); + assertEquals(RefreshMode.WITH_NO_DATA, reparsed.getRefreshMode()); + assertEquals("new_schema", reparsed.getView().getSchemaName()); + } + + @Test + void statementDeparserUsesReplacementOutputBuffer() throws JSQLParserException { + StringBuilder original = new StringBuilder("old output"); + StringBuilder replacement = new StringBuilder(); + StatementDeParser deparser = new StatementDeParser(original); + deparser.setBuilder(replacement); + RefreshMaterializedViewStatement statement = + (RefreshMaterializedViewStatement) CCJSqlParserUtil + .parse("REFRESH MATERIALIZED VIEW schema_name.mv WITH NO DATA"); + assertSame(replacement, statement.accept(deparser, null)); + assertEquals("old output", original.toString()); + assertEquals(statement.toString(), replacement.toString()); + } + + @Test + void respectsReplacementOutputBuffer() throws JSQLParserException { + StringBuilder original = new StringBuilder(); + StringBuilder replacement = new StringBuilder(); + RefreshMaterializedViewStatementDeParser deparser = + new RefreshMaterializedViewStatementDeParser(original); + deparser.setBuilder(replacement); + deparser.deParse((RefreshMaterializedViewStatement) CCJSqlParserUtil + .parse("REFRESH MATERIALIZED VIEW mv WITH NO DATA")); + assertEquals("", original.toString()); + assertEquals("REFRESH MATERIALIZED VIEW mv WITH NO DATA", replacement.toString()); + } + @Test - public void testSimpleUse() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("REFRESH MATERIALIZED VIEW my_view"); + void rendersDefaultModeLikeOmittedMode() { + RefreshMaterializedViewStatement statement = new RefreshMaterializedViewStatement( + new Table("mv"), true, RefreshMode.DEFAULT); + StringBuilder output = new StringBuilder(); + new RefreshMaterializedViewStatementDeParser(output).deParse(statement); + assertEquals("REFRESH MATERIALIZED VIEW CONCURRENTLY mv", output.toString()); + assertEquals(statement.toString(), output.toString()); } }