diff --git a/pom.xml b/pom.xml index 32da52df7..f9291886b 100644 --- a/pom.xml +++ b/pom.xml @@ -193,7 +193,7 @@ org.javacc.plugin javacc-maven-plugin 3.0.3 - + javacc @@ -202,7 +202,7 @@ jjtree-javacc - + jjtree @@ -210,7 +210,7 @@ jjtree - + @@ -394,7 +394,7 @@ true 800m none - + - + org.codehaus.mojo findbugs-maven-plugin 3.0.5 - + - + org.codehaus.mojo javacc-maven-plugin 2.6 - false - + false - + false - + - + ${project.reporting.outputDirectory} diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index 949e96b19..1941328aa 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -375,7 +375,7 @@ public void visit(NamedExpressionList namedExpressionList) { @Override public void visit(MultiExpressionList multiExprList) { - for (ExpressionList list : multiExprList.getExprList()) { + for (ExpressionList list : multiExprList.getExpressionLists()) { visit(list); } } diff --git a/src/main/java/net/sf/jsqlparser/expression/SpannerInterleaveIn.java b/src/main/java/net/sf/jsqlparser/expression/SpannerInterleaveIn.java new file mode 100644 index 000000000..9a7ebc002 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/SpannerInterleaveIn.java @@ -0,0 +1,75 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2021 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.schema.Table; + +import java.util.Collections; +import java.util.List; + +public class SpannerInterleaveIn { + + public enum OnDelete { + CASCADE, + NO_ACTION + } + + private Table table; + private OnDelete onDelete; + + public SpannerInterleaveIn() { + + } + + public SpannerInterleaveIn(Table table, OnDelete action) { + setTable(table); + setOnDelete(action); + } + + public SpannerInterleaveIn(List nameParts) { + this(new Table(nameParts), null); + } + + public SpannerInterleaveIn(String tableName) { + this(Collections.singletonList(tableName)); + } + + public Table getTable() { + return table; + } + + public void setTable(Table table) { + this.table = table; + } + + public OnDelete getOnDelete() { + return onDelete; + } + + public void setOnDelete(OnDelete action) { + this.onDelete = action; + } + + @Override + public String toString() { + return "INTERLEAVE IN PARENT " + getTable().getName() + + (getOnDelete() == null ? "" : " ON DELETE " + (getOnDelete() == OnDelete.CASCADE ? "CASCADE" : "NO ACTION")); + } + + public SpannerInterleaveIn withTable(Table table) { + this.setTable(table); + return this; + } + + public SpannerInterleaveIn withOnDelete(OnDelete action) { + this.setOnDelete(action); + return this; + } +} diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsListVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsListVisitorAdapter.java index ea711fe9b..e8768b646 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsListVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsListVisitorAdapter.java @@ -31,7 +31,7 @@ public void visit(ExpressionList expressionList) { @Override public void visit(MultiExpressionList multiExprList) { - for (ExpressionList list : multiExprList.getExprList()) { + for (ExpressionList list : multiExprList.getExpressionLists()) { visit(list); } } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/CreateTable.java b/src/main/java/net/sf/jsqlparser/statement/create/table/CreateTable.java index 8fb5b4cc1..41b27ad89 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/table/CreateTable.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/CreateTable.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.Optional; +import net.sf.jsqlparser.expression.SpannerInterleaveIn; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; @@ -37,6 +38,7 @@ public class CreateTable implements Statement { private boolean orReplace = false; private RowMovement rowMovement; + private SpannerInterleaveIn interleaveIn = null; @Override public void accept(StatementVisitor statementVisitor) { @@ -186,7 +188,7 @@ public String toString() { sql += ")"; } String options = PlainSelect.getStringList(tableOptionsStrings, false, false); - if (options != null && options.length() > 0) { + if (!options.isEmpty()) { sql += " " + options; } @@ -194,10 +196,13 @@ public String toString() { sql += " " + rowMovement.getMode().toString() + " ROW MOVEMENT"; } if (select != null) { - sql += " AS " + (selectParenthesis ? "(" : "") + select.toString() + (selectParenthesis ? ")" : ""); + sql += " AS " + (selectParenthesis ? "(" : "") + select + (selectParenthesis ? ")" : ""); } if (likeTable != null) { - sql += " LIKE " + (selectParenthesis ? "(" : "") + likeTable.toString() + (selectParenthesis ? ")" : ""); + sql += " LIKE " + (selectParenthesis ? "(" : "") + likeTable + (selectParenthesis ? ")" : ""); + } + if (interleaveIn != null) { + sql += ", " + interleaveIn; } return sql; } @@ -299,4 +304,17 @@ public CreateTable addIndexes(Collection indexes) { collection.addAll(indexes); return this.withIndexes(collection); } + + public SpannerInterleaveIn getSpannerInterleaveIn() { + return interleaveIn; + } + + public void setSpannerInterleaveIn(SpannerInterleaveIn spannerInterleaveIn) { + this.interleaveIn = spannerInterleaveIn; + } + + public CreateTable withSpannerInterleaveIn(SpannerInterleaveIn spannerInterleaveIn) { + this.interleaveIn = spannerInterleaveIn; + return this; + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/ValuesList.java b/src/main/java/net/sf/jsqlparser/statement/select/ValuesList.java index 70b9c9c6e..46fad2d3b 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/ValuesList.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/ValuesList.java @@ -88,7 +88,7 @@ public String toString() { StringBuilder b = new StringBuilder(); b.append("(VALUES "); - for (Iterator it = getMultiExpressionList().getExprList().iterator(); it. + for (Iterator it = getMultiExpressionList().getExpressionLists().iterator(); it. hasNext();) { b.append(PlainSelect.getStringList(it.next().getExpressions(), true, !isNoBrackets())); if (it.hasNext()) { diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index 43def03eb..1c00fb02e 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -496,7 +496,7 @@ public void visit(LateralSubSelect lateralSubSelect) { @Override public void visit(MultiExpressionList multiExprList) { - for (ExpressionList exprList : multiExprList.getExprList()) { + for (ExpressionList exprList : multiExprList.getExpressionLists()) { exprList.accept(this); } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/CreateIndexDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/CreateIndexDeParser.java index 0f2aae236..947c75abb 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/CreateIndexDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/CreateIndexDeParser.java @@ -44,7 +44,7 @@ public void deParse(CreateIndex createIndex) { if (index.getColumnsNames() != null) { buffer.append(" ("); - buffer.append(index.getColumnWithParams().stream() + buffer.append(index.getColumns().stream() .map(cp -> cp.columnName + (cp.getParams() != null ? " " + String.join(" ", cp.getParams()) : "")) .collect(joining(", "))); buffer.append(")"); diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/CreateTableDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/CreateTableDeParser.java index 4036d9ad0..d930e944c 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/CreateTableDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/CreateTableDeParser.java @@ -120,6 +120,9 @@ public void deParse(CreateTable createTable) { buffer.append(")"); } } + if (createTable.getSpannerInterleaveIn() != null) { + buffer.append(", ").append(createTable.getSpannerInterleaveIn()); + } } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/DeclareStatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/DeclareStatementDeParser.java index 42951127b..6e7119c19 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/DeclareStatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/DeclareStatementDeParser.java @@ -31,13 +31,13 @@ public void deParse(DeclareStatement declare) { declare.getUserVariable().accept(expressionVisitor); } - if (declare.getType() == DeclareType.AS) { + if (declare.getDeclareType() == DeclareType.AS) { buffer.append(" AS "); buffer.append(declare.getTypeName()); return; } - if (declare.getType() == DeclareType.TABLE) { + if (declare.getDeclareType() == DeclareType.TABLE) { buffer.append(" TABLE ("); for (int i = 0; i < declare.getColumnDefinitions().size(); i++) { if (i > 0) { diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java index 3f9f7b0ac..818f42821 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -739,7 +739,7 @@ public void visit(ExtractExpression eexpr) { @Override public void visit(MultiExpressionList multiExprList) { - for (Iterator it = multiExprList.getExprList().iterator(); it.hasNext();) { + for (Iterator it = multiExprList.getExpressionLists().iterator(); it.hasNext();) { it.next().accept(this); if (it.hasNext()) { buffer.append(", "); diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java index 5cb975ee6..953a1bb72 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java @@ -164,7 +164,7 @@ public void visit(NamedExpressionList NamedExpressionList) { @Override public void visit(MultiExpressionList multiExprList) { buffer.append(" VALUES "); - for (Iterator it = multiExprList.getExprList().iterator(); it.hasNext();) { + for (Iterator it = multiExprList.getExpressionLists().iterator(); it.hasNext();) { buffer.append("("); for (Iterator iter = it.next().getExpressions().iterator(); iter.hasNext();) { Expression expression = iter.next(); diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ReplaceDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ReplaceDeParser.java index 1e3828076..5e763d9ed 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ReplaceDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ReplaceDeParser.java @@ -123,7 +123,7 @@ public void setSelectVisitor(SelectVisitor visitor) { @Override public void visit(MultiExpressionList multiExprList) { buffer.append("VALUES "); - for (Iterator it = multiExprList.getExprList().iterator(); it.hasNext();) { + for (Iterator it = multiExprList.getExpressionLists().iterator(); it.hasNext();) { buffer.append("("); for (Iterator iter = it.next().getExpressions().iterator(); iter.hasNext();) { Expression expression = iter.next(); diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/UpsertDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/UpsertDeParser.java index 32311c47b..746c3b20d 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/UpsertDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/UpsertDeParser.java @@ -123,7 +123,7 @@ public void visit(NamedExpressionList namedExpressionList) { @Override public void visit(MultiExpressionList multiExprList) { buffer.append(" VALUES "); - for (Iterator it = multiExprList.getExprList().iterator(); it.hasNext();) { + for (Iterator it = multiExprList.getExpressionLists().iterator(); it.hasNext();) { buffer.append("("); for (Iterator iter = it.next().getExpressions().iterator(); iter.hasNext();) { Expression expression = iter.next(); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index bb44f7907..766f341ae 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -169,7 +169,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | -| +| | | | @@ -379,8 +379,8 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | -| @@ -464,6 +464,16 @@ TOKEN : /* Numeric Constants */ | < #HEX_VALUE: ["0"-"9","A"-"F"] > } +TOKEN : /* Google Spanner Token*/ +{ + )* ()* "PARENT" > + | + | )* "("> + | )* "("> + | )* "("> +} + + SPECIAL_TOKEN: { < LINE_COMMENT: ("--" | "//") (~["\r","\n"])*> @@ -491,7 +501,7 @@ TOKEN: } Statement Statement() #Statement: -{ +{ IfElseStatement ifElseStatement = null; Statement stm = null; Statement stm2 = null; @@ -500,11 +510,11 @@ Statement Statement() #Statement: { try { ( - condition=Condition() + condition=Condition() stm = SingleStatement() { ifElseStatement = new IfElseStatement(condition, stm); } [ { ifElseStatement.setUsingSemicolonForIfStatement(true); } ] - [ LOOKAHEAD(2) - stm2 = SingleStatement() { ifElseStatement.setElseStatement(stm2); } + [ LOOKAHEAD(2) + stm2 = SingleStatement() { ifElseStatement.setElseStatement(stm2); } [ { ifElseStatement.setUsingSemicolonForElseStatement(true); }] ] @@ -676,7 +686,7 @@ Block Block() #Block : { Statements Statements() #Statements : { Statements stmts = new Statements(); List list = new ArrayList(); - + IfElseStatement ifElseStatement = null; Statement stm = null; Statement stm2 = null; @@ -687,18 +697,18 @@ Statements Statements() #Statements : { try { ( ( - condition=Condition() + condition=Condition() stm = SingleStatement() { ifElseStatement = new IfElseStatement(condition, stm); } - [ LOOKAHEAD(2) + [ LOOKAHEAD(2) [ { ifElseStatement.setUsingSemicolonForIfStatement(true); } ] - stm2 = SingleStatement() { ifElseStatement.setElseStatement(stm2); } + stm2 = SingleStatement() { ifElseStatement.setElseStatement(stm2); } ] { list.add( ifElseStatement ); } ) | ( - stm = SingleStatement() + stm = SingleStatement() | stm = Block() [ LOOKAHEAD(2) ] @@ -706,30 +716,30 @@ Statements Statements() #Statements : { ) - ( - { if (stm2!=null) - ifElseStatement.setUsingSemicolonForElseStatement(true); - else if (ifElseStatement!=null) - ifElseStatement.setUsingSemicolonForIfStatement(true); } + ( + { if (stm2!=null) + ifElseStatement.setUsingSemicolonForElseStatement(true); + else if (ifElseStatement!=null) + ifElseStatement.setUsingSemicolonForIfStatement(true); } [ ( - condition=Condition() + condition=Condition() stm = SingleStatement() { ifElseStatement = new IfElseStatement(condition, stm); } - [ LOOKAHEAD(2) + [ LOOKAHEAD(2) [ { ifElseStatement.setUsingSemicolonForIfStatement(true); } ] - stm2 = SingleStatement() { ifElseStatement.setElseStatement(stm2); } + stm2 = SingleStatement() { ifElseStatement.setElseStatement(stm2); } ] { list.add( ifElseStatement ); } ) | ( - stm = SingleStatement() + stm = SingleStatement() | stm = Block() [ LOOKAHEAD(2) ] ) { list.add(stm); } - ] + ] )* } catch (ParseException e) { @@ -860,11 +870,11 @@ RenameTableStatement RenameTableStatement(): { Token token; } { - + [ LOOKAHEAD(2) { usingTableKeyword = true; } ] [ LOOKAHEAD(2) { usesIfExistsKeyword = true; } ] oldName = Table() - [ ( + [ ( token= { waitDirective = "WAIT " + token.image; } | { waitDirective = "NOWAIT"; } @@ -872,8 +882,8 @@ RenameTableStatement RenameTableStatement(): { newName = Table() - { - renameTableStatement = new RenameTableStatement(oldName, newName, usingTableKeyword, usesIfExistsKeyword, waitDirective); + { + renameTableStatement = new RenameTableStatement(oldName, newName, usingTableKeyword, usesIfExistsKeyword, waitDirective); } ( @@ -886,7 +896,7 @@ RenameTableStatement RenameTableStatement(): { } )* - { + { return renameTableStatement; } } @@ -899,21 +909,21 @@ PurgeStatement PurgeStatement(): { Token userToken = null; } { - + ( table=Table() { purgeStatement = new PurgeStatement(table); } - | + | index=Index() { purgeStatement = new PurgeStatement(index); } | { purgeStatement = new PurgeStatement(PurgeObjectType.RECYCLEBIN); } | { purgeStatement = new PurgeStatement(PurgeObjectType.DBA_RECYCLEBIN); } | - tableSpaceToken= [ userToken= ] { + tableSpaceToken= [ userToken= ] { purgeStatement = new PurgeStatement( PurgeObjectType.TABLESPACE , tableSpaceToken.image - , userToken!=null ? userToken.image : null); + , userToken!=null ? userToken.image : null); } ) @@ -1672,6 +1682,8 @@ String RelObjectNameWithoutValue() : | tk= | tk= | tk= + + | tk= ) { return tk.image; } @@ -2018,14 +2030,14 @@ WithItem WithItem() #WithItem: [ "(" selectItems=SelectItemsList() ")" { with.setWithItemList(selectItems); } ] // if the next block looks alike an ExpressionList without Brackets, then parse as List - ( LOOKAHEAD( "(" SimpleExpressionList(true) ")" ) + ( LOOKAHEAD( "(" SimpleExpressionList(true) ")" ) "(" simpleExpressionList = SimpleExpressionList(true) { with.withUseBracketsForValues(false).setItemsList(simpleExpressionList); } ")" // Otherwise parse it as a SubSelect | "(" select = SubSelect() { with.setSubSelect(select.withUseBrackets(false)); with.setUseValues(false); } ")" - + ) { return with; } } @@ -2663,7 +2675,7 @@ GroupByElement GroupByColumnReferences(): "(" ")" { groupBy.withUsingBrackets(true); } ) | - LOOKAHEAD(2) ( + LOOKAHEAD(2) ( "(" ( LOOKAHEAD(2) "(" ")" { groupBy.addGroupingSet(new ExpressionList()); } | LOOKAHEAD(3) "(" list = SimpleExpressionList(true) ")" { groupBy.addGroupingSet(list); } @@ -2675,7 +2687,7 @@ GroupByElement GroupByColumnReferences(): ")" ) | - LOOKAHEAD(2) ( + LOOKAHEAD(2) ( list = ComplexExpressionList() { groupBy.setGroupByExpressionList(list.withUsingBrackets(false)); } ) ) @@ -3141,7 +3153,7 @@ Expression InExpression() #InExpression : ( LOOKAHEAD(2) token= { result.setRightExpression(new StringValue(token.image)); } | LOOKAHEAD(3) rightExpression = Function() { result.setRightExpression(rightExpression); } - | LOOKAHEAD( "(" ComplexExpressionList() ")" ) "(" rightItemsList=ComplexExpressionList() { result.setRightItemsList(rightItemsList.withBrackets(true) ); } ")" + | LOOKAHEAD( "(" ComplexExpressionList() ")" ) "(" rightItemsList=ComplexExpressionList() { result.setRightItemsList(rightItemsList.withUsingBrackets(true) ); } ")" | LOOKAHEAD(3) "(" rightExpression = SubSelect() { result.setRightExpression( ((SubSelect) rightExpression).withUseBrackets(true) ); } ")" | LOOKAHEAD(2) rightExpression = SimpleExpression() { result.setRightExpression(rightExpression); } ) @@ -3290,12 +3302,12 @@ ExpressionList SQLExpressionList(): ExpressionList SimpleExpressionList(boolean outerBrackets) #ExpressionList: { - ExpressionList retval = new ExpressionList().withBrackets(outerBrackets); + ExpressionList retval = new ExpressionList().withUsingBrackets(outerBrackets); List expressions = new ArrayList(); Expression expr = null; } { - expr=SimpleExpression() { expressions.add(expr); } + expr=SimpleExpression() { expressions.add(expr); } ( LOOKAHEAD(2) "," expr=SimpleExpression() { expressions.add(expr); } )* { retval.setExpressions(expressions); @@ -3310,16 +3322,16 @@ ExpressionList ComplexExpressionList() #ExpressionList: Expression expr = null; } { - ( + ( LOOKAHEAD(2) expr=OracleNamedFunctionParameter() - | expr=Expression() + | expr=Expression() ) { expressions.add(expr); } ( LOOKAHEAD(2) "," ( LOOKAHEAD(2) expr=OracleNamedFunctionParameter() - | expr=Expression() + | expr=Expression() ) { expressions.add(expr); } )* @@ -3457,7 +3469,7 @@ Expression AnyComparisonExpression() : ) // Otherwise parse it as a SubSelect | subSelect = SubSelect() { anyComparisonExpr=new AnyComparisonExpression(anyType, subSelect.withUseBrackets(false)).withUseBracketsForValues(false); } - + ) ")" { @@ -3655,7 +3667,7 @@ Expression PrimaryExpression() #PrimaryExpression: [ { not=true; } | "!" { not=true; exclamationMarkNot=true; } ] [sign="+" | sign="-" | sign="~"] ( - { retval = new NullValue(); } + LOOKAHEAD(2) { retval = new NullValue(); } | LOOKAHEAD(3) retval=CaseWhenExpression() @@ -3832,7 +3844,7 @@ OracleNamedFunctionParameter OracleNamedFunctionParameter() : { { name=RelObjectNameExt2() - expression=Expression() + expression=Expression() { return new OracleNamedFunctionParameter(name, expression); } @@ -3860,7 +3872,7 @@ NumericBind NumericBind() : { { ":" token= { - var.setBindId(Integer.valueOf(token.image)); + var.setBindId(Integer.parseInt(token.image)); return var; } } @@ -3874,7 +3886,7 @@ DateTimeLiteralExpression DateTimeLiteralExpression() : { t= { expr.setValue(t.image); return expr; } } -ArrayConstructor ArrayConstructor(final boolean arrayKeyword) : { +ArrayConstructor ArrayConstructor(boolean arrayKeyword) : { ArrayList expList = new ArrayList(); ArrayConstructor array = new ArrayConstructor(expList, arrayKeyword); Expression exp = null; @@ -3927,12 +3939,12 @@ JsonFunction JsonFunction() : { Expression expression; JsonFunctionExpression functionExpression; - + } { ( - ( - ( + ( + ( "(" { result.setType( JsonFunctionType.OBJECT ); } ( @@ -3995,25 +4007,25 @@ JsonFunction JsonFunction() : { ")" ) | - ( - { result.setType( JsonFunctionType.ARRAY ); } - "(" - ( - LOOKAHEAD(2) ( + ( + { result.setType( JsonFunctionType.ARRAY ); } + "(" + ( + LOOKAHEAD(2) ( { result.setOnNullType( JsonAggregateOnNullType.NULL ); } ) | expression=Expression() { functionExpression = new JsonFunctionExpression( expression ); result.add( functionExpression ); } - + [ LOOKAHEAD(2) { functionExpression.setUsingFormatJson( true ); } ] - ( + ( "," expression=Expression() { functionExpression = new JsonFunctionExpression( expression ); result.add( functionExpression ); } [ LOOKAHEAD(2) { functionExpression.setUsingFormatJson( true ); } ] )* )* - [ + [ { result.setOnNullType( JsonAggregateOnNullType.ABSENT ); } ] @@ -4032,7 +4044,7 @@ JsonAggregateFunction JsonAggregateFunction() : { Token token; Expression expression; List expressionOrderByList = null; - + Expression filter; ExpressionList expressionList = null; List olist = null; @@ -4041,22 +4053,22 @@ JsonAggregateFunction JsonAggregateFunction() : { } { ( - ( - ( - "(" { result.setType( JsonFunctionType.OBJECT ); } + ( + ( + "(" { result.setType( JsonFunctionType.OBJECT ); } [ "KEY" { result.setUsingKeyKeyword( true ); } ] ( token = | token = | token = | token = | token = | token = | token = ) { result.setKey( token.image ); } - ( ":" | "VALUE" {result.setUsingValueKeyword( true ); } ) + ( ":" | "VALUE" {result.setUsingValueKeyword( true ); } ) ( token = | token = ) { result.setValue( token.image ); } [ { result.setUsingFormatJson( true ); } ] - [ - LOOKAHEAD(2) ( + [ + LOOKAHEAD(2) ( { result.setOnNullType( JsonAggregateOnNullType.NULL ); } ) | - ( + ( { result.setOnNullType( JsonAggregateOnNullType.ABSENT ); } ) ] @@ -4073,19 +4085,19 @@ JsonAggregateFunction JsonAggregateFunction() : { ")" ) | - ( + ( - "(" { result.setType( JsonFunctionType.ARRAY ); } + "(" { result.setType( JsonFunctionType.ARRAY ); } expression=Expression() { result.setExpression( expression ); } [ { result.setUsingFormatJson( true ); } ] [ expressionOrderByList = OrderByElements() { result.setExpressionOrderByElements( expressionOrderByList ); } ] - [ - LOOKAHEAD(2) ( + [ + LOOKAHEAD(2) ( { result.setOnNullType( JsonAggregateOnNullType.NULL ); } ) | - ( + ( { result.setOnNullType( JsonAggregateOnNullType.ABSENT ); } ) ] @@ -4292,15 +4304,15 @@ CastExpression CastExpression(): boolean useCastKeyword; } { - - "(" - expression=SimpleExpression() - { retval.setUseCastKeyword(true); } - ( - LOOKAHEAD(3) rowConstructor = RowConstructor() { retval.setRowConstructor(rowConstructor); } - | type=ColDataType() { retval.setType(type); } + + "(" + expression=SimpleExpression() + { retval.setUseCastKeyword(true); } + ( + LOOKAHEAD(3) rowConstructor = RowConstructor() { retval.setRowConstructor(rowConstructor); } + | type=ColDataType() { retval.setType(type); } ) - ")" + ")" { retval.setLeftExpression(expression); @@ -4345,7 +4357,7 @@ Expression CaseWhenExpression() #CaseWhenExpression: { caseCounter++; } [ switchExp=Condition() ] ( clause=WhenThenSearchCondition() { whenClauses.add(clause); } )+ - [ (LOOKAHEAD( ["("] CaseWhenExpression() [")"] ( | | ) ) ["("] elseExp=CaseWhenExpression() [")" { ((CaseExpression) elseExp).setUsingBrackets(true); } ] + [ (LOOKAHEAD( ["("] CaseWhenExpression() [")"] ( | | ) ) ["("] elseExp=CaseWhenExpression() [")" { ((CaseExpression) elseExp).setUsingBrackets(true); } ] | elseExp=Expression() ) ] @@ -4368,7 +4380,7 @@ WhenClause WhenThenSearchCondition(): whenExp=Expression() ( LOOKAHEAD( ["("] CaseWhenExpression() [")"] ( | | ) ) ["("] thenExp=CaseWhenExpression() [")" { ((CaseExpression) thenExp).setUsingBrackets(true); }] - | + | thenExp=Expression() ) { @@ -4386,11 +4398,11 @@ RowConstructor RowConstructor(): { "(" columnDefinition = ColumnDefinition() { rowConstructor.addColumnDefinition(columnDefinition); } ( - "," + "," columnDefinition = ColumnDefinition() { rowConstructor.addColumnDefinition(columnDefinition); } - )* + )* ")" - + { return rowConstructor; @@ -4455,12 +4467,12 @@ FullTextSearch FullTextSearch() : { } { "(" col=Column() { matchedColumns.add(col); } ("," col=Column() { matchedColumns.add(col); } )* ")" - "(" - ( - againstValue= { fs.setAgainstValue(new StringValue(againstValue.image)); } - | + "(" + ( + againstValue= { fs.setAgainstValue(new StringValue(againstValue.image)); } + | jdbcParameter=SimpleJdbcParameter() { fs.setAgainstValue( jdbcParameter ); } - | + | jdbcNamedParameter=SimpleJdbcNamedParameter() { fs.setAgainstValue( jdbcNamedParameter ); } ) [ @@ -4525,9 +4537,9 @@ Function SpecialStringFunctionWithNamedParameters() : List orderByList; } { - funcName = + funcName = - "(" + "(" ( LOOKAHEAD(NamedExpressionList1()) namedExpressionList=NamedExpressionList1() | @@ -4535,7 +4547,7 @@ Function SpecialStringFunctionWithNamedParameters() : | LOOKAHEAD(3, { getAsBoolean(Feature.allowComplexParsing) }) expressionList=ComplexExpressionList() {expressionList.setUsingBrackets(false);} | - LOOKAHEAD(3) expressionList=SimpleExpressionList(false) + LOOKAHEAD(3) expressionList=SimpleExpressionList(false) ) ")" @@ -4713,7 +4725,7 @@ List ColumnNamesWithParamsList() : { Index Index(): { List name; -} +} { name= RelObjectNameList() { return new Index().withName(name).withType(""); } } @@ -4855,6 +4867,7 @@ CreateTable CreateTable(): List parameter = new ArrayList(); List idxSpec = new ArrayList(); Table fkTable = null; + SpannerInterleaveIn interleaveIn = null; Select select = null; Table likeTable = null; CheckConstraint checkCs = null; @@ -4879,8 +4892,8 @@ CreateTable CreateTable(): [ LOOKAHEAD(2) { createTable.setIfNotExists(true); }] table=Table() - [ LOOKAHEAD(2) ( - LOOKAHEAD(3) + [ LOOKAHEAD(2) ( + LOOKAHEAD(3) ("(" tableColumn=RelObjectName() { columns.add(tableColumn); } ("," tableColumn=RelObjectName() { columns.add(tableColumn); } )* ")") | ("(" @@ -5023,6 +5036,7 @@ CreateTable CreateTable(): ( LOOKAHEAD("(" Table() ")") "(" likeTable=Table() { createTable.setLikeTable(likeTable, true); } ")" | likeTable=Table() { createTable.setLikeTable(likeTable, false); } ) ] + [ interleaveIn = SpannerInterleaveIn( ) { createTable.setSpannerInterleaveIn(interleaveIn); } ] { createTable.setTable(table); if (indexes.size() > 0) @@ -5039,6 +5053,25 @@ CreateTable CreateTable(): } } +SpannerInterleaveIn SpannerInterleaveIn(): +{ + Table table = null; + SpannerInterleaveIn.OnDelete action = null; +} +{ + table = Table() + [ + + ( + { action = SpannerInterleaveIn.OnDelete.NO_ACTION; } + | { action = SpannerInterleaveIn.OnDelete.CASCADE; } + ) + ] + { + return new SpannerInterleaveIn(table, action); + } +} + ColDataType ColDataType(): { ColDataType colDataType = new ColDataType(); @@ -5047,16 +5080,25 @@ ColDataType ColDataType(): List argumentsStringList = new ArrayList(); List array = new ArrayList(); List name; + ColDataType arrayType; } { ( - (tk= | tk=) [tk2=] { colDataType.setDataType(tk.image + (tk2!=null?" " + tk2.image:"")); } + tk= ( + ("<" arrayType = ColDataType() ">") { + colDataType.setDataType("ARRAY<" + arrayType.getDataType() + ">"); + } + ) + | LOOKAHEAD(2) ( tk= | tk= | tk= ) + (tk2= | tk2=) ")" + { colDataType.setDataType(tk.image + tk2.image +")"); } + | (tk= | tk=) [tk2=] { colDataType.setDataType(tk.image + (tk2!=null?" " + tk2.image:"")); } | tk= [LOOKAHEAD(2) tk2=] { colDataType.setDataType(tk.image + (tk2!=null?" " + tk2.image:"")); } | ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= ) [ "." tk2= ] { if (tk2!=null) colDataType.setDataType(tk.image + "." + tk2.image); else colDataType.setDataType(tk.image); } - | tk= [LOOKAHEAD(2) tk2=] + | tk= [LOOKAHEAD(2) tk2=] { if (tk2!=null) colDataType.setDataType(tk.image + " " + tk2.image); else colDataType.setDataType(tk.image); } | LOOKAHEAD(2) tk= tk2= {colDataType.setDataType(tk.image + " " + tk2.image);} | tk= { colDataType.setDataType(tk.image);} @@ -5177,7 +5219,13 @@ List CreateParameter(): ) { param.add(retval); } | - tk= { param.add(tk.image); } + tk= ( + ("(" exp = Expression() ")") { param.add("AS"); param.add("(" + exp.toString() + ")");} + | + { param.add(tk.image);} + ) + | + tk= { param.add(tk.image); } | tk= { param.add(tk.image); } | @@ -5687,7 +5735,7 @@ AlterExpression AlterExpression(): ) | LOOKAHEAD(2) { alterExp.setOperation(AlterOperation.RENAME); alterExp.hasColumn(true);} - ( tk= | tk= ) { alterExp.setColOldName(tk.image); } + ( tk= | tk= ) { alterExp.setColumnOldName(tk.image); } (tk2= | tk2=) { alterExp.setColumnName(tk2.image); } | @@ -5700,12 +5748,12 @@ AlterExpression AlterExpression(): tk= { alterExp.setCommentText(tk.image); } ) | - tokens = captureRest() { + tokens = captureRest() { alterExp.setOperation(AlterOperation.UNSPECIFIC); StringBuilder optionalSpecifier = new StringBuilder(); int i=0; - for (String s: tokens) + for (String s: tokens) if (!s.equals(";")) { if (i>0) optionalSpecifier.append( " " ); @@ -5757,18 +5805,18 @@ AlterSession AlterSession(): } { ( - ( + ( ( { operation = AlterSessionOperation.ADVISE_COMMIT; } | { operation = AlterSessionOperation.ADVISE_ROLLBACK; } | { operation = AlterSessionOperation.ADVISE_NOTHING; } ) ) | - ( + ( { operation = AlterSessionOperation.CLOSE_DATABASE_LINK; } ) - | - ( + | + ( ( { operation = AlterSessionOperation.ENABLE_COMMIT_IN_PROCEDURE; } | { operation = AlterSessionOperation.ENABLE_GUARD; } | ( { operation = AlterSessionOperation.ENABLE_PARALLEL_DML; } @@ -5779,7 +5827,7 @@ AlterSession AlterSession(): ) ) | - ( + ( ( { operation = AlterSessionOperation.DISABLE_COMMIT_IN_PROCEDURE; } | { operation = AlterSessionOperation.DISABLE_GUARD; } | ( { operation = AlterSessionOperation.DISABLE_PARALLEL_DML; } @@ -5790,19 +5838,19 @@ AlterSession AlterSession(): ) ) | - ( + ( ( { operation = AlterSessionOperation.FORCE_PARALLEL_DML; } | { operation = AlterSessionOperation.FORCE_PARALLEL_DDL; } | { operation = AlterSessionOperation.FORCE_PARALLEL_QUERY; } ) ) | - ( + ( { operation = AlterSessionOperation.SET; } ) ) - ( ( token = + ( ( token = | token = | token = "=" | token = @@ -5823,61 +5871,61 @@ AlterSystemStatement AlterSystemStatement(): } { ( - ( + ( "ARCHIVE" "LOG" { operation = AlterSystemOperation.ARCHIVE_LOG; } ) | - ( + ( "CHECKPOINT" { operation = AlterSystemOperation.CHECKPOINT; } ) | - ( + ( "DUMP" "ACTIVE" "SESSION" "HISTORY" { operation = AlterSystemOperation.DUMP_ACTIVE_SESSION_HISTORY; } ) - | - ( - ( + | + ( + ( "DISTRIBUTED RECOVERY" { operation = AlterSystemOperation.ENABLE_DISTRIBUTED_RECOVERY; } | "RESTRICTED SESSION" { operation = AlterSystemOperation.ENABLE_DISTRIBUTED_RECOVERY; } ) ) | - ( - ( + ( + ( "DISTRIBUTED RECOVERY" { operation = AlterSystemOperation.DISABLE_DISTRIBUTED_RECOVERY; } | "RESTRICTED SESSION" { operation = AlterSystemOperation.DISABLE_RESTRICTED_SESSION; } ) ) | - ( + ( "FLUSH" { operation = AlterSystemOperation.FLUSH; } ) | - ( + ( "DISCONNECT" "SESSION" { operation = AlterSystemOperation.DISCONNECT_SESSION; } ) | - ( + ( "DISCONNECT SESSION" { operation = AlterSystemOperation.DISCONNECT_SESSION; } ) | - ( + ( "KILL SESSION" { operation = AlterSystemOperation.KILL_SESSION; } ) | - ( + ( "SWITCH" { operation = AlterSystemOperation.SWITCH; } ) | - ( + ( "SUSPEND" { operation = AlterSystemOperation.SUSPEND; } ) | - ( + ( "RESUME" { operation = AlterSystemOperation.RESUME; } ) | - ( + ( "QUIESCE" "RESTRICTED" { operation = AlterSystemOperation.QUIESCE; } ) | @@ -5885,19 +5933,19 @@ AlterSystemStatement AlterSystemStatement(): "UNQUIESCE" { operation = AlterSystemOperation.UNQUIESCE; } ) | - ( + ( "SHUTDOWN" { operation = AlterSystemOperation.SHUTDOWN; } ) | - ( + ( "REGISTER" { operation = AlterSystemOperation.REGISTER; } ) | - ( + ( "SET" { operation = AlterSystemOperation.SET; } ) | - ( + ( "RESET" { operation = AlterSystemOperation.RESET; } ) ) @@ -5946,14 +5994,14 @@ RollbackStatement RollbackStatement(): { rollbackStatement = new RollbackStatement(); } [ { rollbackStatement.setUsingWorkKeyword(true); } ] [ ( - [ { rollbackStatement.setUsingSavepointKeyword(true); }] + [ { rollbackStatement.setUsingSavepointKeyword(true); }] token= { rollbackStatement.setSavepointName(token.image); } ) | ( token= { rollbackStatement.setForceDistributedTransactionIdentifier(token.image); } ) ] - + { return rollbackStatement; } diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index 376514ef6..714656b68 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -289,6 +289,67 @@ public void testAlterTableAddColumn6() throws JSQLParserException { assertEquals(col1Exp.hasColumn(), true); } + @Test + public void testAlterTableAddColumnSpanner7() throws JSQLParserException { + final String sql = "ALTER TABLE ORDER_PATIENT ADD COLUMN FIRST_NAME_UPPERCASE STRING(MAX)" + + " AS (UPPER(FIRST_NAME)) STORED"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertStatementCanBeDeparsedAs(stmt, sql); + Alter alter = (Alter) stmt; + List alterExps = alter.getAlterExpressions(); + AlterExpression col1Exp = alterExps.get(0); + assertTrue(col1Exp.getColDataTypeList().get(0).toString().endsWith(" STORED")); + assertTrue(col1Exp.hasColumn()); + } + + @Test + public void testAlterTableAddColumnSpanner8() throws JSQLParserException { + final String sql = "ALTER TABLE ORDER_PATIENT ADD COLUMN NAMES ARRAY"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertStatementCanBeDeparsedAs(stmt, sql); + Alter alter = (Alter) stmt; + List alterExps = alter.getAlterExpressions(); + AlterExpression col1Exp = alterExps.get(0); + assertTrue(col1Exp.hasColumn()); + assertNotNull(col1Exp.getColDataTypeList()); + assertEquals(1, col1Exp.getColDataTypeList().size()); + ColumnDataType type = col1Exp.getColDataTypeList().get(0); + assertEquals("NAMES", type.getColumnName()); + assertEquals("ARRAY", type.getColDataType().toString()); + } + + @Test + public void testAlterColumnSetCommitTimestamp1() throws JSQLParserException { + final String sql = "ALTER TABLE FOCUS_PATIENT ALTER COLUMN UPDATE_DATE_TIME_GMT SET OPTIONS (allow_commit_timestamp=true)"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertStatementCanBeDeparsedAs(stmt, sql); + Alter alter = (Alter) stmt; + List alterExps = alter.getAlterExpressions(); + AlterExpression col1Exp = alterExps.get(0); + assertTrue(col1Exp.hasColumn()); + assertNotNull(col1Exp.getColDataTypeList()); + assertEquals(1, col1Exp.getColDataTypeList().size()); + ColumnDataType type = col1Exp.getColDataTypeList().get(0); + assertEquals("UPDATE_DATE_TIME_GMT", type.getColumnName()); + assertEquals("UPDATE_DATE_TIME_GMT SET OPTIONS (allow_commit_timestamp=true)", type.toString()); + } + + @Test + public void testAlterColumnSetCommitTimestamp2() throws JSQLParserException { + final String sql = "ALTER TABLE FOCUS_PATIENT ALTER COLUMN UPDATE_DATE_TIME_GMT SET OPTIONS (allow_commit_timestamp=null)"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertStatementCanBeDeparsedAs(stmt, sql); + Alter alter = (Alter) stmt; + List alterExps = alter.getAlterExpressions(); + AlterExpression col1Exp = alterExps.get(0); + assertTrue(col1Exp.hasColumn()); + assertNotNull(col1Exp.getColDataTypeList()); + assertEquals(1, col1Exp.getColDataTypeList().size()); + ColumnDataType type = col1Exp.getColDataTypeList().get(0); + assertEquals("UPDATE_DATE_TIME_GMT", type.getColumnName()); + assertEquals("UPDATE_DATE_TIME_GMT SET OPTIONS (allow_commit_timestamp=null)", type.toString()); + } + @Test public void testAlterTableModifyColumn1() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("ALTER TABLE animals MODIFY (col1 integer, col2 number (8, 2))"); @@ -410,7 +471,7 @@ public void testAddConstraintKeyIssue320() throws JSQLParserException { } @Test - public void testIssue633() throws JSQLParserException, JSQLParserException, JSQLParserException { + public void testIssue633() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("ALTER TABLE team_phases ADD CONSTRAINT team_phases_id_key UNIQUE (id)"); } diff --git a/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java b/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java index 8c5dc0648..12f987d6e 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java @@ -64,7 +64,7 @@ public void testCreateTable3() throws JSQLParserException { @Test public void testCreateTableAsSelect() - throws JSQLParserException, JSQLParserException, JSQLParserException, JSQLParserException { + throws JSQLParserException { String statement = "CREATE TABLE a AS SELECT col1, col2 FROM b"; assertSqlCanBeParsedAndDeparsed(statement); } @@ -857,4 +857,37 @@ public void testCreateUnionIssue1309() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( "CREATE TABLE temp.abc AS (SELECT c FROM t1) UNION (SELECT c FROM t2)"); } -} + + @Test + public void testCreateTableSpanner() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "CREATE TABLE COMMAND (\n" + + " DATASET_ID INT64 NOT NULL,\n" + + " COMMAND_ID STRING(MAX) NOT NULL,\n" + + " VAL_BOOL BOOL,\n" + + " VAL_BYTES BYTES(1024),\n" + + " VAL_DATE DATE,\n" + + " VAL_TIMESTAMP TIMESTAMP,\n" + + " VAL_COMMIT_TIMESTAMP TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp = true),\n" + + " VAL_FLOAT64 FLOAT64,\n" + + " VAL_JSON JSON(2048),\n" + + " VAL_NUMERIC NUMERIC,\n" + + " VAL_STRING STRING(MAX),\n" + + " VAL_TIMESTAMP TIMESTAMP,\n" + + " ARR_BOOL ARRAY,\n" + + " ARR_BYTES ARRAY,\n" + + " ARR_DATE ARRAY,\n" + + " ARR_TIMESTAMP ARRAY,\n" + + " ARR_FLOAT64 ARRAY,\n" + + " ARR_JSON ARRAY,\n" + + " ARR_NUMERIC ARRAY,\n" + + " ARR_STRING ARRAY,\n" + + " ARR_TIMESTAMP ARRAY,\n" + + " PAYLOAD STRING(MAX),\n" + + " AUTHOR STRING(MAX) NOT NULL,\n" + + " SEARCH STRING(MAX) AS (UPPER(AUTHOR)) STORED\n" + + " ) PRIMARY KEY ( DATASET_ID, COMMAND_ID )\n" + + ", INTERLEAVE IN PARENT DATASET ON DELETE CASCADE", true); + } + +} \ No newline at end of file