diff --git a/.travis.yml b/.travis.yml index 5652c04cf..581903065 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,10 @@ jdk: - openjdk11 after_success: - - mvn clean cobertura:cobertura coveralls:report \ No newline at end of file + - mvn clean cobertura:cobertura coveralls:report + +cache: + directories: + - $HOME/.m2 + - $HOME/.gradle/caches/ + - $HOME/.gradle/wrapper/ \ No newline at end of file diff --git a/README.md b/README.md index 5cac7869e..024d6addd 100644 --- a/README.md +++ b/README.md @@ -54,9 +54,25 @@ To help JSqlParser's development you are encouraged to provide Also I would like to know about needed examples or documentation stuff. ## Extensions in the latest SNAPSHOT version 4.2 - +* API change: Support `SELECT ...` without a `FROM` clause, making `SELECT 1, 2` and `SELECT *` parsable statements (before those failed) +* API change: Support complex `UPDATE` sets (using multiple `SubQuery` or `ValueList` or Single Values, in combination) +* Support nested `CASE` expressions with complex expression arguments +* API change: Support `JOIN` with multiple trailing `ON` Expressions (`JOIN ... JOIN ... ON ... ON ...`) +* Support Oracle Hierarchical `CONNECT_BY_ROOT` Operator +* Support Transact-SQL `IF ... ELSE ...` Statement Control Flows. +* Allow optional parameters for the `ALTER TABLE ...` statement (e.g. `ALTER TABLE ... MOVE TABLESPACE ...`) +* Support Oracle `ALTER SYSTEM ...` statement +* Support Oracle Named Function Parameters`Func( param1 => arg1, ...` +* Add Gradle build +* Allow `JdbcParameter` or `JdbcNamedParameter` for MySQL FullTextSearch +* Allow `Cast` into `Row` Constructor +* Support Oracle `RENAME ... TO ...` statement +* Support Oracle `PURGE` statement +* Support JSON functions `JSON_OBJECT()`, `JSON_ARRAY()`, `JSON_OBJECTAGG()`, `JSON_ARRAYAGG()` * API change: merge ALL and ANY expressions class -* allow `CURRENT DATE`in addition to `CURRENT_DATE` (without underbar) +* Allow DB2 compliant `CURRENT DATE`in addition to `CURRENT_DATE` (without underscore) + +Additionally, we have fixed many errors and improved the code quality and the test coverage. ## Extensions of JSqlParser releases @@ -67,16 +83,22 @@ Also I would like to know about needed examples or documentation stuff. ## Building from the sources As the project is a Maven project, building is rather simple by running: +```shell +mvn package +``` - mvn package +Since 4.2, alternatively Gradle can be used +```shell +gradle build +``` The project requires the following to build: -- Maven +- Maven (or Gradle) - JDK 8 or later. The jar will target JDK 8, but the version of the maven-compiler-plugin that JsqlParser uses requires JDK 8+ -This will produce the jsqlparser-VERSION.jar file in the target/ directory. +This will produce the jsqlparser-VERSION.jar file in the `target/` directory (`build/libs/jsqlparser-VERSION.jar` in case of Gradle). -**To build this project without using Maven, one has to build the parser by JavaCC using the CLI options it provides.** +**To build this project without using Maven or Gradle, one has to build the parser by JavaCC using the CLI options it provides.** ## Debugging through problems @@ -124,7 +146,7 @@ And this is the dependency declaration in your pom: com.github.jsqlparser jsqlparser - 4.0 + 4.1 ``` diff --git a/build.gradle b/build.gradle index 8bd8e2600..f137150c8 100644 --- a/build.gradle +++ b/build.gradle @@ -73,7 +73,7 @@ jacocoTestCoverageVerification { violationRules { rule { limit { - minimum = 0.837 + minimum = 0.838 } } } diff --git a/src/main/java/net/sf/jsqlparser/statement/update/Update.java b/src/main/java/net/sf/jsqlparser/statement/update/Update.java index 3dcd27059..fbfafd68d 100644 --- a/src/main/java/net/sf/jsqlparser/statement/update/Update.java +++ b/src/main/java/net/sf/jsqlparser/statement/update/Update.java @@ -183,12 +183,12 @@ public void setSelect(Select select) { @Deprecated public boolean isUseColumnsBrackets() { - return updateSets.get(0).usingBrackets; + return updateSets.get(0).usingBracketsForColumns; } @Deprecated public void setUseColumnsBrackets(boolean useColumnsBrackets) { - updateSets.get(0).usingBrackets = useColumnsBrackets; + updateSets.get(0).usingBracketsForColumns = useColumnsBrackets; } @Deprecated @@ -268,7 +268,7 @@ public String toString() { b.append(", "); } - if (updateSet.usingBrackets) { + if (updateSet.usingBracketsForColumns) { b.append("("); } @@ -279,46 +279,28 @@ public String toString() { b.append(updateSet.columns.get(i)); } - if (updateSet.usingBrackets) { + if (updateSet.usingBracketsForColumns) { b.append(")"); } b.append(" = "); + if (updateSet.usingBracketsForValues) { + b.append("("); + } + for (int i = 0; i < updateSet.expressions.size(); i++) { if (i > 0) { b.append(", "); } b.append(updateSet.expressions.get(i)); } + if (updateSet.usingBracketsForValues) { + b.append(")"); + } j++; } - -// if (!useSelect) { -// for (int i = 0; i < getColumns().size(); i++) { -// if (i != 0) { -// b.append(", "); -// } -// b.append(columns.get(i)).append(" = "); -// b.append(expressions.get(i)); -// } -// } else { -// if (useColumnsBrackets) { -// b.append("("); -// } -// for (int i = 0; i < getColumns().size(); i++) { -// if (i != 0) { -// b.append(", "); -// } -// b.append(columns.get(i)); -// } -// if (useColumnsBrackets) { -// b.append(")"); -// } -// b.append(" = "); -// b.append("(").append(select).append(")"); -// } if (fromItem != null) { b.append(" FROM ").append(fromItem); if (joins != null) { diff --git a/src/main/java/net/sf/jsqlparser/statement/update/UpdateSet.java b/src/main/java/net/sf/jsqlparser/statement/update/UpdateSet.java index 4426b87f8..3e6da1ba1 100644 --- a/src/main/java/net/sf/jsqlparser/statement/update/UpdateSet.java +++ b/src/main/java/net/sf/jsqlparser/statement/update/UpdateSet.java @@ -17,7 +17,8 @@ import java.util.Objects; public class UpdateSet { - protected boolean usingBrackets = false; + protected boolean usingBracketsForColumns = false; + protected boolean usingBracketsForValues = false; protected ArrayList columns = new ArrayList<>(); protected ArrayList expressions = new ArrayList<>(); @@ -34,12 +35,20 @@ public UpdateSet(Column column, Expression expression) { this.expressions.add(expression); } - public boolean isUsingBrackets() { - return usingBrackets; + public boolean isUsingBracketsForValues() { + return usingBracketsForValues; } - public void setUsingBrackets(boolean usingBrackets) { - this.usingBrackets = usingBrackets; + public void setUsingBracketsForValues(boolean usingBracketsForValues) { + this.usingBracketsForValues = usingBracketsForValues; + } + + public boolean isUsingBracketsForColumns() { + return usingBracketsForColumns; + } + + public void setUsingBracketsForColumns(boolean usingBracketsForColumns) { + this.usingBracketsForColumns = usingBracketsForColumns; } public ArrayList getColumns() { @@ -61,13 +70,18 @@ public void setExpressions(ArrayList expressions) { public void add(Column column, Expression expression) { columns.add(column); expressions.add(expression); - }; + } public void add(Column column) { columns.add(column); - }; + } + + public void add(Expression expression) { + expressions.add(expression); + } public void add(ExpressionList expressionList) { expressions.addAll(expressionList.getExpressions()); - }; + } + } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java index 01851ef5f..fdd168391 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java @@ -66,7 +66,7 @@ public void deParse(Update update) { buffer.append(", "); } - if (updateSet.isUsingBrackets()) { + if (updateSet.isUsingBracketsForColumns()) { buffer.append("("); } for (int i = 0; i < updateSet.getColumns().size(); i++) { @@ -75,56 +75,27 @@ public void deParse(Update update) { } updateSet.getColumns().get(i).accept(expressionVisitor); } - if (updateSet.isUsingBrackets()) { + if (updateSet.isUsingBracketsForColumns()) { buffer.append(")"); } buffer.append(" = "); + if (updateSet.isUsingBracketsForValues()) { + buffer.append("("); + } for (int i = 0; i < updateSet.getExpressions().size(); i++) { if (i > 0) { buffer.append(", "); } updateSet.getExpressions().get(i).accept(expressionVisitor); } + if (updateSet.isUsingBracketsForValues()) { + buffer.append(")"); + } j++; } - -// if (!update.isUseSelect()) { -// for (int i = 0; i < update.getColumns().size(); i++) { -// Column column = update.getColumns().get(i); -// column.accept(expressionVisitor); -// -// buffer.append(" = "); -// -// Expression expression = update.getExpressions().get(i); -// expression.accept(expressionVisitor); -// if (i < update.getColumns().size() - 1) { -// buffer.append(", "); -// } -// } -// } else { -// if (update.isUseColumnsBrackets()) { -// buffer.append("("); -// } -// for (int i = 0; i < update.getColumns().size(); i++) { -// if (i != 0) { -// buffer.append(", "); -// } -// Column column = update.getColumns().get(i); -// column.accept(expressionVisitor); -// } -// if (update.isUseColumnsBrackets()) { -// buffer.append(")"); -// } -// buffer.append(" = "); -// buffer.append("("); -// Select select = update.getSelect(); -// select.getSelectBody().accept(selectVisitor); -// buffer.append(")"); -// } - if (update.getFromItem() != null) { buffer.append(" FROM ").append(update.getFromItem()); if (update.getJoins() != null) { diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index caa931d61..ec23fa8ee 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -1114,6 +1114,7 @@ Update Update( List with ): UpdateSet updateSet = null; Column tableColumn = null; + SubSelect subSelect; Expression valueExpression = null; ExpressionList expressionList; Expression where = null; @@ -1130,31 +1131,44 @@ Update Update( List with ): ( - LOOKAHEAD(3) ( - tableColumn=Column() "=" valueExpression=SimpleExpression() { update.addUpdateSet(tableColumn, valueExpression); } - ("," tableColumn=Column() "=" valueExpression=SimpleExpression() { update.addUpdateSet(tableColumn, valueExpression); } )* - ) + LOOKAHEAD(3) tableColumn=Column() "=" valueExpression=SimpleExpression() { update.addUpdateSet(tableColumn, valueExpression); } + ("," tableColumn=Column() "=" valueExpression=SimpleExpression() { update.addUpdateSet(tableColumn, valueExpression); } )* | ( { updateSet = new UpdateSet(); update.addUpdateSet(updateSet); } - [ "(" { updateSet.setUsingBrackets(true); } ] + [ LOOKAHEAD(2) "(" { updateSet.setUsingBracketsForColumns(true); } ] tableColumn=Column() { updateSet.add(tableColumn); } - ("," tableColumn=Column() { updateSet.add(tableColumn); } )* - [ ")" ] + ( LOOKAHEAD(2) "," tableColumn=Column() { updateSet.add(tableColumn); } )* + [ LOOKAHEAD(2) ")" ] "=" - expressionList = ComplexExpressionList() { updateSet.add(expressionList); } ( - "," - tableColumn=Column() { updateSet = new UpdateSet(tableColumn); update.addUpdateSet(updateSet); } - ("," tableColumn=Column() { updateSet.add(tableColumn); } )* + LOOKAHEAD(3) subSelect=SubSelect() { updateSet.add(subSelect.withUseBrackets(false)); } + | + LOOKAHEAD(3) "(" expressionList = ComplexExpressionList() { updateSet.setUsingBracketsForValues(true); updateSet.add(expressionList); } ")" + | + valueExpression = Expression() { updateSet.add(valueExpression); } + ) + + ( + "," { updateSet = new UpdateSet(); update.addUpdateSet(updateSet); } + + [ LOOKAHEAD(2) "(" { updateSet.setUsingBracketsForColumns(true); } ] + tableColumn=Column() { updateSet.add(tableColumn); } + ( LOOKAHEAD(2) "," tableColumn=Column() { updateSet.add(tableColumn); } )* + [ LOOKAHEAD(2) ")" ] "=" - "(" - expressionList = ComplexExpressionList() { updateSet.add(expressionList); } - ")" + + ( + LOOKAHEAD(3) subSelect=SubSelect() { updateSet.add(subSelect.withUseBrackets(false)); } + | + LOOKAHEAD(3) "(" expressionList = ComplexExpressionList() { updateSet.setUsingBracketsForValues(true); updateSet.add(expressionList); } ")" + | + valueExpression = Expression() { updateSet.add(valueExpression); } + ) ) * ) ) @@ -1815,12 +1829,12 @@ PlainSelect PlainSelect() #PlainSelect: selectItems=SelectItemsList() [intoTables = IntoClause() { plainSelect.setIntoTables(intoTables); } ] - [ + [ LOOKAHEAD(2) fromItem=FromItem() joins=JoinsList() ] [ ksqlWindow=KSQLWindowClause() { plainSelect.setKsqlWindow(ksqlWindow); } ] - [ where=WhereClause() { plainSelect.setWhere(where); }] + [ LOOKAHEAD(2) where=WhereClause() { plainSelect.setWhere(where); }] [ oracleHierarchicalQueryClause=OracleHierarchicalQueryClause() { plainSelect.setOracleHierarchical(oracleHierarchicalQueryClause); } ] [ groupBy=GroupByColumnReferences() { plainSelect.setGroupByElement(groupBy); }] [ having=Having() { plainSelect.setHaving(having); }] @@ -1877,7 +1891,7 @@ SelectBody SetOperationList() #SetOperationList: { )* - [orderByElements=OrderByElements() {list.setOrderByElements(orderByElements);} ] + [ LOOKAHEAD(2) orderByElements=OrderByElements() {list.setOrderByElements(orderByElements);} ] [LOOKAHEAD() limit=LimitWithOffset() {list.setLimit(limit);} ] [LOOKAHEAD() offset = Offset() { list.setOffset(offset);} ] [LOOKAHEAD() fetch = Fetch() { list.setFetch(fetch);} ] @@ -1992,7 +2006,7 @@ List SelectItemsList(): SelectItem selectItem = null; } { - selectItem=SelectItem() { selectItemsList.add(selectItem); } ("," selectItem=SelectItem() { selectItemsList.add(selectItem); } )* + selectItem=SelectItem() { selectItemsList.add(selectItem); } ( LOOKAHEAD(2) "," selectItem=SelectItem() { selectItemsList.add(selectItem); } )* { return selectItemsList; } } @@ -2280,7 +2294,7 @@ List IntoClause(): Table table; } { - table=Table() { tables.add(table); } ("," table=Table() { tables.add(table); } )* + table=Table() { tables.add(table); } ( LOOKAHEAD(2) "," table=Table() { tables.add(table); } )* { return tables; } @@ -2432,7 +2446,7 @@ List JoinsList(): Join join = null; } { - (join=JoinerExpression() { joinsList.add(join); })* + ( LOOKAHEAD(2) join=JoinerExpression() { joinsList.add(join); })* { return joinsList; } } @@ -2655,7 +2669,7 @@ List OrderByElements(): } { [ ] orderByElement=OrderByElement() { orderByList.add(orderByElement); } - ("," orderByElement=OrderByElement() { orderByList.add(orderByElement); } )* + ( LOOKAHEAD(2) "," orderByElement=OrderByElement() { orderByList.add(orderByElement); } )* { return orderByList; } @@ -4959,7 +4973,7 @@ CreateTable CreateTable(): // see https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_7002.htm#i2126725 // table properties , all these are optional [ rowMovement = RowMovement() { createTable.setRowMovement(rowMovement); }] - [ select = SelectWithWithItems( ) { createTable.setSelect(select, false); }] + [ select = SelectWithWithItems( ) { createTable.setSelect(select, fa [ ( LOOKAHEAD("(" Table() ")") "(" likeTable=Table() { createTable.setLikeTable(likeTable, true); } ")" | likeTable=Table() { createTable.setLikeTable(likeTable, false); } ) diff --git a/src/test/java/net/sf/jsqlparser/statement/ExplainTest.java b/src/test/java/net/sf/jsqlparser/statement/ExplainTest.java index f146f239b..3239a6780 100644 --- a/src/test/java/net/sf/jsqlparser/statement/ExplainTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/ExplainTest.java @@ -65,5 +65,8 @@ public void getOption_returnsValues() throws JSQLParserException { ExplainStatement.Option buffers = explain.getOption(ExplainStatement.OptionType.BUFFERS); assertThat(buffers).isNotNull().extracting(ExplainStatement.Option::getValue).isEqualTo("FALSE"); + + explain = (ExplainStatement) CCJSqlParserUtil.parse("EXPLAIN SELECT * FROM mytable"); + assertThat(explain.getOption(ExplainStatement.OptionType.ANALYZE)).isNull(); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/IfElseStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/IfElseStatementTest.java index ff71a2f4e..a2aa90e6f 100644 --- a/src/test/java/net/sf/jsqlparser/statement/IfElseStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/IfElseStatementTest.java @@ -82,7 +82,7 @@ public void testObjectBuilder() throws JSQLParserException { } @Test - public void testValidation() throws JSQLParserException { + public void testValidation() { String sqlStr = "IF OBJECT_ID('tOrigin', 'U') IS NOT NULL DROP TABLE tOrigin1;"; List errors = Validation.validate(Arrays.asList(DatabaseType.SQLSERVER, FeaturesAllowed.DROP), sqlStr); diff --git a/src/test/java/net/sf/jsqlparser/statement/ResetStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/ResetStatementTest.java index e64c709bd..745348d41 100644 --- a/src/test/java/net/sf/jsqlparser/statement/ResetStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/ResetStatementTest.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.statement; import net.sf.jsqlparser.JSQLParserException; +import org.junit.Assert; import org.junit.Test; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; @@ -25,4 +26,14 @@ public void tesResetAll() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("RESET ALL"); } + @Test + public void testObject() { + ResetStatement resetStatement=new ResetStatement(); + Assert.assertNotNull(resetStatement.getName()); + + resetStatement.add("something"); + resetStatement.setName("somethingElse"); + Assert.assertEquals("somethingElse", resetStatement.getName()); + } + } diff --git a/src/test/java/net/sf/jsqlparser/statement/RollbackStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/RollbackStatementTest.java new file mode 100644 index 000000000..5d72bd0d1 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/statement/RollbackStatementTest.java @@ -0,0 +1,30 @@ +/*- + * #%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.statement; + +import org.junit.Assert; +import org.junit.Test; + +public class RollbackStatementTest { + + @Test + public void testObject() { + RollbackStatement rollbackStatement = new RollbackStatement() + .withUsingWorkKeyword(true) + .withUsingSavepointKeyword(true) + .withSavepointName("mySavePoint") + .withForceDistributedTransactionIdentifier("$ForceDistributedTransactionIdentifier"); + + Assert.assertTrue(rollbackStatement.isUsingSavepointKeyword()); + Assert.assertEquals("mySavePoint", rollbackStatement.getSavepointName()); + Assert.assertEquals("$ForceDistributedTransactionIdentifier", rollbackStatement.getForceDistributedTransactionIdentifier()); + } + +} diff --git a/src/test/java/net/sf/jsqlparser/statement/SetStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/SetStatementTest.java index c99220e37..bf55cd34f 100644 --- a/src/test/java/net/sf/jsqlparser/statement/SetStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/SetStatementTest.java @@ -11,8 +11,13 @@ import net.sf.jsqlparser.JSQLParserException; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; + +import net.sf.jsqlparser.expression.StringValue; +import org.junit.Assert; import org.junit.Test; +import java.util.Collections; + /** * * @author toben @@ -57,4 +62,13 @@ public void tesLocalWithEq() throws JSQLParserException { public void testValueOnIssue927() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("SET standard_conforming_strings = on"); } + + @Test + public void testObject() { + SetStatement setStatement = new SetStatement(); + setStatement.add("standard_conforming_strings", Collections.singletonList(new StringValue("ON")), false); + setStatement.withUseEqual(0, true).remove(0); + + Assert.assertEquals(0, setStatement.getCount()); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/StatementsTest.java b/src/test/java/net/sf/jsqlparser/statement/StatementsTest.java index 5ae82d230..4f8529e6b 100644 --- a/src/test/java/net/sf/jsqlparser/statement/StatementsTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/StatementsTest.java @@ -67,7 +67,10 @@ public void testStatementsProblem() throws JSQLParserException { @Test public void testStatementsErrorRecovery() throws JSQLParserException, ParseException { - String sqls = "select * from mytable; select * from;"; + // "SELECT *" and "SELECT 1,2" are valid statements and so would return a correct SELECT object + // String sqls = "select * from mytable; select * from;"; + String sqls = "select * from mytable; select from;"; + CCJSqlParser parser = new CCJSqlParser(new StringProvider(sqls)); parser.setErrorRecovery(true); Statements parseStatements = parser.Statements(); @@ -75,6 +78,7 @@ public void testStatementsErrorRecovery() throws JSQLParserException, ParseExcep assertEquals(2, parseStatements.getStatements().size()); assertTrue(parseStatements.getStatements().get(0) instanceof Select); + assertNull(parseStatements.getStatements().get(1)); } @@ -93,7 +97,10 @@ public void testStatementsErrorRecovery2() throws JSQLParserException, ParseExce @Test public void testStatementsErrorRecovery3() throws JSQLParserException, ParseException { - String sqls = "select * from mytable; select * from;select * from mytable2"; + // "SELECT *" and "SELECT 1, 2" are valid SELECT statements + // String sqls = "select * from mytable; select * from;select * from mytable2"; + String sqls = "select * from mytable; select from;select * from mytable2"; + CCJSqlParser parser = new CCJSqlParser(new StringProvider(sqls)); parser.setErrorRecovery(true); Statements parseStatements = parser.Statements(); diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterSessionTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterSessionTest.java index 7b61b4a07..6ca0fd408 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterSessionTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterSessionTest.java @@ -11,8 +11,12 @@ import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.test.TestUtils; +import org.junit.Assert; import org.junit.Test; +import java.util.Arrays; +import java.util.Collections; + public class AlterSessionTest { @Test public void testAlterSessionAdvise() throws JSQLParserException { @@ -64,4 +68,25 @@ public void testAlterSessionSet() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION SET ddl_lock_timeout=7200", true); TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION SET ddl_lock_timeout = 7200", true); } + + + @Test + public void testAlterSessionResumable() throws JSQLParserException { + TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION ENABLE RESUMABLE", true); + TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION DISABLE RESUMABLE", true); + } + + @Test + public void testObject() { + AlterSession alterSession = new AlterSession(AlterSessionOperation.FORCE_PARALLEL_QUERY, Collections.emptyList()); + Assert.assertEquals(AlterSessionOperation.FORCE_PARALLEL_QUERY, alterSession.getOperation()); + + alterSession.setOperation(AlterSessionOperation.DISABLE_PARALLEL_DML); + Assert.assertEquals(AlterSessionOperation.DISABLE_PARALLEL_DML, alterSession.getOperation()); + + Assert.assertEquals(0, alterSession.getParameters().size()); + + alterSession.setParameters(Arrays.asList("PARALLEL", "6")); + Assert.assertEquals(2, alterSession.getParameters().size()); + } } 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 5a8bb365b..07a176db2 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java @@ -845,4 +845,10 @@ public void testCreateTableIssue1230() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( "CREATE TABLE TABLE_HISTORY (ID bigint generated by default as identity, CREATED_AT timestamp not null, TEXT varchar (255), primary key (ID))"); } + + @Test + public void testCreateUnionIssue1309() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "CREATE TABLE temp.abc AS (SELECT c FROM t1) UNION (SELECT c FROM t2)"); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/create/synonym/CreateSynonymTest.java b/src/test/java/net/sf/jsqlparser/statement/create/synonym/CreateSynonymTest.java index 74ad5248f..0f3641bd2 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/synonym/CreateSynonymTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/synonym/CreateSynonymTest.java @@ -11,7 +11,9 @@ import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.schema.Synonym; import org.assertj.core.api.Assertions; +import org.junit.Assert; import org.junit.Test; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; @@ -51,5 +53,8 @@ public void synonymAttributes() throws Exception { Assertions.assertThat(createSynonym.isPublicSynonym()).isTrue(); Assertions.assertThat(createSynonym.getSynonym().getFullyQualifiedName()).isEqualTo("TBL_TABLE_NAME"); Assertions.assertThat(createSynonym.getFor()).isEqualTo("SCHEMA.T_TBL_NAME"); + + Assert.assertEquals(2, createSynonym.getForList().size()); + Assert.assertEquals("NEW_TBL_TABLE_NAME", createSynonym.withSynonym(new Synonym().withName("NEW_TBL_TABLE_NAME")).getSynonym().getName()); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/show/ShowTablesStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/show/ShowTablesStatementTest.java index 535759351..e280cb000 100644 --- a/src/test/java/net/sf/jsqlparser/statement/show/ShowTablesStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/show/ShowTablesStatementTest.java @@ -9,6 +9,10 @@ */ package net.sf.jsqlparser.statement.show; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.Assert; import org.junit.Test; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; @@ -44,4 +48,18 @@ public void showTablesLikeExpression() throws Exception { public void showTablesWhereExpression() throws Exception { assertSqlCanBeParsedAndDeparsed("SHOW TABLES WHERE table_name = 'FOO'"); } + + @Test + public void testObject() throws JSQLParserException, JSQLParserException { + ShowTablesStatement showTablesStatement = (ShowTablesStatement) CCJSqlParserUtil.parse("SHOW TABLES WHERE table_name = 'FOO'"); + Assert.assertEquals(0, showTablesStatement.getModifiers().size()); + TestUtils.assertExpressionCanBeDeparsedAs(showTablesStatement.getWhereCondition(), "table_name = 'FOO'"); + + showTablesStatement = (ShowTablesStatement) CCJSqlParserUtil.parse("SHOW FULL TABLES IN db_name"); + Assert.assertEquals(1, showTablesStatement.getModifiers().size()); + Assert.assertEquals(ShowTablesStatement.SelectionMode.IN, showTablesStatement.getSelectionMode()); + + showTablesStatement = (ShowTablesStatement) CCJSqlParserUtil.parse("SHOW TABLES LIKE '%FOO%'"); + TestUtils.assertExpressionCanBeDeparsedAs(showTablesStatement.getLikeExpression(), "'%FOO%'"); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java b/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java index 565cd493a..8476b9bb1 100644 --- a/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java @@ -20,6 +20,9 @@ import static net.sf.jsqlparser.test.TestUtils.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; + +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import org.junit.Assert; import org.junit.Test; public class UpdateTest { @@ -191,44 +194,58 @@ public void testWith() throws JSQLParserException { @Test public void testUpdateSetsIssue1316() throws JSQLParserException { - String statement = + String sqlStr = "update test\n" + "set (a, b) = (select '1', '2')"; - assertSqlCanBeParsedAndDeparsed(statement, true); + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = + "update test\n" + + "set a = '1'" + + " , b = '2'"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); - statement = + sqlStr = "update test\n" + "set (a, b) = ('1', '2')"; - assertSqlCanBeParsedAndDeparsed(statement, true); + assertSqlCanBeParsedAndDeparsed(sqlStr, true); - statement = + sqlStr = "update test\n" + - "set (a, b) = values ('1', '2')"; - assertSqlCanBeParsedAndDeparsed(statement, true); + "set (a, b) = (values ('1', '2'))"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); - statement = + sqlStr = "update test\n" + "set (a, b) = (1, (select 2))"; - assertSqlCanBeParsedAndDeparsed(statement, true); - - statement = - "UPDATE\n" + - "prpjpaymentbill b\n" + - "SET\n" + - "(\n" + - "b.packagecode,\n" + - "b.packageremark,\n" + - "b.agentcode\n" + - ") =\n" + - "(SELECT\n" + - "p.payrefreason,\n" + - "p.classcode,\n" + - "p.riskcode\n" + - "FROM\n" + - "prpjcommbill p where p.policertiid='SDDH200937010330006366' ),\n" + - "b.payrefnotype = '05',\n" + - "b.packageunit = '4101170402'\n" + - "where b.payrefno='B370202091026000005' "; - assertSqlCanBeParsedAndDeparsed(statement, true); + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = + "UPDATE prpjpaymentbill b\n" + + "SET ( b.packagecode\n" + + " , b.packageremark\n" + + " , b.agentcode ) = ( SELECT p.payrefreason\n" + + " , p.classcode\n" + + " , p.riskcode\n" + + " FROM prpjcommbill p\n" + + " WHERE p.policertiid = 'SDDH200937010330006366' ) -- this is supposed to be UpdateSet 1\n" + + " , b.payrefnotype = '05' -- this is supposed to be UpdateSet 2\n" + + " , b.packageunit = '4101170402' -- this is supposed to be UpdateSet 3\n" + + "WHERE b.payrefno = 'B370202091026000005'"; + + + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + Update update = (Update) CCJSqlParserUtil.parse(sqlStr); + Assert.assertEquals(3, update.getUpdateSets().size()); + + Assert.assertEquals(3, update.getUpdateSets().get(0).getColumns().size()); + Assert.assertEquals(1, update.getUpdateSets().get(0).getExpressions().size()); + + Assert.assertEquals(1, update.getUpdateSets().get(1).getColumns().size()); + Assert.assertEquals(1, update.getUpdateSets().get(1).getExpressions().size()); + + Assert.assertEquals(1, update.getUpdateSets().get(2).getColumns().size()); + Assert.assertEquals(1, update.getUpdateSets().get(2).getExpressions().size()); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/values/ValuesTest.java b/src/test/java/net/sf/jsqlparser/statement/values/ValuesTest.java index aa32bc543..46d71a1bc 100644 --- a/src/test/java/net/sf/jsqlparser/statement/values/ValuesTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/values/ValuesTest.java @@ -15,6 +15,7 @@ import net.sf.jsqlparser.expression.StringValue; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.statement.Statement; +import net.sf.jsqlparser.statement.StatementVisitorAdapter; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.select.SetOperationList; @@ -22,6 +23,8 @@ import org.junit.Test; +import java.util.Arrays; + public class ValuesTest { @Test @@ -48,4 +51,12 @@ public void testDuplicateKey() throws JSQLParserException { public void testComplexWithQueryIssue561() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("WITH split (word, str, hascomma) AS (VALUES ('', 'Auto,A,1234444', 1) UNION ALL SELECT substr(str, 0, CASE WHEN instr(str, ',') THEN instr(str, ',') ELSE length(str) + 1 END), ltrim(substr(str, instr(str, ',')), ','), instr(str, ',') FROM split WHERE hascomma) SELECT trim(word) FROM split WHERE word != ''"); } + + @Test + public void testObject() { + ValuesStatement valuesStatement=new ValuesStatement().addExpressions(new StringValue("1"), new StringValue("2")); + valuesStatement.addExpressions(Arrays.asList(new StringValue("3"), new StringValue("4"))); + + valuesStatement.accept(new StatementVisitorAdapter()); + } } diff --git a/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java b/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java index bc8e2954d..ee5e5e408 100644 --- a/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java +++ b/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java @@ -16,6 +16,7 @@ import java.util.ArrayList; import java.util.List; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.statement.update.UpdateSet; import org.junit.Before; import org.junit.Test; @@ -31,7 +32,6 @@ import net.sf.jsqlparser.statement.IfElseStatement; import net.sf.jsqlparser.statement.SetStatement; import net.sf.jsqlparser.statement.delete.Delete; -import net.sf.jsqlparser.statement.drop.Drop; import net.sf.jsqlparser.statement.execute.Execute; import net.sf.jsqlparser.statement.insert.Insert; import net.sf.jsqlparser.statement.replace.Replace; @@ -368,12 +368,9 @@ public void shouldUseProvidedDeparsersWhenDeParsingUpsertWithExpressionList() th @Test @SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") - public void shouldUseProvidedDeparsersWhenDeParsingIfThenStatement() { - Expression condition = mock(Expression.class); - Drop ifStatement = mock(Drop.class); - - IfElseStatement ifElseStatement = new IfElseStatement(condition, ifStatement); - + public void shouldUseProvidedDeparsersWhenDeParsingIfThenStatement() throws JSQLParserException { + String sqlStr = "IF OBJECT_ID('tOrigin', 'U') IS NOT NULL DROP TABLE tOrigin1"; + IfElseStatement ifElseStatement = (IfElseStatement) CCJSqlParserUtil.parse(sqlStr); statementDeParser.deParse(ifElseStatement); }