diff --git a/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java b/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java index 2b2c4cba5..f1e5be3cd 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java @@ -28,6 +28,8 @@ public class WithItem { private List> withItemList; private boolean recursive = false; + private boolean materialized = false; + public WithItem(T statement, Alias alias) { this.statement = statement; this.alias = alias; @@ -79,6 +81,14 @@ public void setRecursive(boolean recursive) { this.recursive = recursive; } + public boolean isMaterialized() { + return materialized; + } + + public void setMaterialized(boolean materialized) { + this.materialized = materialized; + } + /** * The {@link SelectItem}s in this WITH (for example the A,B,C in "WITH mywith (A,B,C) AS ...") * @@ -108,6 +118,7 @@ public String toString() { builder.append(")"); } builder.append(" AS "); + builder.append(materialized ? "MATERIALIZED " : ""); builder.append(statement); return builder.toString(); } @@ -121,8 +132,9 @@ public WithItem withWithItemList(List> withItemList) { return this; } - public WithItem withRecursive(boolean recursive) { + public WithItem withRecursive(boolean recursive, boolean materialized) { this.setRecursive(recursive); + this.setMaterialized(materialized); return this; } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java index a80af55ad..f7ac3ccf1 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java @@ -682,6 +682,9 @@ public StringBuilder visit(WithItem withItem, S context) { .append(PlainSelect.getStringList(withItem.getWithItemList(), true, true)); } buffer.append(" AS "); + if (withItem.isMaterialized()) { + buffer.append("MATERIALIZED "); + } StatementDeParser statementDeParser = new StatementDeParser((ExpressionDeParser) expressionVisitor, this, buffer); statementDeParser.deParse(withItem.getParenthesedStatement()); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index cfe72baca..7413d79f9 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -2705,6 +2705,7 @@ List> WithList(): WithItem WithItem() #WithItem: { boolean recursive = false; + boolean materialized = false; String name; List> selectItems = null; ParenthesedStatement statement; @@ -2714,6 +2715,7 @@ WithItem WithItem() #WithItem: name=RelObjectName() [ "(" selectItems=SelectItemsList() ")" ] + [ LOOKAHEAD(2) { materialized = true; } ] ( LOOKAHEAD(2) statement = ParenthesedSelect() | @@ -2726,7 +2728,7 @@ WithItem WithItem() #WithItem: { WithItem withItem = new WithItem(statement, new Alias(name, false)); return withItem - .withRecursive(recursive) + .withRecursive(recursive, materialized) .withWithItemList(selectItems); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java index dca870860..7964118f6 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -3186,6 +3186,12 @@ public void testSelectOracleColl() throws JSQLParserException { "SELECT * FROM the_table tt WHERE TT.COL1 = lines(idx).COL1"); } + @Test + public void testSelectWithMaterializedWith() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "WITH tokens_with_supply AS MATERIALIZED (SELECT * FROM tokens) SELECT * FROM tokens_with_supply"); + } + @Test public void testSelectInnerWith() throws JSQLParserException { String stmt =