Skip to content

Commit

Permalink
Fixes #1684: Support CREATE MATERIALIZED VIEW with AUTO REFRESH
Browse files Browse the repository at this point in the history
Support parsing create view statements in Redshift with AUTO REFRESH
option.
  • Loading branch information
zaza committed Dec 11, 2022
1 parent 08a92fc commit 747152a
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ public static List<String> getReservedKeywords(int restriction) {

, { "NEXTVAL", RESTRICTED_JSQLPARSER }

, { "AUTO", RESTRICTED_JSQLPARSER }
, { "REFRESH", RESTRICTED_JSQLPARSER }
, { "YES", RESTRICTED_JSQLPARSER }
, { "NO", RESTRICTED_JSQLPARSER }

//@todo: Object Names should not start with Hex-Prefix, we shall not find that Token
, { "0x", RESTRICTED_JSQLPARSER }
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2019 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.statement.create.view;

public enum AutoRefreshOption {
NONE,

YES,

NO
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class CreateView implements Statement {
private boolean materialized = false;
private ForceOption force = ForceOption.NONE;
private TemporaryOption temp = TemporaryOption.NONE;
private AutoRefreshOption autoRefresh = AutoRefreshOption.NONE;
private boolean withReadOnly = false;

@Override
Expand Down Expand Up @@ -95,6 +96,14 @@ public void setTemporary(TemporaryOption temp) {
this.temp = temp;
}

public AutoRefreshOption getAutoRefresh() {
return autoRefresh;
}

public void setAutoRefresh(AutoRefreshOption autoRefresh) {
this.autoRefresh = autoRefresh;
}

public boolean isWithReadOnly() {
return withReadOnly;
}
Expand Down Expand Up @@ -129,6 +138,9 @@ public String toString() {
}
sql.append("VIEW ");
sql.append(view);
if (autoRefresh != AutoRefreshOption.NONE) {
sql.append(" AUTO REFRESH ").append(autoRefresh.name());
}
if (columnNames != null) {
sql.append(PlainSelect.getStringList(columnNames, true, true));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import net.sf.jsqlparser.statement.create.view.CreateView;
import net.sf.jsqlparser.statement.create.view.TemporaryOption;
import net.sf.jsqlparser.statement.create.view.AutoRefreshOption;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectVisitor;
Expand Down Expand Up @@ -60,6 +61,10 @@ public void deParse(CreateView createView) {
buffer.append("MATERIALIZED ");
}
buffer.append("VIEW ").append(createView.getView().getFullyQualifiedName());

if (createView.getAutoRefresh() != AutoRefreshOption.NONE) {
buffer.append(" AUTO REFRESH ").append(createView.getAutoRefresh().name());
}
if (createView.getColumnNames() != null) {
buffer.append(PlainSelect.getStringList(createView.getColumnNames(), true, true));
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
| <K_AT: "AT">
| <K_ASC:"ASC">
| <K_AUTHORIZATION:"AUTHORIZATION">
| <K_AUTO:"AUTO">
| <K_BEGIN:"BEGIN">
| <K_BETWEEN:"BETWEEN">
| <K_BINARY: "BINARY">
Expand Down Expand Up @@ -345,6 +346,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
| <K_RECYCLEBIN: "RECYCLEBIN">
| <K_RECURSIVE:"RECURSIVE">
| <K_REFERENCES:"REFERENCES">
| <K_REFRESH:"REFRESH">
| <K_REGEXP: "REGEXP">
| <K_RLIKE: "RLIKE">
| <K_REGISTER: "REGISTER">
Expand Down Expand Up @@ -439,6 +441,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
| <K_XMLAGG:"XMLAGG">
| <K_XMLTEXT:"XMLTEXT">
| <K_YAML:"YAML">
| <K_YES:"YES">
| <K_ZONE:"ZONE">
}

Expand Down Expand Up @@ -5406,6 +5409,7 @@ CreateView CreateView():
Table view = null;
Select select = null;
List<String> columnNames = null;
Token tk = null;
}
{
<K_CREATE>
Expand All @@ -5420,6 +5424,7 @@ CreateView CreateView():
]
[ <K_MATERIALIZED> { createView.setMaterialized(true);} ]
<K_VIEW> view=Table() { createView.setView(view); }
[LOOKAHEAD(3) <K_AUTO> <K_REFRESH> (tk=<K_YES> | tk=<K_NO>) { createView.setAutoRefresh(AutoRefreshOption.valueOf(tk.image)); } ]
[ columnNames = ColumnsNamesList() { createView.setColumnNames(columnNames); } ]
<K_AS>
select=SelectWithWithItems( ) { createView.setSelect(select); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,21 @@
package net.sf.jsqlparser.statement.create;

import java.io.StringReader;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.parser.ParseException;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.create.view.AutoRefreshOption;
import net.sf.jsqlparser.statement.create.view.CreateView;
import net.sf.jsqlparser.statement.select.PlainSelect;
import static net.sf.jsqlparser.test.TestUtils.*;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;

import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.Test;

public class CreateViewTest {
Expand Down Expand Up @@ -121,4 +128,59 @@ public void testCreateTemporaryViewIssue665() throws JSQLParserException {
public void testCreateWithReadOnlyViewIssue838() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("CREATE VIEW v14(c1, c2) AS SELECT c1, C2 FROM t1 WITH READ ONLY");
}

@Test
public void testCreateViewAutoRefreshNone() throws JSQLParserException {
String stmt = "CREATE VIEW myview AS SELECT * FROM mytab";
CreateView createView = (CreateView) assertSqlCanBeParsedAndDeparsed(stmt);
assertEquals(createView.getAutoRefresh(), AutoRefreshOption.NONE);
}

@Test
public void testCreateViewAutoRefreshYes() throws JSQLParserException {
String stmt = "CREATE VIEW myview AUTO REFRESH YES AS SELECT * FROM mytab";
CreateView createView = (CreateView) assertSqlCanBeParsedAndDeparsed(stmt);
assertEquals(createView.getAutoRefresh(), AutoRefreshOption.YES);
}

@Test
public void testCreateViewAutoRefreshNo() throws JSQLParserException {
String stmt = "CREATE VIEW myview AUTO REFRESH NO AS SELECT * FROM mytab";
CreateView createView = (CreateView) assertSqlCanBeParsedAndDeparsed(stmt);
assertEquals(createView.getAutoRefresh(), AutoRefreshOption.NO);
}

@Test
public void testCreateViewAutoFails() throws JSQLParserException {
String stmt = "CREATE VIEW myview AUTO AS SELECT * FROM mytab";

ThrowingCallable throwingCallable = () -> CCJSqlParserUtil.parse(stmt);

assertThatThrownBy(throwingCallable).isInstanceOf(JSQLParserException.class)
.hasRootCauseInstanceOf(ParseException.class).rootCause()
.hasMessageStartingWith("Encountered unexpected token");
}

@Test
public void testCreateViewRefreshFails() throws JSQLParserException {
String stmt = "CREATE VIEW myview REFRESH AS SELECT * FROM mytab";

ThrowingCallable throwingCallable = () -> CCJSqlParserUtil.parse(stmt);

assertThatThrownBy(throwingCallable).isInstanceOf(JSQLParserException.class)
.hasRootCauseInstanceOf(ParseException.class).rootCause()
.hasMessageStartingWith("Encountered unexpected token");
}

@Test
public void testCreateViewAutoRefreshFails() throws JSQLParserException {
String stmt = "CREATE VIEW myview AUTO REFRESH AS SELECT * FROM mytab";

ThrowingCallable throwingCallable = () -> CCJSqlParserUtil.parse(stmt);

assertThatThrownBy(throwingCallable).isInstanceOf(JSQLParserException.class)
.hasRootCauseInstanceOf(ParseException.class).rootCause()
.hasMessageStartingWith("Encountered unexpected token");
}

}

0 comments on commit 747152a

Please sign in to comment.