From 41b6fce5ba553cb93af6f28e3212dbffa905c1e6 Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Thu, 1 Jun 2023 09:36:37 +0700 Subject: [PATCH] JSQLParser 5.0 (#1778) * Fixes #1684: Support CREATE MATERIALIZED VIEW with AUTO REFRESH Support parsing create view statements in Redshift with AUTO REFRESH option. * Reduce cyclomatic complexity in CreateView.toString Extract adding the force option into a dedicated method resulting in the cyclomatic complexity reduction of the CreateView.toString method. * Enhanced Keywords Add Keywords and document, which keywords are allowed for what purpose * Fix incorrect tests * Define Reserved Keywords explicitly Derive All Keywords from Grammar directly Generate production for Object Names (semi-) automatically Add parametrized Keyword Tests * Fix test resources * Adjust Gradle to JUnit 5 Parallel Test execution Gradle Caching Explicitly request for latest JavaCC 7.0.10 * Do not mark SpeedTest for concurrent execution * Remove unused imports * Adjust Gradle to JUnit 5 Parallel Test execution Gradle Caching Explicitly request for latest JavaCC 7.0.10 * Do not mark SpeedTest for concurrent execution * Remove unused imports * Sphinx Documentation Update the MANTICORE Sphinx Theme, but ignore it in GIT Add the content to the Sphinx sites Add a Gradle function to derive Stable and Snapshot version from GIT Tags Add a Gradle GIT change task Add a Gradle sphinx task Add a special Test case for illustrating the use of JSQLParser * doc: request for `Conventional Commit` messages * feat: make important Classes Serializable Implement Serializable for persisting via ObjectOutputStream * chore: Make Serializable * doc: Better integration of the RR diagrams - apply neutral Sphinx theme - insert the RR diagrams into the sphinx sources - better documentation on Gradle dependencies - link GitHub repository * Merge * feat: Oracle Alternative Quoting - add support for Oracle Alternative Quoting e.g. `q'(...)'` - fixes #1718 - add a Logo and FavIcon to the Website - document recent changes on Quoting/Escaping - add an example on building SQL from Java - rework the README.md, promote the Website - add Spotless Formatter, using Google Java Style (with Tab=4 Spaces) * style: Appease PMD/Codacy * doc: fix the issue template - fix the issue template - fix the -SNAPSHOT version number * Update issue templates * Update issue templates * feat: Support more Statement Separators - `GO` - Slash `/` - Two empty lines * feat: FETCH uses EXPRESSION - `FETCH` uses `EXPRESSION` instead of SimpleJDBCParameter only - Visit/Accept `FETCH` `EXPRESSION` instead of `append` to String - Visit/Accept `OFFSET` `EXPRESSION` instead of `append` to String - Gradle: remove obsolete/incompatible `jvmArgs` from Test() * style: apply Spotless * test: commit missing test * feat: Lateral View Implement Lateral View according to https://spark.apache.org/docs/latest/sql-ref-syntax-qry-select-lateral-view.html#syntax Add proper tests Fixes #1777 Fixes #239 Fixes #1723 * feat: Oracle `HAVING` before `GROUP BY` Basic support for Oracle's `HAVING` before `GROUP BY` option. It will be parsed without any special consideration for the order. Special Oracle Test groupby07.sql gets parsed, but fails when the deparser reorders the clauses. Fixes #1774 * feat: Multi-Part Names for Variables and Parameters Fixes #1771 Fixes #1768 * feat: ClickHouse `Select...` ``FINAL` modifier Fixes #1774 BREAKING-CHANGE: introduces reserved keyword `FINAL` * feat: Test if a JOIN is an INNER JOIN according to the SQL:2016 An `INNER JOIN` is a qualified `JOIN` with the `INNER` qualifier or without any `LEFT` or `RIGHT` qualifier. Fixes #1775 * feat: Switch off contradicting `JOIN` qualifiers, when setting a qualifier * feat: implement SQL:2016 Convert() and Trim() - Fixes #868 - Fixes #1767 - Fixes Special Oracle Test `function03.sql` * feat: ClickHouse `LIMIT ... BY ...` clause - LimitDeparser accepts ExpressionVisitor - `SELECT` can have optional `LIMIT ... BY ...` clause - Fixes #1436 * test: add specific tests for closed issues * test: add specific tests for closed issues * refactor: remove `SelectExpressionItem` in favor of `SelectItem` BREAKING-CHANGE: `SelectExpressionItem` removed * doc: Update examples * build: Add missing import * doc: Update the README.md * fix: assign Enum case insensitive Fixes #1779 * fix: assign Enum case insensitive Remove redundant `DateTime` enum Fixes #1779 * Revert "fix: assign Enum case insensitive" This reverts commit 86d0acef86f72a8c1226a2f330a580993232c33f. * feat: Consolidate the `ExpressionList`, removing many redundant List alike Classes and Productions - `ExpressionList` extends a `List` directly and implements `Expression` - `ExpressionList` has no Brackets - introduce `ParenthesedExpressionList` which extends `ExpressionList` and has Brackets - refactor `MultiExpressionList` to extend `List` - replace any occurrence of `List` with `ExpressionList` and remove lots of redundant Productions - `RowConstructor` extends `ExpressionList` - remove redundant `ValueExpressionList` (it was just an `ExpressionList` - get rid of any `useBrackets` flags - consolidate the `Cast` Functions - use `ExpressionListDeparser` as much as possible BREAKING-CHANGE: All `List` and `List` related methods have changed. No `useBrackets` flags, instead use `ParenthesedExpressionList` when brackets are needed. * fix: Remove tests for `()`, since `ParenthesedExpressionList` will catch those too * refactor: UpdateSets for `Update` and `InsertConflictTarget` - remove redundant code - add license headers - register `function06.sql` success * build: Increase TimeOut for the GitHub CI * style: Appease Codacy * style: Checkstyle * refactor: Remove `ItemsList`, `MultiExpressionList`, `Replace` Since we have proper `ExpressionList` implementing `Expression` we can narrow down the API: - remove `ItemsList`, `ItemsListVisitor`, `ItemsListValidator` in favor of `ExpressionList` - remove `MultiExpressionList` in favor of `ExpressionList` - refactor `NamedExpressionList` so it extends `ExpressionList` and uses `ExpressionListDeparser` - simplify `InExpression` and `AnyComparisionExpression` BREAKING-CHANGE: many Classes and Methods removed * style: Appease Codacy * style: Rework all the ENUMs - assign Value only when really needed - implement `from()` method for getting the case-insensitive Enum * doc: Better Sphinx Tabs Addresses issue #1784 item 2 * doc: RR chart colors cater for Dark Mode Addresses issue #1784 item 3 * refactor: remove SimpleFunction Remove the production `SimpleFunction` Clean-up `InternalFunction` * build: improve Gradle Build - fix Version/Snapshot - add XML Doclet (for generating API Website via XSLT later) - fix the publishing task and add GitHub package * refactor: `Insert` uses `ExpressionList` and `UpdateSet` * test: Disable API Sanitation for the moment * style: Appease Checkstyle * style: Appease PMD * fix: find the correct position when field belongs to an internal class * style: replace all List with ExpressionList<> and enforce policy via Acceptance Test - refactor `Merge`, use `ExpressionList`, `UpdateSet` and Visitor Pattern - refactor `Upsert`, use `ExpressionList`, `UpdateSet` and Visitor Pattern - refactor `Set` Statement - refactor `Limit`, `Pivot`, `Unpivot` ** Breaking Changes ** Getters/Setters of `Merge`, `Upsert`, `Set` have changed * refactor: generify `SelectItem` and remove `FunctionItem` and `ExpressionListItem` - generify `SelectItem` - replace `FunctionItem` with `SelectItem` - replace `ExpressionListItem` with `SelectItem` - appease PMD/Codacy ** Breaking Changes ** Getters/Setters of `Pivot`, `UnPivot`, `PivotXML` have changed * fix: Java Version 8 * feat: JdbcNamedParameter allows "&" (instead of ":") - fixes #1785 * feat: access Elements of Array Columns - Example `update utilisateur set listes[0] = 1` - fixes #1083 * feat: `MEMBER OF` condition as shown at https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_member-of - fixes #1631 * style: appease PMD/Codacy * style: appease PMD/Codacy * test: add unit test for issue #1778 * feat: Write API documentation to the WebSite via XMLDoclet * Update sphinx.yml * build: Sphinx build fixes * build: Sphinx build fixes * build: Sphinx build fixes * build: improve the GIT Snapshot detection * fix: issue #1791 - Allow `START` keyword as table `CreateParameter` * fix: issue #1789 - allow `CREATE TABLE ...` column parameter with Postgres`nextval('public.actor_actor_id_seq'::regclass)` * fix: issue #1789 - allow `CREATE TABLE ...` column parameter with Postgres`nextval('public.actor_actor_id_seq'::regclass)` * refactor: simplify production `CreateParameter()` * refactor: SHOW statement, supporting any RDBMS specific implementation - returns any RDBMS specific implementation as `UnsupportedStatement` - fixes #1702 * refactor: RETURNING clause - supports Oracle's `RETURN ... INTO ...` - fixes #1780 - fixes #686 - Special Oracle tests `insert11.sql` and `insert12.sql` * refactor: CREATE and ALTER productions - avoid LOOKAHEADs - simplify the SimpleStatement() production - use UnsupportedStatements() for any RDBMS specific syntax - fixes #1515 - fixes #1453 * fix: Complex Parsing Approach - optionally provide a global Executor, instead spawning one for each parse - run into Complex Parsing only, when Complex Parsing was allowed - provide a Logger - fixes #1792 * style: Quieten the logger * style: Cosmetic improvements * feat: chaining JSON Expressions - supports chains like '{"obj":{"field": "value"}}'::JSON -> 'obj'::TEXT ->> 'field'::TEXT - fixes #1792 * style: remove unused imports * refact: Statements extends List * build: try to work around the Maven/JDK8 issue on GitHub * feat: parse CREATE TRIGGER as UnsupportedStatement - fixes #1090 * feat: functions blocks, parenthesed JSON Expressions - fixes #1792, the very complex example - fixes #1477 * feat: functions blocks, parenthesed JSON Expressions - fixes #1792, the very complex example - fixes #1477 - cosmetics * feat: Quoted Identifiers can contain double-quotes (PostgreSQL) - `SELECT "test""column""name"` - fixes #1335 * build: improve Upload task * doc: Website improvements - Show Release vs. SNAPSHOT - FURO theme - fix inline tab appearance --------- Co-authored-by: zaza --- .github/workflows/sphinx.yml | 4 +- .gitignore | 4 + README.md | 39 +- build.gradle | 239 +- .../expression/AnalyticExpression.java | 42 +- .../jsqlparser/expression/AnalyticType.java | 8 +- .../expression/AnyComparisonExpression.java | 51 +- .../net/sf/jsqlparser/expression/AnyType.java | 7 +- .../expression/ArrayConstructor.java | 14 +- .../jsqlparser/expression/CastExpression.java | 57 +- .../expression/DateTimeLiteralExpression.java | 4 + .../expression/ExpressionVisitor.java | 18 +- .../expression/ExpressionVisitorAdapter.java | 105 +- .../sf/jsqlparser/expression/Function.java | 16 +- .../expression/JdbcNamedParameter.java | 16 +- .../expression/JsonAggregateOnNullType.java | 7 +- .../JsonAggregateUniqueKeysType.java | 7 +- .../expression/JsonFunctionType.java | 9 +- .../expression/MySQLGroupConcat.java | 21 +- .../sf/jsqlparser/expression/Parenthesis.java | 5 +- .../expression/RangeExpression.java | 50 + .../jsqlparser/expression/RowConstructor.java | 52 +- .../expression/SafeCastExpression.java | 95 - .../expression/SpannerInterleaveIn.java | 13 +- .../expression/TimezoneExpression.java | 4 +- .../expression/TranscodingFunction.java | 71 + .../jsqlparser/expression/TrimFunction.java | 124 + .../expression/TryCastExpression.java | 95 - .../expression/ValueListExpression.java | 47 - .../jsqlparser/expression/WindowElement.java | 6 +- .../jsqlparser/expression/WindowOffset.java | 8 +- .../relational/ExistsExpression.java | 4 +- .../operators/relational/ExpressionList.java | 100 +- .../operators/relational/FullTextSearch.java | 30 +- .../operators/relational/InExpression.java | 39 +- .../operators/relational/ItemsList.java | 18 - .../relational/ItemsListVisitor.java | 23 - .../relational/ItemsListVisitorAdapter.java | 38 - .../relational/MemberOfExpression.java | 63 + .../relational/MultiExpressionList.java | 86 - .../relational/NamedExpressionList.java | 58 +- .../relational/ParenthesedExpressionList.java | 41 + .../jsqlparser/parser/CCJSqlParserUtil.java | 147 +- .../parser/ParserKeywordsUtils.java | 258 +- .../sf/jsqlparser/parser/feature/Feature.java | 4 +- .../java/net/sf/jsqlparser/schema/Column.java | 68 +- .../net/sf/jsqlparser/schema/Sequence.java | 37 +- .../sf/jsqlparser/statement/DeclareType.java | 6 +- .../statement/ExplainStatement.java | 23 +- .../sf/jsqlparser/statement/OutputClause.java | 20 +- .../jsqlparser/statement/PurgeObjectType.java | 6 +- .../statement/ReferentialAction.java | 41 +- .../jsqlparser/statement/ReturningClause.java | 97 + .../sf/jsqlparser/statement/SetStatement.java | 26 +- .../statement/StatementVisitor.java | 3 - .../statement/StatementVisitorAdapter.java | 6 - .../sf/jsqlparser/statement/Statements.java | 37 +- .../statement/UnsupportedStatement.java | 24 +- .../statement/alter/AlterOperation.java | 4 + .../alter/AlterSessionOperation.java | 40 +- .../statement/alter/AlterSystemOperation.java | 71 +- .../create/table/ColumnDefinition.java | 17 +- .../create/table/ForeignKeyIndex.java | 24 +- .../create/table/RowMovementMode.java | 4 + .../create/view/AutoRefreshOption.java | 8 +- .../statement/create/view/ForceOption.java | 10 +- .../create/view/TemporaryOption.java | 10 +- .../jsqlparser/statement/delete/Delete.java | 69 +- .../delete/DeleteModifierPriority.java | 6 +- .../jsqlparser/statement/execute/Execute.java | 31 +- .../statement/insert/ConflictActionType.java | 6 +- .../jsqlparser/statement/insert/Insert.java | 291 +- .../insert/InsertConflictAction.java | 35 +- .../insert/InsertModifierPriority.java | 6 +- .../statement/merge/MergeInsert.java | 59 +- .../statement/merge/MergeUpdate.java | 71 +- .../jsqlparser/statement/replace/Replace.java | 83 - .../statement/select/AllColumns.java | 8 +- .../statement/select/AllTableColumns.java | 10 +- .../jsqlparser/statement/select/Distinct.java | 21 +- .../statement/select/ExpressionListItem.java | 52 - .../sf/jsqlparser/statement/select/First.java | 9 +- .../statement/select/FunctionItem.java | 51 - .../statement/select/GroupByElement.java | 94 +- .../sf/jsqlparser/statement/select/Join.java | 57 + .../statement/select/KSQLJoinWindow.java | 34 +- .../statement/select/KSQLWindow.java | 32 +- .../statement/select/LateralView.java | 106 + .../sf/jsqlparser/statement/select/Limit.java | 45 + .../statement/select/MySqlSqlCacheFlags.java | 6 +- .../statement/select/OrderByElement.java | 7 +- .../statement/select/ParenthesedSelect.java | 9 + .../sf/jsqlparser/statement/select/Pivot.java | 84 +- .../jsqlparser/statement/select/PivotXml.java | 28 +- .../statement/select/PlainSelect.java | 106 +- .../jsqlparser/statement/select/Select.java | 33 +- .../select/SelectExpressionItem.java | 67 - .../statement/select/SelectItem.java | 69 +- .../statement/select/SelectItemVisitor.java | 7 +- .../select/SelectItemVisitorAdapter.java | 13 +- .../statement/select/SetOperationList.java | 6 +- .../statement/select/TableFunction.java | 6 +- .../jsqlparser/statement/select/UnPivot.java | 23 +- .../jsqlparser/statement/select/Values.java | 35 +- .../jsqlparser/statement/select/WithItem.java | 16 +- .../statement/show/ShowTablesStatement.java | 13 +- .../jsqlparser/statement/update/Update.java | 113 +- .../update/UpdateModifierPriority.java | 6 +- .../statement/update/UpdateSet.java | 109 +- .../jsqlparser/statement/upsert/Upsert.java | 250 +- .../statement/upsert/UpsertType.java | 13 +- .../sf/jsqlparser/util/AddAliasesVisitor.java | 20 +- .../util/ConnectExpressionsVisitor.java | 25 +- .../net/sf/jsqlparser/util/SelectUtils.java | 9 +- .../sf/jsqlparser/util/TablesNamesFinder.java | 112 +- .../util/deparser/AbstractDeParser.java | 22 + .../util/deparser/DeleteDeParser.java | 43 +- .../util/deparser/ExpressionDeParser.java | 195 +- .../util/deparser/ExpressionListDeParser.java | 49 +- .../util/deparser/GroupByDeParser.java | 49 +- .../util/deparser/InsertDeParser.java | 76 +- .../util/deparser/LimitDeparser.java | 23 +- .../util/deparser/ReplaceDeParser.java | 144 - .../util/deparser/SelectDeParser.java | 141 +- .../util/deparser/StatementDeParser.java | 102 +- .../util/deparser/UpdateDeParser.java | 60 +- .../util/deparser/UpsertDeParser.java | 128 +- .../deparser/ValuesStatementDeParser.java | 6 +- .../util/validation/ParseCapability.java | 19 +- .../validator/AbstractValidator.java | 18 - .../validation/validator/DeleteValidator.java | 7 +- .../validator/ExecuteValidator.java | 5 +- .../validator/ExpressionValidator.java | 122 +- .../validation/validator/InsertValidator.java | 43 +- .../validator/ItemsListValidator.java | 49 - .../validation/validator/MergeValidator.java | 10 +- .../validation/validator/SelectValidator.java | 21 +- .../validator/StatementValidator.java | 6 - .../validation/validator/UpdateValidator.java | 6 +- .../validation/validator/UpsertValidator.java | 15 +- .../validator/ValuesStatementValidator.java | 2 +- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 2166 +++--- src/main/resources/rr/xhtml2rst.xsl | 37 +- src/site/sphinx/_static/floating_toc.css | 83 + src/site/sphinx/_static/floating_toc.js | 98 + src/site/sphinx/_static/svg.css | 12 +- src/site/sphinx/_static/tabs.css | 89 - src/site/sphinx/changelog.rst | 240 +- src/site/sphinx/conf.py | 10 +- src/site/sphinx/contribution.rst | 17 +- src/site/sphinx/index.rst | 11 +- src/site/sphinx/keywords.rst | 2 + .../sphinx/{syntax.rst => syntax_stable.rst} | 6379 +++++++++-------- src/site/sphinx/usage.rst | 164 +- .../ExpressionVisitorAdapterTest.java | 6 +- .../jsqlparser/expression/FunctionTest.java | 41 + .../expression/JdbcNamedParameterTest.java | 42 + .../expression/JsonExpressionTest.java | 111 + .../expression/RowConstructorTest.java | 22 + .../expression/TranscodingFunctionTest.java | 52 + .../expression/TrimFunctionTest.java | 40 + .../mysql/MySqlSqlCalcFoundRowsTest.java | 4 +- .../relational/InExpressionTest.java | 33 + .../relational/MemberOfExpressionTest.java | 25 + .../jsqlparser/parser/CCJSqlParserTest.java | 11 +- .../parser/CCJSqlParserUtilTest.java | 268 +- .../feature/FeatureConfigurationTest.java | 13 +- .../statement/ReferentialActionTest.java | 30 + .../statement/ReturningClauseTest.java | 28 + .../statement/SetStatementTest.java | 22 +- .../statement/ShowStatementTest.java | 19 +- .../statement/UnsupportedStatementTest.java | 77 +- .../builder/JSQLParserFluentModelTests.java | 26 +- .../builder/ReflectionModelTest.java | 15 +- .../statement/create/AlterViewTest.java | 13 +- .../statement/create/CreateTableTest.java | 386 +- .../statement/insert/InsertTest.java | 110 +- .../statement/replace/ReplaceTest.java | 41 +- .../statement/select/ClickHouseTest.java | 32 + .../jsqlparser/statement/select/HiveTest.java | 10 + .../select/NestedBracketsPerformanceTest.java | 8 +- .../statement/select/PostgresTest.java | 56 +- .../statement/select/SelectASTTest.java | 17 +- .../statement/select/SelectTest.java | 476 +- .../select/SelectXMLSerializeTest.java | 22 +- .../statement/select/SpecialOracleTest.java | 7 +- .../statement/update/UpdateTest.java | 182 +- .../statement/upsert/UpsertTest.java | 91 +- .../statement/values/ValuesTest.java | 18 +- .../sf/jsqlparser/test/HowToUseSample.java | 58 +- .../net/sf/jsqlparser/test/TestUtils.java | 6 +- .../sf/jsqlparser/util/APISanitationTest.java | 400 ++ .../sf/jsqlparser/util/SelectUtilsTest.java | 4 +- .../util/deparser/ExecuteDeParserTest.java | 15 +- .../util/deparser/ExpressionDeParserTest.java | 47 +- .../util/deparser/StatementDeParserTest.java | 81 +- .../validator/ReplaceValidatorTest.java | 4 +- .../validator/UpsertValidatorTest.java | 2 +- .../oracle-tests/compound_statements03.sql | 3 +- .../select/oracle-tests/function03.sql | 3 +- .../select/oracle-tests/function06.sql | 3 +- .../select/oracle-tests/groupby07.sql | 3 +- .../select/oracle-tests/insert11.sql | 3 +- .../select/oracle-tests/insert12.sql | 3 +- 204 files changed, 9912 insertions(+), 8836 deletions(-) create mode 100644 src/main/java/net/sf/jsqlparser/expression/RangeExpression.java delete mode 100644 src/main/java/net/sf/jsqlparser/expression/SafeCastExpression.java create mode 100644 src/main/java/net/sf/jsqlparser/expression/TranscodingFunction.java create mode 100644 src/main/java/net/sf/jsqlparser/expression/TrimFunction.java delete mode 100644 src/main/java/net/sf/jsqlparser/expression/TryCastExpression.java delete mode 100644 src/main/java/net/sf/jsqlparser/expression/ValueListExpression.java delete mode 100644 src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsList.java delete mode 100644 src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsListVisitor.java delete mode 100644 src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsListVisitorAdapter.java create mode 100644 src/main/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpression.java delete mode 100644 src/main/java/net/sf/jsqlparser/expression/operators/relational/MultiExpressionList.java create mode 100644 src/main/java/net/sf/jsqlparser/expression/operators/relational/ParenthesedExpressionList.java create mode 100644 src/main/java/net/sf/jsqlparser/statement/ReturningClause.java delete mode 100644 src/main/java/net/sf/jsqlparser/statement/replace/Replace.java delete mode 100644 src/main/java/net/sf/jsqlparser/statement/select/ExpressionListItem.java delete mode 100644 src/main/java/net/sf/jsqlparser/statement/select/FunctionItem.java create mode 100644 src/main/java/net/sf/jsqlparser/statement/select/LateralView.java delete mode 100644 src/main/java/net/sf/jsqlparser/statement/select/SelectExpressionItem.java delete mode 100644 src/main/java/net/sf/jsqlparser/util/deparser/ReplaceDeParser.java delete mode 100644 src/main/java/net/sf/jsqlparser/util/validation/validator/ItemsListValidator.java create mode 100644 src/site/sphinx/_static/floating_toc.css create mode 100644 src/site/sphinx/_static/floating_toc.js delete mode 100644 src/site/sphinx/_static/tabs.css rename src/site/sphinx/{syntax.rst => syntax_stable.rst} (77%) create mode 100644 src/test/java/net/sf/jsqlparser/expression/FunctionTest.java create mode 100644 src/test/java/net/sf/jsqlparser/expression/JdbcNamedParameterTest.java create mode 100644 src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java create mode 100644 src/test/java/net/sf/jsqlparser/expression/RowConstructorTest.java create mode 100644 src/test/java/net/sf/jsqlparser/expression/TranscodingFunctionTest.java create mode 100644 src/test/java/net/sf/jsqlparser/expression/TrimFunctionTest.java create mode 100644 src/test/java/net/sf/jsqlparser/expression/operators/relational/InExpressionTest.java create mode 100644 src/test/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpressionTest.java create mode 100644 src/test/java/net/sf/jsqlparser/statement/ReferentialActionTest.java create mode 100644 src/test/java/net/sf/jsqlparser/statement/ReturningClauseTest.java create mode 100644 src/test/java/net/sf/jsqlparser/util/APISanitationTest.java diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml index 2c2b7f76c..f4ebbb6da 100644 --- a/.github/workflows/sphinx.yml +++ b/.github/workflows/sphinx.yml @@ -9,7 +9,7 @@ jobs: - name: Install XSLT Processor run: sudo apt-get install xsltproc sphinx-common - name: Install dependencies - run: pip install sphinx_rtd_theme sphinx-book-theme myst_parser sphinx-prompt sphinx_substitution_extensions sphinx_issues sphinx_tabs pygments + run: pip install sphinx_rtd_theme sphinx-book-theme myst_parser sphinx-prompt sphinx_substitution_extensions sphinx_issues sphinx-tabs sphinx_inline_tabs pygments - name: Checkout project sources uses: actions/checkout@v2 with: @@ -18,7 +18,7 @@ jobs: - name: Setup Gradle uses: gradle/gradle-build-action@v2 - name: Run build with Gradle Wrapper - run: gradle sphinx + run: gradle --no-build-cache clean xmldoc sphinx - name: Deploy uses: actions/configure-pages@v2 - name: Upload artifact diff --git a/.gitignore b/.gitignore index 81cbc5c83..76f3c99dd 100755 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ # Exclude the Auto-generated Changelog /src/site/sphinx/changelog.rst +/src/site/sphinx/javadoc_stable.rst +/src/site/sphinx/syntax_stable.rst # Generated by javacc-maven-plugin /bin @@ -27,3 +29,5 @@ /nbproject/ /.gradle +/src/site/sphinx/javadoc_snapshot.rst +/src/site/sphinx/syntax_snapshot.rst diff --git a/README.md b/README.md index aeef82101..643f6301a 100644 --- a/README.md +++ b/README.md @@ -19,29 +19,34 @@ SELECT 1 FROM dual WHERE a = b ```text SQL Text - └─Statements: net.sf.jsqlparser.statement.select.PlainSelect - ├─selectItems -> Collection - │ └─selectItems: net.sf.jsqlparser.statement.select.SelectExpressionItem - │ └─LongValue: 1 - ├─Table: dual - └─where: net.sf.jsqlparser.expression.operators.relational.EqualsTo - ├─Column: a - └─Column: b + └─Statements: net.sf.jsqlparser.statement.select.Select + ├─selectItems -> Collection + │ └─LongValue: 1 + ├─Table: dual + └─where: net.sf.jsqlparser.expression.operators.relational.EqualsTo + ├─Column: a + └─Column: b ``` ```java -Statement statement = CCJSqlParserUtil.parse(sqlStr); -if (statement instanceof PlainSelect) { - PlainSelect plainSelect = (PlainSelect) statement; +String sqlStr = "select 1 from dual where a=b"; - SelectExpressionItem selectExpressionItem = - (SelectExpressionItem) plainSelect.getSelectItems().get(0); +PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); - Table table = (Table) plainSelect.getFromItem(); +SelectItem selectItem = + select.getSelectItems().get(0); +Assertions.assertEquals( + new LongValue(1) + , selectItem.getExpression()); - EqualsTo equalsTo = (EqualsTo) plainSelect.getWhere(); - Column a = (Column) equalsTo.getLeftExpression(); - Column b = (Column) equalsTo.getRightExpression(); +Table table = (Table) select.getFromItem(); +Assertions.assertEquals("dual", table.getName()); + +EqualsTo equalsTo = (EqualsTo) select.getWhere(); +Column a = (Column) equalsTo.getLeftExpression(); +Column b = (Column) equalsTo.getRightExpression(); +Assertions.assertEquals("a", a.getColumnName()); +Assertions.assertEquals("b", b.getColumnName()); } ``` diff --git a/build.gradle b/build.gradle index 43b75a34e..a0003d29a 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,10 @@ import se.bjurr.gitchangelog.plugin.gradle.GitChangelogTask -import java.nio.charset.Charset - plugins { id 'java' id 'maven-publish' + id 'signing' + id "ca.coglinc2.javacc" version "latest.release" id 'jacoco' id "com.github.spotbugs" version "latest.release" @@ -17,21 +17,19 @@ plugins { id 'org.hidetake.ssh' version "latest.release" id "se.bjurr.gitchangelog.git-changelog-gradle-plugin" version "latest.release" + id "me.champeau.jmh" version "latest.release" + id "com.nwalsh.gradle.saxon.saxon-gradle" version "0.9.6" } - - -group = 'com.github.jsqlparser' - def getVersion = { boolean considerSnapshot -> - def major = 0 - def minor = 0 - def patch = 0 - def commit = "" - def snapshot ="" + Integer major = 0 + Integer minor = 0 + Integer patch = null + Integer build = null + def commit = null + def snapshot = "" new ByteArrayOutputStream().withStream { os -> exec { - workingDir "$projectDir" args = [ "--no-pager" , "describe" @@ -42,30 +40,45 @@ def getVersion = { boolean considerSnapshot -> executable "git" standardOutput = os } - def matcher = os.toString() =~ /jsqlparser-(\d*)\.(\d*)-(\d*)-([a-zA-Z\d]*)/ - matcher.find() - - major = matcher[0][1] - minor = matcher[0][2] - patch = matcher[0][3] - commit = matcher[0][4] + def versionStr = os.toString().trim() + def pattern = /(?\d*)\.(?\d*)(\.(?\d*))?(-(?\d*)-(?[a-zA-Z\d]*))?/ + def matcher = versionStr =~ pattern + if (matcher.find()) { + major = matcher.group('major') as Integer + minor = matcher.group('minor') as Integer + patch = matcher.group('patch') as Integer + build = matcher.group('build') as Integer + commit = matcher.group('commit') + } - if (considerSnapshot) { + if (considerSnapshot && ( versionStr.endsWith('SNAPSHOT') || build!=null) ) { minor++ - snapshot = "-SNAPSHOT" + if (patch!=null) patch = 0 + snapshot = "-SNAPSHOT" } } - return "${major}.${minor}${snapshot}" + return patch!=null + ? "${major}.${minor}.${patch}${snapshot}" + : "${major}.${minor}${snapshot}" } version = getVersion(true) - +group = 'com.github.jsqlparser' description = 'JSQLParser library' -java.sourceCompatibility = JavaVersion.VERSION_1_8 +archivesBaseName = "JSQLParser" repositories { gradlePluginPortal() mavenLocal() mavenCentral() + + // Sonatype OSSRH + maven { + url = uri('https://s01.oss.sonatype.org/content/repositories/snapshots/') + } +} + +configurations { + xmlDoclet } dependencies { @@ -83,7 +96,14 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter-params:+' // https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter - testImplementation 'org.mockito:mockito-junit-jupiter:4.+' + testImplementation 'org.mockito:mockito-junit-jupiter:+' + + // Performance Benchmark + testImplementation 'org.openjdk.jmh:jmh-core:+' + testImplementation 'org.openjdk.jmh:jmh-generator-annprocess:+' + + // Java Doc in XML Format + xmlDoclet 'com.manticore-projects.tools:xml-doclet:+' // enforce latest version of JavaCC testImplementation 'net.java.dev.javacc:javacc:+' @@ -97,13 +117,59 @@ compileJavacc { java { withSourcesJar() withJavadocJar() + + sourceCompatibility = '1.8' + targetCompatibility = '1.8' + // needed for XML-Doclet to work (since Doclet changed again with Java 13) + toolchain { + languageVersion.set(JavaLanguageVersion.of(11)) + } +} + +compileJava { + options.release = 8 } javadoc { - options.addBooleanOption('html5', true) + if(JavaVersion.current().isJava9Compatible()) { + options.addBooleanOption('html5', true) + } options.addBooleanOption("Xdoclint:none", true) } +tasks.register('xmldoc', Javadoc) { + def outFile = reporting.file( + version.endsWith("-SNAPSHOT") + ? "xmlDoclet/javadoc_snapshot.xml" + : "xmlDoclet/javadoc_stable.xml" + ) + + def rstFile = reporting.file( + version.endsWith("-SNAPSHOT") + ? "xmlDoclet/javadoc_snapshot.rst" + : "xmlDoclet/javadoc_stable.rst" + ) + + source = sourceSets.main.allJava + // beware: Gradle deletes this folder automatically and there is no switch-off + destinationDir = reporting.file("xmlDoclet") + options.docletpath = configurations.xmlDoclet.files as List + options.doclet = "com.github.markusbernhardt.xmldoclet.XmlDoclet" + title = "API $version" + options.addBooleanOption("rst", true) + options.addBooleanOption("withFloatingToc", true) + options.addStringOption("basePackage", "net.sf.jsqlparser") + options.addStringOption("filename", outFile.getName()) + + dependsOn(compileJava) + doLast { + copy { + from rstFile + into "${projectDir}/src/site/sphinx/" + } + } +} + test { environment = [ 'EXPORT_TEST_TO_FILE': 'True' ] useJUnitPlatform() @@ -111,8 +177,6 @@ test { // set heap size for the test JVM(s) minHeapSize = "128m" maxHeapSize = "1G" - - finalizedBy check } jacocoTestReport { @@ -250,14 +314,14 @@ spotless { } } -tasks.withType(Checkstyle) { +tasks.withType(Checkstyle).configureEach { reports { xml.required = false html.required = true } } -task renderRR() { +tasks.register('renderRR') { dependsOn(compileJavacc) doLast { // these WAR files have been provided as a courtesy by Gunther Rademacher @@ -301,15 +365,10 @@ task renderRR() { "${buildDir}/rr/JSqlParserCC.ebnf" ] } - - //@todo: a Java based solution may be more appropriate here - exec { - commandLine "sh", "-c", "xsltproc src/main/resources/rr/xhtml2rst.xsl $buildDir/rr/JSqlParserCC.xhtml > src/site/sphinx/syntax.rst" - } } } -task gitChangelogTask(type: GitChangelogTask) { +tasks.register('gitChangelogTask', GitChangelogTask) { fromRepo = file("$projectDir") file = new File("${projectDir}/src/site/sphinx/changelog.rst") fromRef = "4.0" @@ -348,7 +407,7 @@ Version {{name}} // @formatter:on } -task updateKeywords(type: JavaExec) { +tasks.register('updateKeywords', JavaExec) { group = "Execution" description = "Run the main class with JavaExecTask" classpath = sourceSets.main.runtimeClasspath @@ -361,8 +420,38 @@ task updateKeywords(type: JavaExec) { dependsOn(compileJava) } -task sphinx(type: Exec) { - dependsOn(gitChangelogTask, renderRR, updateKeywords) +xslt { + def outFile = version.endsWith("-SNAPSHOT") + ? file("src/site/sphinx/syntax_snapshot.rst") + : file("src/site/sphinx/syntax_stable.rst") + + dependsOn(renderRR) + stylesheet 'src/main/resources/rr/xhtml2rst.xsl' + + // Transform every .xml file in the "input" directory. + input "$buildDir/rr/JSqlParserCC.xhtml" + output outFile +} + +tasks.register('sphinx', Exec) { + dependsOn(gitChangelogTask, renderRR, xslt, updateKeywords, xmldoc) + +// doFirst() { +// exec { +// args = [ +// "install" +// , "sphinx_rtd_theme" +// , "sphinx-book-theme" +// , "myst_parser" +// , "sphinx-prompt" +// , "sphinx_substitution_extensions" +// , "sphinx_issues" +// , "sphinx_inline_tabs" +// , "pygments" +// ] +// executable "pip" +// } +// } String PROLOG = """ .. |_| unicode:: U+00A0 @@ -402,33 +491,81 @@ task sphinx(type: Exec) { } } +publish { + dependsOn(check) +} + publishing { publications { mavenJava(MavenPublication) { - artifactId 'jsqlparser' - from(components.java) + artifactId = 'jsqlparser' + + from components.java versionMapping { usage('java-api') { - fromResolutionOf('testFixturesRuntimeClasspath') + fromResolutionOf('runtimeClasspath') } usage('java-runtime') { fromResolutionResult() } } + pom { + name = 'JSQLParser library' + description = 'Parse SQL Statements into Abstract Syntax Trees (AST)' + url = 'https://github.com/JSQLParser/JSqlParser' + licenses { + license { + name = 'GNU Library or Lesser General Public License (LGPL) V2.1' + url = 'http://www.gnu.org/licenses/lgpl-2.1.html' + } + license { + name = 'The Apache Software License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + developers { + developer { + id = 'twa' + name = 'Tobias Warneke' + email = 't.warneke@gmx.net' + } + developer { + id = 'are' + name = 'Andreas Reichel' + email = 'andreas@manticore-projects.com' + } + } + scm { + connection = 'scm:git:https://github.com/JSQLParser/JSqlParser.git' + developerConnection = 'scm:git:ssh://git@github.com:JSQLParser/JSqlParser.git' + url = 'https://github.com/JSQLParser/JSqlParser.git' + } + } } } repositories { - maven { - // Username and Password are defined in ~/.gradle/gradle.properties name "ossrh" - url "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" + + def releasesRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots" + def snapshotsRepoUrl= "https://oss.sonatype.org/service/local/staging/deploy/maven2" + url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl + credentials(PasswordCredentials) + } + maven { + name = "GitHubPackages" + + url = uri("https://maven.pkg.github.com/manticore-projects/jsqlparser") credentials(PasswordCredentials) } } } -tasks.withType(JavaCompile) { +signing { + sign publishing.publications.mavenJava +} + +tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' } @@ -440,11 +577,11 @@ remotes { } } -task upload { +tasks.register('upload') { doFirst { - if( findProperty("${project.name}.host")==null ) { + if (findProperty("${project.name}.host") == null) { println( - """ + """ Property \"${project.name}.host\' not found. Please define \"${project.name}.host\" in the Gradle configuration (e. g. \$HOME/.gradle/gradle.properties. """ @@ -456,7 +593,9 @@ task upload { session(remotes.webServer) { def versionStable = getVersion(false) execute "mkdir -p download/${project.name}-${versionStable}" - put from: "${project.buildDir}/libs", into: "download/${project.name}-${versionStable}" + for (File file: fileTree(include:['*.jar'], dir:"${project.buildDir}/libs").collect()) { + put from: file, into: "download/${project.name}-${versionStable}" + } } } } diff --git a/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java b/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java index 07aa23d4f..75e53c0fa 100644 --- a/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java @@ -9,16 +9,19 @@ */ package net.sf.jsqlparser.expression; -import java.util.List; -import static java.util.stream.Collectors.joining; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; import net.sf.jsqlparser.statement.select.OrderByElement; +import java.util.List; + +import static java.util.stream.Collectors.joining; + /** - * Analytic function. The name of the function is variable but the parameters following the special analytic function - * path. e.g. row_number() over (order by test). Additional there can be an expression for an analytical aggregate like - * sum(col) or the "all collumns" wildcard like count(*). + * Analytic function. The name of the function is variable but the parameters following the special + * analytic function path. e.g. row_number() over (order by test). Additional there can be an + * expression for an analytical aggregate like sum(col) or the "all collumns" wildcard like + * count(*). * * @author tw */ @@ -33,15 +36,15 @@ public class AnalyticExpression extends ASTNodeAccessImpl implements Expression private AnalyticType type = AnalyticType.OVER; private boolean distinct = false; private boolean unique = false; - private boolean ignoreNulls = false; //IGNORE NULLS inside function parameters - private boolean ignoreNullsOutside = false; //IGNORE NULLS outside function parameters + private boolean ignoreNulls = false; // IGNORE NULLS inside function parameters + private boolean ignoreNullsOutside = false; // IGNORE NULLS outside function parameters private Expression filterExpression = null; private List funcOrderBy = null; - private String windowName = null; // refers to an external window definition (paritionBy, orderBy, windowElement) + private String windowName = null; // refers to an external window definition (paritionBy, + // orderBy, windowElement) private WindowDefinition windowDef = new WindowDefinition(); - public AnalyticExpression() { - } + public AnalyticExpression() {} public AnalyticExpression(Function function) { name = function.getName(); @@ -50,18 +53,19 @@ public AnalyticExpression(Function function) { unique = function.isUnique(); funcOrderBy = function.getOrderByElements(); - ExpressionList list = function.getParameters(); + ExpressionList list = function.getParameters(); if (list != null) { if (list.getExpressions().size() > 3) { - throw new IllegalArgumentException("function object not valid to initialize analytic expression"); + throw new IllegalArgumentException( + "function object not valid to initialize analytic expression"); } - expression = list.getExpressions().get(0); + expression = list.get(0); if (list.getExpressions().size() > 1) { - offset = list.getExpressions().get(1); + offset = list.get(1); } if (list.getExpressions().size() > 2) { - defaultValue = list.getExpressions().get(2); + defaultValue = list.get(2); } } ignoreNulls = function.isIgnoreNulls(); @@ -97,7 +101,8 @@ public void setPartitionExpressionList(ExpressionList partitionExpressionList) { setPartitionExpressionList(partitionExpressionList, false); } - public void setPartitionExpressionList(ExpressionList partitionExpressionList, boolean brackets) { + public void setPartitionExpressionList(ExpressionList partitionExpressionList, + boolean brackets) { windowDef.partitionBy.setPartitionExpressionList(partitionExpressionList, brackets); } @@ -202,7 +207,8 @@ public void setWindowDefinition(WindowDefinition windowDef) { } @Override - @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity", "PMD.MissingBreakInSwitch"}) + @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity", + "PMD.MissingBreakInSwitch"}) public String toString() { StringBuilder b = new StringBuilder(); @@ -266,7 +272,7 @@ public String toString() { if (windowName != null) { b.append(" ").append(windowName); - } else if (type!=AnalyticType.WITHIN_GROUP_OVER) { + } else if (type != AnalyticType.WITHIN_GROUP_OVER) { b.append(" "); b.append(windowDef.toString()); } diff --git a/src/main/java/net/sf/jsqlparser/expression/AnalyticType.java b/src/main/java/net/sf/jsqlparser/expression/AnalyticType.java index 115c45305..2738849c6 100644 --- a/src/main/java/net/sf/jsqlparser/expression/AnalyticType.java +++ b/src/main/java/net/sf/jsqlparser/expression/AnalyticType.java @@ -10,9 +10,9 @@ package net.sf.jsqlparser.expression; public enum AnalyticType { - OVER, - WITHIN_GROUP, + OVER, WITHIN_GROUP, WITHIN_GROUP_OVER, FILTER_ONLY; - WITHIN_GROUP_OVER, - FILTER_ONLY + public static AnalyticType from(String type) { + return Enum.valueOf(AnalyticType.class, type.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/expression/AnyComparisonExpression.java b/src/main/java/net/sf/jsqlparser/expression/AnyComparisonExpression.java index 665bc8833..f7a9368c0 100644 --- a/src/main/java/net/sf/jsqlparser/expression/AnyComparisonExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/AnyComparisonExpression.java @@ -9,9 +9,8 @@ */ package net.sf.jsqlparser.expression; -import net.sf.jsqlparser.expression.operators.relational.ItemsList; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; -import net.sf.jsqlparser.statement.select.ParenthesedSelect; +import net.sf.jsqlparser.statement.select.Select; /** * Combines ANY and SOME expressions. @@ -19,52 +18,18 @@ * @author toben */ public class AnyComparisonExpression extends ASTNodeAccessImpl implements Expression { - - private final ItemsList itemsList; - private boolean useBracketsForValues = false; - private final ParenthesedSelect subSelect; + private final Select select; private final AnyType anyType; - public AnyComparisonExpression(AnyType anyType, ParenthesedSelect subSelect) { - this.anyType = anyType; - this.subSelect = subSelect; - this.itemsList = null; - } - - public AnyComparisonExpression(AnyType anyType, ItemsList itemsList) { + public AnyComparisonExpression(AnyType anyType, Select select) { this.anyType = anyType; - this.itemsList = itemsList; - this.subSelect = null; - } - - public ParenthesedSelect getSubSelect() { - return subSelect; - } - - public ItemsList getItemsList() { - return itemsList; + this.select = select; } - public boolean isUsingItemsList() { - return itemsList != null; + public Select getSelect() { + return select; } - public boolean isUsingSubSelect() { - return subSelect != null; - } - - public boolean isUsingBracketsForValues() { - return useBracketsForValues; - } - - public void setUseBracketsForValues(boolean useBracketsForValues) { - this.useBracketsForValues = useBracketsForValues; - } - - public AnyComparisonExpression withUseBracketsForValues(boolean useBracketsForValues) { - this.setUseBracketsForValues(useBracketsForValues); - return this; - } @Override public void accept(ExpressionVisitor expressionVisitor) { @@ -77,9 +42,7 @@ public AnyType getAnyType() { @Override public String toString() { - String s = anyType.name() + " (" - + (subSelect != null ? subSelect.toString() : "VALUES " + itemsList.toString()) - + " )"; + String s = anyType.name() + select; return s; } } diff --git a/src/main/java/net/sf/jsqlparser/expression/AnyType.java b/src/main/java/net/sf/jsqlparser/expression/AnyType.java index 460de9704..fec6fb09d 100644 --- a/src/main/java/net/sf/jsqlparser/expression/AnyType.java +++ b/src/main/java/net/sf/jsqlparser/expression/AnyType.java @@ -10,8 +10,9 @@ package net.sf.jsqlparser.expression; public enum AnyType { + ANY, SOME, ALL; - ANY, - SOME, - ALL + public static AnyType from(String type) { + return Enum.valueOf(AnyType.class, type.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/expression/ArrayConstructor.java b/src/main/java/net/sf/jsqlparser/expression/ArrayConstructor.java index 079191622..267708dc4 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ArrayConstructor.java +++ b/src/main/java/net/sf/jsqlparser/expression/ArrayConstructor.java @@ -9,20 +9,18 @@ */ package net.sf.jsqlparser.expression; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; -import net.sf.jsqlparser.statement.select.PlainSelect; - -import java.util.List; public class ArrayConstructor extends ASTNodeAccessImpl implements Expression { - private List expressions; + private ExpressionList expressions; private boolean arrayKeyword; - public List getExpressions() { + public ExpressionList getExpressions() { return expressions; } - public void setExpressions(List expressions) { + public void setExpressions(ExpressionList expressions) { this.expressions = expressions; } @@ -34,7 +32,7 @@ public void setArrayKeyword(boolean arrayKeyword) { this.arrayKeyword = arrayKeyword; } - public ArrayConstructor(List expressions, boolean arrayKeyword) { + public ArrayConstructor(ExpressionList expressions, boolean arrayKeyword) { this.expressions = expressions; this.arrayKeyword = arrayKeyword; } @@ -51,7 +49,7 @@ public String toString() { sb.append("ARRAY"); } sb.append("["); - sb.append(PlainSelect.getStringList(expressions, true, false)); + sb.append(expressions.toString()); sb.append("]"); return sb.toString(); } diff --git a/src/main/java/net/sf/jsqlparser/expression/CastExpression.java b/src/main/java/net/sf/jsqlparser/expression/CastExpression.java index 519eb4ef6..d928a26b2 100644 --- a/src/main/java/net/sf/jsqlparser/expression/CastExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/CastExpression.java @@ -11,35 +11,41 @@ import net.sf.jsqlparser.parser.ASTNodeAccessImpl; import net.sf.jsqlparser.statement.create.table.ColDataType; +import net.sf.jsqlparser.statement.create.table.ColumnDefinition; +import net.sf.jsqlparser.statement.select.Select; + +import java.util.ArrayList; public class CastExpression extends ASTNodeAccessImpl implements Expression { + public String keyword; private Expression leftExpression; - private ColDataType type; - private RowConstructor rowConstructor; + private ColDataType colDataType = null; + private ArrayList columnDefinitions = new ArrayList<>(); private boolean useCastKeyword = true; - - public RowConstructor getRowConstructor() { - return rowConstructor; - } - - public void setRowConstructor(RowConstructor rowConstructor) { - this.rowConstructor = rowConstructor; - this.type = null; - } - - public CastExpression withRowConstructor(RowConstructor rowConstructor) { - setRowConstructor(rowConstructor); - return this; + + public CastExpression(String keyword) { + this.keyword = keyword; + } + + public CastExpression() { + this("CAST"); + } + + public ColDataType getColDataType() { + return colDataType; + } + + public ArrayList getColumnDefinitions() { + return columnDefinitions; } - public ColDataType getType() { - return type; + public void setColDataType(ColDataType colDataType) { + this.colDataType = colDataType; } - public void setType(ColDataType type) { - this.type = type; - this.rowConstructor = null; + public void addColumnDefinition(ColumnDefinition columnDefinition) { + this.columnDefinitions.add(columnDefinition); } public Expression getLeftExpression() { @@ -66,16 +72,17 @@ public void setUseCastKeyword(boolean useCastKeyword) { @Override public String toString() { if (useCastKeyword) { - return rowConstructor!=null - ? "CAST(" + leftExpression + " AS " + rowConstructor.toString() + ")" - : "CAST(" + leftExpression + " AS " + type.toString() + ")"; + return columnDefinitions.size() > 1 + ? keyword + "(" + leftExpression + " AS ROW(" + + Select.getStringList(columnDefinitions) + "))" + : keyword + "(" + leftExpression + " AS " + colDataType.toString() + ")"; } else { - return leftExpression + "::" + type.toString(); + return leftExpression + "::" + colDataType.toString(); } } public CastExpression withType(ColDataType type) { - this.setType(type); + this.setColDataType(type); return this; } diff --git a/src/main/java/net/sf/jsqlparser/expression/DateTimeLiteralExpression.java b/src/main/java/net/sf/jsqlparser/expression/DateTimeLiteralExpression.java index 3d87c6203..9290e882b 100644 --- a/src/main/java/net/sf/jsqlparser/expression/DateTimeLiteralExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/DateTimeLiteralExpression.java @@ -54,5 +54,9 @@ public DateTimeLiteralExpression withType(DateTime type) { public enum DateTime { DATE, TIME, TIMESTAMP, TIMESTAMPTZ; + + public static DateTime from(String dateTimeStr) { + return Enum.valueOf(DateTime.class, dateTimeStr.toUpperCase()); + } } } diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java index ce4db3521..b611f89c2 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java @@ -27,6 +27,7 @@ import net.sf.jsqlparser.expression.operators.relational.Between; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; import net.sf.jsqlparser.expression.operators.relational.ExistsExpression; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.FullTextSearch; import net.sf.jsqlparser.expression.operators.relational.GeometryDistance; import net.sf.jsqlparser.expression.operators.relational.GreaterThan; @@ -38,6 +39,7 @@ import net.sf.jsqlparser.expression.operators.relational.JsonOperator; import net.sf.jsqlparser.expression.operators.relational.LikeExpression; import net.sf.jsqlparser.expression.operators.relational.Matches; +import net.sf.jsqlparser.expression.operators.relational.MemberOfExpression; import net.sf.jsqlparser.expression.operators.relational.MinorThan; import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals; import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo; @@ -134,6 +136,8 @@ public interface ExpressionVisitor { void visit(ExistsExpression existsExpression); + void visit(MemberOfExpression memberOfExpression); + void visit(AnyComparisonExpression anyComparisonExpression); void visit(Concat concat); @@ -148,10 +152,6 @@ public interface ExpressionVisitor { void visit(CastExpression cast); - void visit(TryCastExpression cast); - - void visit(SafeCastExpression cast); - void visit(Modulo modulo); void visit(AnalyticExpression aexpr); @@ -178,9 +178,9 @@ public interface ExpressionVisitor { void visit(MySQLGroupConcat groupConcat); - void visit(ValueListExpression valueList); + void visit(ExpressionList expressionList); - void visit(RowConstructor rowConstructor); + void visit(RowConstructor rowConstructor); void visit(RowGetExpression rowGetExpression); @@ -227,4 +227,10 @@ public interface ExpressionVisitor { void visit(GeometryDistance geometryDistance); void visit(Select selectBody); + + void visit(TranscodingFunction transcodingFunction); + + void visit(TrimFunction trimFunction); + + void visit(RangeExpression rangeExpression); } diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index c410c57d2..965d767fc 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -36,31 +36,26 @@ import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression; import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression; import net.sf.jsqlparser.expression.operators.relational.IsNullExpression; -import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor; import net.sf.jsqlparser.expression.operators.relational.JsonOperator; import net.sf.jsqlparser.expression.operators.relational.LikeExpression; import net.sf.jsqlparser.expression.operators.relational.Matches; +import net.sf.jsqlparser.expression.operators.relational.MemberOfExpression; import net.sf.jsqlparser.expression.operators.relational.MinorThan; import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals; -import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; -import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList; import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo; import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator; import net.sf.jsqlparser.expression.operators.relational.RegExpMySQLOperator; import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression; import net.sf.jsqlparser.schema.Column; -import net.sf.jsqlparser.statement.create.table.ColumnDefinition; import net.sf.jsqlparser.statement.select.AllColumns; import net.sf.jsqlparser.statement.select.AllTableColumns; -import net.sf.jsqlparser.statement.select.ExpressionListItem; -import net.sf.jsqlparser.statement.select.FunctionItem; import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.ParenthesedSelect; import net.sf.jsqlparser.statement.select.Pivot; import net.sf.jsqlparser.statement.select.PivotVisitor; import net.sf.jsqlparser.statement.select.PivotXml; import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectExpressionItem; +import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.SelectItemVisitor; import net.sf.jsqlparser.statement.select.SelectVisitor; import net.sf.jsqlparser.statement.select.UnPivot; @@ -68,7 +63,7 @@ @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.UncommentedEmptyMethodBody"}) public class ExpressionVisitorAdapter - implements ExpressionVisitor, ItemsListVisitor, PivotVisitor, SelectItemVisitor { + implements ExpressionVisitor, PivotVisitor, SelectItemVisitor { private SelectVisitor selectVisitor; @@ -220,14 +215,8 @@ public void visit(GreaterThanEquals expr) { @Override public void visit(InExpression expr) { - if (expr.getLeftExpression() != null) { - expr.getLeftExpression().accept(this); - } - if (expr.getRightExpression() != null) { - expr.getRightExpression().accept(this); - } else if (expr.getRightItemsList() != null) { - expr.getRightItemsList().accept(this); - } + expr.getLeftExpression().accept(this); + expr.getRightExpression().accept(this); } @Override @@ -311,6 +300,11 @@ public void visit(ExistsExpression expr) { expr.getRightExpression().accept(this); } + @Override + public void visit(MemberOfExpression memberOfExpression) { + memberOfExpression.getRightExpression().accept(this); + } + @Override public void visit(AnyComparisonExpression expr) { @@ -346,16 +340,6 @@ public void visit(CastExpression expr) { expr.getLeftExpression().accept(this); } - @Override - public void visit(TryCastExpression expr) { - expr.getLeftExpression().accept(this); - } - - @Override - public void visit(SafeCastExpression expr) { - expr.getLeftExpression().accept(this); - } - @Override public void visit(Modulo expr) { visitBinaryExpression(expr); @@ -406,26 +390,19 @@ public void visit(RegExpMatchOperator expr) { } @Override - public void visit(ExpressionList expressionList) { - for (Expression expr : expressionList.getExpressions()) { + public void visit(ExpressionList expressionList) { + for (Expression expr : expressionList) { expr.accept(this); } } @Override - public void visit(NamedExpressionList namedExpressionList) { - for (Expression expr : namedExpressionList.getExpressions()) { + public void visit(RowConstructor rowConstructor) { + for (Expression expr : rowConstructor) { expr.accept(this); } } - @Override - public void visit(MultiExpressionList multiExprList) { - for (ExpressionList list : multiExprList.getExprList()) { - visit(list); - } - } - @Override public void visit(NotExpression notExpr) { notExpr.getExpression().accept(this); @@ -490,38 +467,31 @@ public void visit(MySQLGroupConcat groupConcat) { } } - @Override - public void visit(ValueListExpression valueListExpression) { - for (Expression expr : valueListExpression.getExpressionList().getExpressions()) { - expr.accept(this); - } - } - @Override public void visit(Pivot pivot) { - for (FunctionItem item : pivot.getFunctionItems()) { - item.getFunction().accept(this); + for (SelectItem item : pivot.getFunctionItems()) { + item.getExpression().accept(this); } for (Column col : pivot.getForColumns()) { col.accept(this); } if (pivot.getSingleInItems() != null) { - for (SelectExpressionItem item : pivot.getSingleInItems()) { - item.accept(this); + for (SelectItem item : pivot.getSingleInItems()) { + item.getExpression().accept(this); } } if (pivot.getMultiInItems() != null) { - for (ExpressionListItem item : pivot.getMultiInItems()) { - item.getExpressionList().accept(this); + for (SelectItem item : pivot.getMultiInItems()) { + item.getExpression().accept(this); } } } @Override public void visit(PivotXml pivot) { - for (FunctionItem item : pivot.getFunctionItems()) { - item.getFunction().accept(this); + for (SelectItem item : pivot.getFunctionItems()) { + item.getExpression().accept(this); } for (Column col : pivot.getForColumns()) { col.accept(this); @@ -551,23 +521,10 @@ public void visit(IsDistinctExpression isDistinctExpression) { } @Override - public void visit(SelectExpressionItem selectExpressionItem) { + public void visit(SelectItem selectExpressionItem) { selectExpressionItem.getExpression().accept(this); } - @Override - public void visit(RowConstructor rowConstructor) { - if (rowConstructor.getColumnDefinitions().isEmpty()) { - for (Expression expression : rowConstructor.getExprList().getExpressions()) { - expression.accept(this); - } - } else { - for (ColumnDefinition columnDefinition : rowConstructor.getColumnDefinitions()) { - columnDefinition.accept(this); - } - } - } - @Override public void visit(RowGetExpression rowGetExpression) { rowGetExpression.getExpression().accept(this); @@ -684,7 +641,19 @@ public void visit(Select selectBody) { } - public void visit(ColumnDefinition columnDefinition) { - columnDefinition.accept(this); + @Override + public void visit(TranscodingFunction transcodingFunction) { + + } + + @Override + public void visit(TrimFunction trimFunction) { + + } + + @Override + public void visit(RangeExpression rangeExpression) { + rangeExpression.getStartExpression().accept(this); + rangeExpression.getEndExpression().accept(this); } } diff --git a/src/main/java/net/sf/jsqlparser/expression/Function.java b/src/main/java/net/sf/jsqlparser/expression/Function.java index 0912d50e9..70066fc07 100644 --- a/src/main/java/net/sf/jsqlparser/expression/Function.java +++ b/src/main/java/net/sf/jsqlparser/expression/Function.java @@ -9,14 +9,14 @@ */ package net.sf.jsqlparser.expression; -import java.util.Arrays; -import java.util.List; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; -import net.sf.jsqlparser.schema.*; +import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.statement.select.OrderByElement; -import net.sf.jsqlparser.statement.select.PlainSelect; + +import java.util.Arrays; +import java.util.List; /** * A function as MAX,COUNT... @@ -128,7 +128,7 @@ public void setParameters(ExpressionList list) { * * @return the list of named parameters of the function (if any, else null) */ - public NamedExpressionList getNamedParameters() { + public NamedExpressionList getNamedParameters() { return namedParameters; } @@ -205,7 +205,7 @@ public String toString() { if (isAllColumns()) { b.append("ALL "); } - b.append(PlainSelect.getStringList(parameters.getExpressions(), true, false)); + b.append(parameters); if (orderByElements != null) { b.append(" ORDER BY "); boolean comma = false; @@ -272,6 +272,10 @@ public Function withParameters(ExpressionList parameters) { return this; } + public Function withParameters(Expression... parameters) { + return withParameters(new ExpressionList(parameters)); + } + public Function withNamedParameters(NamedExpressionList namedParameters) { this.setNamedParameters(namedParameters); return this; diff --git a/src/main/java/net/sf/jsqlparser/expression/JdbcNamedParameter.java b/src/main/java/net/sf/jsqlparser/expression/JdbcNamedParameter.java index 42cc78131..9e8d83792 100644 --- a/src/main/java/net/sf/jsqlparser/expression/JdbcNamedParameter.java +++ b/src/main/java/net/sf/jsqlparser/expression/JdbcNamedParameter.java @@ -12,16 +12,24 @@ import net.sf.jsqlparser.parser.ASTNodeAccessImpl; public class JdbcNamedParameter extends ASTNodeAccessImpl implements Expression { - + private String parameterCharacter = ":"; private String name; - public JdbcNamedParameter() { - } + public JdbcNamedParameter() {} public JdbcNamedParameter(String name) { this.name = name; } + public String getParameterCharacter() { + return parameterCharacter; + } + + public JdbcNamedParameter setParameterCharacter(String parameterCharacter) { + this.parameterCharacter = parameterCharacter; + return this; + } + public String getName() { return name; } @@ -37,7 +45,7 @@ public void accept(ExpressionVisitor expressionVisitor) { @Override public String toString() { - return ":" + name; + return parameterCharacter + name; } public JdbcNamedParameter withName(String name) { diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonAggregateOnNullType.java b/src/main/java/net/sf/jsqlparser/expression/JsonAggregateOnNullType.java index bc3ec2a00..d9e2b4c51 100644 --- a/src/main/java/net/sf/jsqlparser/expression/JsonAggregateOnNullType.java +++ b/src/main/java/net/sf/jsqlparser/expression/JsonAggregateOnNullType.java @@ -30,6 +30,9 @@ * @author Andreas Reichel */ public enum JsonAggregateOnNullType { - NULL - , ABSENT + NULL, ABSENT; + + public static JsonAggregateOnNullType from(String type) { + return Enum.valueOf(JsonAggregateOnNullType.class, type.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonAggregateUniqueKeysType.java b/src/main/java/net/sf/jsqlparser/expression/JsonAggregateUniqueKeysType.java index 2f0b18d21..aa1370595 100644 --- a/src/main/java/net/sf/jsqlparser/expression/JsonAggregateUniqueKeysType.java +++ b/src/main/java/net/sf/jsqlparser/expression/JsonAggregateUniqueKeysType.java @@ -30,6 +30,9 @@ * @author Andreas Reichel */ public enum JsonAggregateUniqueKeysType { - WITH - , WITHOUT + WITH, WITHOUT; + + public static JsonAggregateUniqueKeysType from(String type) { + return Enum.valueOf(JsonAggregateUniqueKeysType.class, type.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonFunctionType.java b/src/main/java/net/sf/jsqlparser/expression/JsonFunctionType.java index 5aafdfc2b..4502b3ca6 100644 --- a/src/main/java/net/sf/jsqlparser/expression/JsonFunctionType.java +++ b/src/main/java/net/sf/jsqlparser/expression/JsonFunctionType.java @@ -15,8 +15,9 @@ * @author Andreas Reichel */ public enum JsonFunctionType { - OBJECT - , ARRAY - , POSTGRES_OBJECT - , MYSQL_OBJECT + OBJECT, ARRAY, POSTGRES_OBJECT, MYSQL_OBJECT; + + public static JsonFunctionType from(String type) { + return Enum.valueOf(JsonFunctionType.class, type.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/expression/MySQLGroupConcat.java b/src/main/java/net/sf/jsqlparser/expression/MySQLGroupConcat.java index ee347ffa9..49161bbee 100644 --- a/src/main/java/net/sf/jsqlparser/expression/MySQLGroupConcat.java +++ b/src/main/java/net/sf/jsqlparser/expression/MySQLGroupConcat.java @@ -9,15 +9,15 @@ */ package net.sf.jsqlparser.expression; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import net.sf.jsqlparser.statement.select.OrderByElement; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.parser.ASTNodeAccessImpl; -import net.sf.jsqlparser.statement.select.OrderByElement; -import net.sf.jsqlparser.statement.select.PlainSelect; public class MySQLGroupConcat extends ASTNodeAccessImpl implements Expression { @@ -26,7 +26,7 @@ public class MySQLGroupConcat extends ASTNodeAccessImpl implements Expression { private List orderByElements; private String separator; - public ExpressionList getExpressionList() { + public ExpressionList getExpressionList() { return expressionList; } @@ -70,7 +70,7 @@ public String toString() { if (isDistinct()) { b.append("DISTINCT "); } - b.append(PlainSelect.getStringList(expressionList.getExpressions(), true, false)); + b.append(expressionList); if (orderByElements != null && !orderByElements.isEmpty()) { b.append(" ORDER BY "); for (int i = 0; i < orderByElements.size(); i++) { @@ -108,13 +108,16 @@ public MySQLGroupConcat withSeparator(String separator) { } public MySQLGroupConcat addOrderByElements(OrderByElement... orderByElements) { - List collection = Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new); Collections.addAll(collection, orderByElements); return this.withOrderByElements(collection); } - public MySQLGroupConcat addOrderByElements(Collection orderByElements) { - List collection = Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new); + public MySQLGroupConcat addOrderByElements( + Collection orderByElements) { + List collection = + Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new); collection.addAll(orderByElements); return this.withOrderByElements(collection); } diff --git a/src/main/java/net/sf/jsqlparser/expression/Parenthesis.java b/src/main/java/net/sf/jsqlparser/expression/Parenthesis.java index c83e273e3..51d3ef707 100644 --- a/src/main/java/net/sf/jsqlparser/expression/Parenthesis.java +++ b/src/main/java/net/sf/jsqlparser/expression/Parenthesis.java @@ -18,8 +18,7 @@ public class Parenthesis extends ASTNodeAccessImpl implements Expression { private Expression expression; - public Parenthesis() { - } + public Parenthesis() {} public Parenthesis(Expression expression) { setExpression(expression); @@ -40,7 +39,7 @@ public void accept(ExpressionVisitor expressionVisitor) { @Override public String toString() { - return "(" + expression + ")"; + return "(" + (expression != null ? expression : "") + ")"; } public Parenthesis withExpression(Expression expression) { diff --git a/src/main/java/net/sf/jsqlparser/expression/RangeExpression.java b/src/main/java/net/sf/jsqlparser/expression/RangeExpression.java new file mode 100644 index 000000000..69cba377d --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/RangeExpression.java @@ -0,0 +1,50 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; + +public class RangeExpression extends ASTNodeAccessImpl implements Expression { + private Expression startExpression; + private Expression endExpression; + + public RangeExpression(Expression startExpression, Expression endExpression) { + this.startExpression = startExpression; + this.endExpression = endExpression; + } + + public Expression getStartExpression() { + return startExpression; + } + + public RangeExpression setStartExpression(Expression startExpression) { + this.startExpression = startExpression; + return this; + } + + public Expression getEndExpression() { + return endExpression; + } + + public RangeExpression setEndExpression(Expression endExpression) { + this.endExpression = endExpression; + return this; + } + + @Override + public String toString() { + return startExpression + ":" + endExpression; + } + + @Override + public void accept(ExpressionVisitor expressionVisitor) { + expressionVisitor.visit(this); + } +} diff --git a/src/main/java/net/sf/jsqlparser/expression/RowConstructor.java b/src/main/java/net/sf/jsqlparser/expression/RowConstructor.java index 12891b915..6eabf3b70 100644 --- a/src/main/java/net/sf/jsqlparser/expression/RowConstructor.java +++ b/src/main/java/net/sf/jsqlparser/expression/RowConstructor.java @@ -9,33 +9,18 @@ */ package net.sf.jsqlparser.expression; -import java.util.ArrayList; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.parser.ASTNodeAccessImpl; -import net.sf.jsqlparser.statement.create.table.ColumnDefinition; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; -public class RowConstructor extends ASTNodeAccessImpl implements Expression { - private ExpressionList exprList; - private ArrayList columnDefinitions = new ArrayList<>(); +public class RowConstructor extends ParenthesedExpressionList + implements Expression { private String name = null; - public RowConstructor() { - } - - public ArrayList getColumnDefinitions() { - return columnDefinitions; - } - - public boolean addColumnDefinition(ColumnDefinition columnDefinition) { - return columnDefinitions.add(columnDefinition); - } + public RowConstructor() {} - public ExpressionList getExprList() { - return exprList; - } - - public void setExprList(ExpressionList exprList) { - this.exprList = exprList; + public RowConstructor(String name, ExpressionList expressionList) { + this.name = name; + addAll(expressionList); } public String getName() { @@ -46,30 +31,9 @@ public void setName(String name) { this.name = name; } - @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); - } - @Override public String toString() { - if (columnDefinitions.size()>0) { - StringBuilder builder = new StringBuilder(name != null ? name : ""); - builder.append("("); - int i = 0; - for (ColumnDefinition columnDefinition:columnDefinitions) { - builder.append(i>0 ? ", " : "").append(columnDefinition.toString()); - i++; - } - builder.append(")"); - return builder.toString(); - } - return (name != null ? name : "") + exprList.toString(); - } - - public RowConstructor withExprList(ExpressionList exprList) { - this.setExprList(exprList); - return this; + return (name != null ? name : "") + super.toString(); } public RowConstructor withName(String name) { diff --git a/src/main/java/net/sf/jsqlparser/expression/SafeCastExpression.java b/src/main/java/net/sf/jsqlparser/expression/SafeCastExpression.java deleted file mode 100644 index 28fad85d5..000000000 --- a/src/main/java/net/sf/jsqlparser/expression/SafeCastExpression.java +++ /dev/null @@ -1,95 +0,0 @@ -/*- - * #%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.expression; - -import net.sf.jsqlparser.parser.ASTNodeAccessImpl; -import net.sf.jsqlparser.statement.create.table.ColDataType; - -public class SafeCastExpression extends ASTNodeAccessImpl implements Expression { - - private Expression leftExpression; - private ColDataType type; - private RowConstructor rowConstructor; - private boolean useCastKeyword = true; - - public RowConstructor getRowConstructor() { - return rowConstructor; - } - - public void setRowConstructor(RowConstructor rowConstructor) { - this.rowConstructor = rowConstructor; - this.type = null; - } - - public SafeCastExpression withRowConstructor(RowConstructor rowConstructor) { - setRowConstructor(rowConstructor); - return this; - } - - public ColDataType getType() { - return type; - } - - public void setType(ColDataType type) { - this.type = type; - this.rowConstructor = null; - } - - public Expression getLeftExpression() { - return leftExpression; - } - - public void setLeftExpression(Expression expression) { - leftExpression = expression; - } - - @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); - } - - public boolean isUseCastKeyword() { - return useCastKeyword; - } - - public void setUseCastKeyword(boolean useCastKeyword) { - this.useCastKeyword = useCastKeyword; - } - - @Override - public String toString() { - if (useCastKeyword) { - return rowConstructor!=null - ? "SAFE_CAST(" + leftExpression + " AS " + rowConstructor.toString() + ")" - : "SAFE_CAST(" + leftExpression + " AS " + type.toString() + ")"; - } else { - return leftExpression + "::" + type.toString(); - } - } - - public SafeCastExpression withType(ColDataType type) { - this.setType(type); - return this; - } - - public SafeCastExpression withUseCastKeyword(boolean useCastKeyword) { - this.setUseCastKeyword(useCastKeyword); - return this; - } - - public SafeCastExpression withLeftExpression(Expression leftExpression) { - this.setLeftExpression(leftExpression); - return this; - } - - public E getLeftExpression(Class type) { - return type.cast(getLeftExpression()); - } -} diff --git a/src/main/java/net/sf/jsqlparser/expression/SpannerInterleaveIn.java b/src/main/java/net/sf/jsqlparser/expression/SpannerInterleaveIn.java index 59a8ec856..18cb16ac4 100644 --- a/src/main/java/net/sf/jsqlparser/expression/SpannerInterleaveIn.java +++ b/src/main/java/net/sf/jsqlparser/expression/SpannerInterleaveIn.java @@ -17,8 +17,11 @@ public class SpannerInterleaveIn { public enum OnDelete { - CASCADE, - NO_ACTION + CASCADE, NO_ACTION; + + public static OnDelete from(String action) { + return Enum.valueOf(OnDelete.class, action.toUpperCase()); + } } private Table table; @@ -60,7 +63,9 @@ public void setOnDelete(OnDelete action) { @Override public String toString() { return "INTERLEAVE IN PARENT " + getTable().getName() + - (getOnDelete() == null ? "" : " ON DELETE " + (getOnDelete() == OnDelete.CASCADE ? "CASCADE" : "NO ACTION")); + (getOnDelete() == null ? "" + : " ON DELETE " + + (getOnDelete() == OnDelete.CASCADE ? "CASCADE" : "NO ACTION")); } public SpannerInterleaveIn withTable(Table table) { @@ -72,4 +77,4 @@ public SpannerInterleaveIn withOnDelete(OnDelete action) { this.setOnDelete(action); return this; } -} \ No newline at end of file +} diff --git a/src/main/java/net/sf/jsqlparser/expression/TimezoneExpression.java b/src/main/java/net/sf/jsqlparser/expression/TimezoneExpression.java index 414dd27c1..6fe53154f 100644 --- a/src/main/java/net/sf/jsqlparser/expression/TimezoneExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/TimezoneExpression.java @@ -9,15 +9,15 @@ */ package net.sf.jsqlparser.expression; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; -import java.util.ArrayList; import java.util.List; public class TimezoneExpression extends ASTNodeAccessImpl implements Expression { private Expression leftExpression; - private ArrayList timezoneExpressions = new ArrayList<>(); + private ExpressionList timezoneExpressions = new ExpressionList<>(); public Expression getLeftExpression() { return leftExpression; diff --git a/src/main/java/net/sf/jsqlparser/expression/TranscodingFunction.java b/src/main/java/net/sf/jsqlparser/expression/TranscodingFunction.java new file mode 100644 index 000000000..61fa05290 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/TranscodingFunction.java @@ -0,0 +1,71 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; + +public class TranscodingFunction extends ASTNodeAccessImpl implements Expression { + private Expression expression; + private String transcodingName; + + public TranscodingFunction(Expression expression, String transcodingName) { + this.expression = expression; + this.transcodingName = transcodingName; + } + + public TranscodingFunction() { + this(null, null); + } + + public Expression getExpression() { + return expression; + } + + public void setExpression(Expression expression) { + this.expression = expression; + } + + public TranscodingFunction withExpression(Expression expression) { + this.setExpression(expression); + return this; + } + + public String getTranscodingName() { + return transcodingName; + } + + public void setTranscodingName(String transcodingName) { + this.transcodingName = transcodingName; + } + + public TranscodingFunction withTranscodingName(String transcodingName) { + this.setTranscodingName(transcodingName); + return this; + + } + + public void accept(ExpressionVisitor expressionVisitor) { + expressionVisitor.visit(this); + } + + public StringBuilder appendTo(StringBuilder builder) { + return builder + .append("CONVERT( ") + .append(expression) + .append(" USING ") + .append(transcodingName) + .append(" )"); + } + + @Override + public String toString() { + return appendTo(new StringBuilder()).toString(); + } +} diff --git a/src/main/java/net/sf/jsqlparser/expression/TrimFunction.java b/src/main/java/net/sf/jsqlparser/expression/TrimFunction.java new file mode 100644 index 000000000..40c4678af --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/TrimFunction.java @@ -0,0 +1,124 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; + +public class TrimFunction extends ASTNodeAccessImpl implements Expression { + public enum TrimSpecification { + LEADING, TRAILING, BOTH + } + + private TrimSpecification trimSpecification; + private Expression expression; + private Expression fromExpression; + private boolean isUsingFromKeyword; + + public TrimFunction(TrimSpecification trimSpecification, + Expression expression, + Expression fromExpression, + boolean isUsingFromKeyword) { + + this.trimSpecification = trimSpecification; + this.expression = expression; + this.fromExpression = fromExpression; + this.isUsingFromKeyword = isUsingFromKeyword; + } + + public TrimFunction() { + this(null, null, null, false); + } + + public TrimSpecification getTrimSpecification() { + return trimSpecification; + } + + public void setTrimSpecification(TrimSpecification trimSpecification) { + this.trimSpecification = trimSpecification; + } + + public TrimFunction withTrimSpecification(TrimSpecification trimSpecification) { + this.setTrimSpecification(trimSpecification); + return this; + } + + public Expression getExpression() { + return expression; + } + + public void setExpression(Expression expression) { + this.expression = expression; + } + + public TrimFunction withExpression(Expression expression) { + this.setExpression(expression); + return this; + } + + public Expression getFromExpression() { + return fromExpression; + } + + public void setFromExpression(Expression fromExpression) { + if (fromExpression == null) { + setUsingFromKeyword(false); + } + this.fromExpression = fromExpression; + } + + public TrimFunction withFromExpression(Expression fromExpression) { + this.setFromExpression(fromExpression); + return this; + } + + public boolean isUsingFromKeyword() { + return isUsingFromKeyword; + } + + public void setUsingFromKeyword(boolean useFromKeyword) { + isUsingFromKeyword = useFromKeyword; + } + + public TrimFunction withUsingFromKeyword(boolean useFromKeyword) { + this.setUsingFromKeyword(useFromKeyword); + return this; + } + + @Override + public void accept(ExpressionVisitor expressionVisitor) { + expressionVisitor.visit(this); + } + + StringBuilder appendTo(StringBuilder builder) { + builder.append("Trim("); + + if (trimSpecification != null) { + builder.append(" ").append(trimSpecification.name()); + } + + if (expression != null) { + builder.append(" ").append(expression); + } + + if (fromExpression != null) { + builder + .append(isUsingFromKeyword ? " FROM " : ", ") + .append(fromExpression); + } + builder.append(" )"); + + return builder; + } + + @Override + public String toString() { + return appendTo(new StringBuilder()).toString(); + } +} diff --git a/src/main/java/net/sf/jsqlparser/expression/TryCastExpression.java b/src/main/java/net/sf/jsqlparser/expression/TryCastExpression.java deleted file mode 100644 index ce967940e..000000000 --- a/src/main/java/net/sf/jsqlparser/expression/TryCastExpression.java +++ /dev/null @@ -1,95 +0,0 @@ -/*- - * #%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.expression; - -import net.sf.jsqlparser.parser.ASTNodeAccessImpl; -import net.sf.jsqlparser.statement.create.table.ColDataType; - -public class TryCastExpression extends ASTNodeAccessImpl implements Expression { - - private Expression leftExpression; - private ColDataType type; - private RowConstructor rowConstructor; - private boolean useCastKeyword = true; - - public RowConstructor getRowConstructor() { - return rowConstructor; - } - - public void setRowConstructor(RowConstructor rowConstructor) { - this.rowConstructor = rowConstructor; - this.type = null; - } - - public TryCastExpression withRowConstructor(RowConstructor rowConstructor) { - setRowConstructor(rowConstructor); - return this; - } - - public ColDataType getType() { - return type; - } - - public void setType(ColDataType type) { - this.type = type; - this.rowConstructor = null; - } - - public Expression getLeftExpression() { - return leftExpression; - } - - public void setLeftExpression(Expression expression) { - leftExpression = expression; - } - - @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); - } - - public boolean isUseCastKeyword() { - return useCastKeyword; - } - - public void setUseCastKeyword(boolean useCastKeyword) { - this.useCastKeyword = useCastKeyword; - } - - @Override - public String toString() { - if (useCastKeyword) { - return rowConstructor!=null - ? "TRY_CAST(" + leftExpression + " AS " + rowConstructor.toString() + ")" - : "TRY_CAST(" + leftExpression + " AS " + type.toString() + ")"; - } else { - return leftExpression + "::" + type.toString(); - } - } - - public TryCastExpression withType(ColDataType type) { - this.setType(type); - return this; - } - - public TryCastExpression withUseCastKeyword(boolean useCastKeyword) { - this.setUseCastKeyword(useCastKeyword); - return this; - } - - public TryCastExpression withLeftExpression(Expression leftExpression) { - this.setLeftExpression(leftExpression); - return this; - } - - public E getLeftExpression(Class type) { - return type.cast(getLeftExpression()); - } -} diff --git a/src/main/java/net/sf/jsqlparser/expression/ValueListExpression.java b/src/main/java/net/sf/jsqlparser/expression/ValueListExpression.java deleted file mode 100644 index 5023f4caa..000000000 --- a/src/main/java/net/sf/jsqlparser/expression/ValueListExpression.java +++ /dev/null @@ -1,47 +0,0 @@ -/*- - * #%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.expression; - -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.parser.ASTNodeAccessImpl; - -/** - * Models a list of expressions usable as condition.
- * This allows for instance the following expression : - * "[WHERE] (a, b) [OPERATOR] (c, d)" - * where "(a, b)" and "(c, d)" are instances of this class. - */ -public class ValueListExpression extends ASTNodeAccessImpl implements Expression { - - private ExpressionList expressionList; - - public ExpressionList getExpressionList() { - return expressionList; - } - - public void setExpressionList(ExpressionList expressionList) { - this.expressionList = expressionList; - } - - @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); - } - - @Override - public String toString() { - return expressionList.toString(); - } - - public ValueListExpression withExpressionList(ExpressionList expressionList) { - this.setExpressionList(expressionList); - return this; - } -} diff --git a/src/main/java/net/sf/jsqlparser/expression/WindowElement.java b/src/main/java/net/sf/jsqlparser/expression/WindowElement.java index 1213f0236..89c85e79a 100644 --- a/src/main/java/net/sf/jsqlparser/expression/WindowElement.java +++ b/src/main/java/net/sf/jsqlparser/expression/WindowElement.java @@ -14,9 +14,11 @@ public class WindowElement implements Serializable { public enum Type { + ROWS, RANGE; - ROWS, - RANGE + public static Type from(String type) { + return Enum.valueOf(Type.class, type.toUpperCase()); + } } private Type type; diff --git a/src/main/java/net/sf/jsqlparser/expression/WindowOffset.java b/src/main/java/net/sf/jsqlparser/expression/WindowOffset.java index e0a89d279..843f14150 100644 --- a/src/main/java/net/sf/jsqlparser/expression/WindowOffset.java +++ b/src/main/java/net/sf/jsqlparser/expression/WindowOffset.java @@ -14,11 +14,11 @@ public class WindowOffset implements Serializable { public enum Type { + PRECEDING, FOLLOWING, CURRENT, EXPR; - PRECEDING, - FOLLOWING, - CURRENT, - EXPR + public static Type from(String type) { + return Enum.valueOf(Type.class, type.toUpperCase()); + } } private Expression expression; diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExistsExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExistsExpression.java index 8fce8d04e..099fb054f 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExistsExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExistsExpression.java @@ -15,8 +15,8 @@ public class ExistsExpression extends ASTNodeAccessImpl implements Expression { - private Expression rightExpression; - private boolean not = false; + protected Expression rightExpression; + protected boolean not = false; public Expression getRightExpression() { return rightExpression; diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExpressionList.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExpressionList.java index 311fe4da6..9f08215b8 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExpressionList.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExpressionList.java @@ -9,85 +9,103 @@ */ package net.sf.jsqlparser.expression.operators.relational; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.ExpressionVisitor; +import net.sf.jsqlparser.parser.SimpleNode; + import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.List; -import java.util.Optional; -import net.sf.jsqlparser.expression.Expression; -import net.sf.jsqlparser.statement.select.PlainSelect; /** * A list of expressions, as in SELECT A FROM TAB WHERE B IN (expr1,expr2,expr3) */ -public class ExpressionList implements ItemsList, Serializable { +public class ExpressionList extends ArrayList + implements Expression, Serializable { + private transient SimpleNode node; - private List expressions; - private boolean usingBrackets = true; + public ExpressionList(Collection expressions) { + addAll(expressions); + } - public boolean isUsingBrackets() { - return usingBrackets; + public ExpressionList(List expressions) { + super(expressions); } - public void setUsingBrackets(boolean usingBrackets) { - this.usingBrackets = usingBrackets; + public ExpressionList(T... expressions) { + this(Arrays.asList(expressions)); } - - public ExpressionList withUsingBrackets(boolean usingBrackets) { - setUsingBrackets(usingBrackets); + + @Deprecated + public boolean isUsingBrackets() { + return false; + } + + @Deprecated + public List getExpressions() { return this; } - public ExpressionList() { + @Deprecated + public void setExpressions(List expressions) { + this.clear(); + this.addAll(expressions); } - public ExpressionList(List expressions) { - this.expressions = expressions; + public ExpressionList addExpression(T expression) { + this.add(expression); + return this; } - public ExpressionList(Expression... expressions) { - this.expressions = new ArrayList<>(Arrays.asList(expressions)); + public ExpressionList addExpressions(T... expressions) { + addAll(Arrays.asList(expressions)); + return this; } - public List getExpressions() { - return expressions; + public ExpressionList addExpressions(Collection expressions) { + addAll(expressions); + return this; } - public ExpressionList addExpressions(Expression... elements) { - List list = Optional.ofNullable(getExpressions()).orElseGet(ArrayList::new); - Collections.addAll(list, elements); - return withExpressions(list); + public ExpressionList withExpressions(T... expressions) { + this.clear(); + return addExpressions(expressions); } - public ExpressionList withExpressions(List expressions) { - this.setExpressions(expressions); - return this; + public ExpressionList withExpressions(Collection expressions) { + this.clear(); + return addExpressions(expressions); } - public void setExpressions(List expressions) { - this.expressions = expressions; + public StringBuilder appendTo(StringBuilder builder) { + for (int i = 0; i < size(); i++) { + if (i > 0) { + builder.append(", "); + } + builder.append(get(i)); + } + return builder; } - @Deprecated - public ExpressionList withBrackets(boolean brackets) { - return withUsingBrackets(brackets); + @Override + public String toString() { + return appendTo(new StringBuilder()).toString(); } @Override - public void accept(ItemsListVisitor itemsListVisitor) { - itemsListVisitor.visit(this); + public void accept(ExpressionVisitor expressionVisitor) { + expressionVisitor.visit(this); } @Override - public String toString() { - return PlainSelect.getStringList(expressions, true, usingBrackets); + public SimpleNode getASTNode() { + return node; } - public ExpressionList addExpressions(Collection expressions) { - List collection = Optional.ofNullable(getExpressions()).orElseGet(ArrayList::new); - collection.addAll(expressions); - return this.withExpressions(collection); + @Override + public void setASTNode(SimpleNode node) { + this.node = node; } } diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/FullTextSearch.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/FullTextSearch.java index 639f0b182..83c1f7b3a 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/FullTextSearch.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/FullTextSearch.java @@ -9,12 +9,6 @@ */ package net.sf.jsqlparser.expression.operators.relational; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.expression.JdbcNamedParameter; @@ -23,9 +17,14 @@ import net.sf.jsqlparser.parser.ASTNodeAccessImpl; import net.sf.jsqlparser.schema.Column; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.Optional; + public class FullTextSearch extends ASTNodeAccessImpl implements Expression { - private List _matchColumns; + private ExpressionList _matchColumns; private Expression _againstValue; private String _searchModifier; @@ -33,22 +32,22 @@ public FullTextSearch() { } - public void setMatchColumns(List columns) { + public void setMatchColumns(ExpressionList columns) { this._matchColumns = columns; } - public List getMatchColumns() { + public ExpressionList getMatchColumns() { return this._matchColumns; } public void setAgainstValue(StringValue val) { this._againstValue = val; } - + public void setAgainstValue(JdbcNamedParameter val) { this._againstValue = val; } - + public void setAgainstValue(JdbcParameter val) { this._againstValue = val; } @@ -87,7 +86,7 @@ public String toString() { (this._searchModifier != null ? " " + this._searchModifier : "") + ")"; } - public FullTextSearch withMatchColumns(List matchColumns) { + public FullTextSearch withMatchColumns(ExpressionList matchColumns) { this.setMatchColumns(matchColumns); return this; } @@ -103,13 +102,12 @@ public FullTextSearch withSearchModifier(String searchModifier) { } public FullTextSearch addMatchColumns(Column... matchColumns) { - List collection = Optional.ofNullable(getMatchColumns()).orElseGet(ArrayList::new); - Collections.addAll(collection, matchColumns); - return this.withMatchColumns(collection); + return this.addMatchColumns(Arrays.asList(matchColumns)); } public FullTextSearch addMatchColumns(Collection matchColumns) { - List collection = Optional.ofNullable(getMatchColumns()).orElseGet(ArrayList::new); + ExpressionList collection = + Optional.ofNullable(getMatchColumns()).orElseGet(ExpressionList::new); collection.addAll(matchColumns); return this.withMatchColumns(collection); } diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/InExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/InExpression.java index 89f410870..e359c693a 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/InExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/InExpression.java @@ -13,20 +13,19 @@ import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; -public class InExpression extends ASTNodeAccessImpl implements Expression, SupportsOldOracleJoinSyntax { +public class InExpression extends ASTNodeAccessImpl + implements Expression, SupportsOldOracleJoinSyntax { private Expression leftExpression; - private ItemsList rightItemsList; private boolean not = false; private Expression rightExpression; private int oldOracleJoinSyntax = NO_ORACLE_JOIN; - public InExpression() { - } + public InExpression() {} - public InExpression(Expression leftExpression, ItemsList itemsList) { - setLeftExpression(leftExpression); - setRightItemsList(itemsList); + public InExpression(Expression leftExpression, Expression rightExpression) { + this.leftExpression = leftExpression; + this.rightExpression = rightExpression; } @Override @@ -34,7 +33,8 @@ public void setOldOracleJoinSyntax(int oldOracleJoinSyntax) { this.oldOracleJoinSyntax = oldOracleJoinSyntax; if (oldOracleJoinSyntax < 0 || oldOracleJoinSyntax > 1) { throw new IllegalArgumentException( - "unexpected join type for oracle found with IN (type=" + oldOracleJoinSyntax + ")"); + "unexpected join type for oracle found with IN (type=" + oldOracleJoinSyntax + + ")"); } } @@ -43,23 +43,10 @@ public int getOldOracleJoinSyntax() { return oldOracleJoinSyntax; } - public ItemsList getRightItemsList() { - return rightItemsList; - } - public Expression getLeftExpression() { return leftExpression; } - public InExpression withRightItemsList(ItemsList list) { - this.setRightItemsList(list); - return this; - } - - public final void setRightItemsList(ItemsList list) { - rightItemsList = list; - } - public InExpression withLeftExpression(Expression expression) { this.setLeftExpression(expression); return this; @@ -104,11 +91,7 @@ public String toString() { statementBuilder.append("NOT "); } statementBuilder.append("IN "); - if (rightExpression == null) { - statementBuilder.append(rightItemsList); - } else { - statementBuilder.append(rightExpression); - } + statementBuilder.append(rightExpression); return statementBuilder.toString(); } @@ -146,10 +129,6 @@ public InExpression withNot(boolean not) { return this; } - public E getRightItemsList(Class type) { - return type.cast(getRightItemsList()); - } - public E getLeftExpression(Class type) { return type.cast(getLeftExpression()); } diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsList.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsList.java deleted file mode 100644 index caffa1fe1..000000000 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsList.java +++ /dev/null @@ -1,18 +0,0 @@ -/*- - * #%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.expression.operators.relational; - -/** - * Values of an "INSERT" statement (for example a SELECT or a list of expressions) - */ -public interface ItemsList { - - void accept(ItemsListVisitor itemsListVisitor); -} diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsListVisitor.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsListVisitor.java deleted file mode 100644 index 02de5577c..000000000 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsListVisitor.java +++ /dev/null @@ -1,23 +0,0 @@ -/*- - * #%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.expression.operators.relational; - -import net.sf.jsqlparser.statement.select.ParenthesedSelect; - -public interface ItemsListVisitor { - - void visit(ParenthesedSelect selectBody); - - void visit(ExpressionList expressionList); - - void visit(NamedExpressionList namedExpressionList); - - void visit(MultiExpressionList multiExprList); -} 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 deleted file mode 100644 index 27fbf1666..000000000 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ItemsListVisitorAdapter.java +++ /dev/null @@ -1,38 +0,0 @@ -/*- - * #%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.expression.operators.relational; - -import net.sf.jsqlparser.statement.select.ParenthesedSelect; - -@SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) -public class ItemsListVisitorAdapter implements ItemsListVisitor { - - @Override - public void visit(ParenthesedSelect subSelect) { - - } - - @Override - public void visit(NamedExpressionList namedExpressionList) { - - } - - @Override - public void visit(ExpressionList expressionList) { - - } - - @Override - public void visit(MultiExpressionList multiExprList) { - for (ExpressionList list : multiExprList.getExprList()) { - visit(list); - } - } -} diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpression.java new file mode 100644 index 000000000..590606629 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpression.java @@ -0,0 +1,63 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression.operators.relational; + +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.ExpressionVisitor; +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; + +public class MemberOfExpression extends ASTNodeAccessImpl implements Expression { + + Expression leftExpression; + Expression rightExpression; + boolean isNot; + + public MemberOfExpression(Expression leftExpression, Expression rightExpression) { + this.leftExpression = leftExpression; + this.rightExpression = rightExpression; + } + + public Expression getLeftExpression() { + return leftExpression; + } + + public MemberOfExpression setLeftExpression(Expression leftExpression) { + this.leftExpression = leftExpression; + return this; + } + + public Expression getRightExpression() { + return rightExpression; + } + + public MemberOfExpression setRightExpression(Expression rightExpression) { + this.rightExpression = rightExpression; + return this; + } + + public boolean isNot() { + return isNot; + } + + public MemberOfExpression setNot(boolean not) { + isNot = not; + return this; + } + + @Override + public String toString() { + return leftExpression + " MEMBER OF " + rightExpression; + } + + @Override + public void accept(ExpressionVisitor expressionVisitor) { + expressionVisitor.visit(this); + } +} diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/MultiExpressionList.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/MultiExpressionList.java deleted file mode 100644 index 2466a2981..000000000 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/MultiExpressionList.java +++ /dev/null @@ -1,86 +0,0 @@ -/*- - * #%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.expression.operators.relational; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import net.sf.jsqlparser.expression.Expression; - -/** - * A list of ExpressionList items. e.g. multi values of insert statements. This one allows only - * equally sized ExpressionList. - */ -public class MultiExpressionList implements ItemsList { - - private List expressionLists; - - public MultiExpressionList() { - this.expressionLists = new ArrayList<>(); - } - - @Override - public void accept(ItemsListVisitor itemsListVisitor) { - itemsListVisitor.visit(this); - } - - @Deprecated - public List getExprList() { - return getExpressionLists(); - } - - public List getExpressionLists() { - return expressionLists; - } - - public void setExpressionLists(List expressionLists) { - this.expressionLists = expressionLists; - } - - public MultiExpressionList withExpressionLists(List expressionLists) { - this.setExpressionLists(expressionLists); - return this; - } - - public void addExpressionList(ExpressionList el) { - if (!expressionLists.isEmpty() - && expressionLists.get(0).getExpressions().size() != el.getExpressions().size()) { - throw new IllegalArgumentException("different count of parameters"); - } - expressionLists.add(el); - } - - public void addExpressionList(List list) { - addExpressionList(new ExpressionList(list)); - } - - public void addExpressionList(Expression... expr) { - addExpressionList(new ExpressionList(Arrays.asList(expr))); - } - - public MultiExpressionList addExpressionLists(ExpressionList... expr) { - Stream.of(expr).forEach(this::addExpressionList); - return this; - } - - public MultiExpressionList addExpressionLists(Collection expr) { - expr.stream().forEach(this::addExpressionList); - return this; - } - - @Override - public String toString() { - return expressionLists.stream().map(ExpressionList::toString).collect(Collectors.joining(", ")); - } -} diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/NamedExpressionList.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/NamedExpressionList.java index 8ee675640..e7473cf0d 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/NamedExpressionList.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/NamedExpressionList.java @@ -9,68 +9,41 @@ */ package net.sf.jsqlparser.expression.operators.relational; +import net.sf.jsqlparser.expression.Expression; + import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; -import net.sf.jsqlparser.expression.Expression; /** - * A list of named expressions, as in - * as in select substr('xyzzy' from 2 for 3) + * A list of named expressions, as in as in select substr('xyzzy' from 2 for 3) */ -public class NamedExpressionList implements ItemsList { - - private List expressions; +public class NamedExpressionList extends ExpressionList { private List names; - public NamedExpressionList() { - } - - public NamedExpressionList(List expressions) { - this.expressions = expressions; - } - - public NamedExpressionList(Expression... expressions) { - this.expressions = Arrays.asList(expressions); - } - - public List getExpressions() { - return expressions; - } - public List getNames() { return names; } - public void setExpressions(List list) { - expressions = list; - } - public void setNames(List list) { names = list; } - @Override - public void accept(ItemsListVisitor itemsListVisitor) { - itemsListVisitor.visit(this); - } - @Override public String toString() { StringBuilder ret = new StringBuilder(); ret.append("("); - for (int i = 0; i < expressions.size(); i++) { + for (int i = 0; i < size(); i++) { if (i > 0) { ret.append(" "); } if (!names.get(i).equals("")) { - ret.append(names.get(i)).append(" ").append(expressions.get(i)); + ret.append(names.get(i)).append(" ").append(get(i)); } else { - ret.append(expressions.get(i)); + ret.append(get(i)); } } ret.append(")"); @@ -78,28 +51,11 @@ public String toString() { return ret.toString(); } - public NamedExpressionList withExpressions(List expressions) { - this.setExpressions(expressions); - return this; - } - public NamedExpressionList withNames(List names) { this.setNames(names); return this; } - public NamedExpressionList addExpressions(Expression... expressions) { - List collection = Optional.ofNullable(getExpressions()).orElseGet(ArrayList::new); - Collections.addAll(collection, expressions); - return this.withExpressions(collection); - } - - public NamedExpressionList addExpressions(Collection expressions) { - List collection = Optional.ofNullable(getExpressions()).orElseGet(ArrayList::new); - collection.addAll(expressions); - return this.withExpressions(collection); - } - public NamedExpressionList addNames(String... names) { List collection = Optional.ofNullable(getNames()).orElseGet(ArrayList::new); Collections.addAll(collection, names); diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ParenthesedExpressionList.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ParenthesedExpressionList.java new file mode 100644 index 000000000..13efb57c8 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ParenthesedExpressionList.java @@ -0,0 +1,41 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression.operators.relational; + +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.statement.select.PlainSelect; + +import java.util.Arrays; +import java.util.Collection; + +public class ParenthesedExpressionList extends ExpressionList { + public ParenthesedExpressionList() {} + + public ParenthesedExpressionList(ExpressionList expressions) { + addAll(expressions); + } + + public ParenthesedExpressionList(T... expressions) { + addAll(Arrays.asList(expressions)); + } + + public ParenthesedExpressionList(Collection expressions) { + addAll(expressions); + } + + public static ParenthesedExpressionList from(ExpressionList expressions) { + return new ParenthesedExpressionList(expressions); + } + + @Override + public String toString() { + return PlainSelect.getStringList(this, true, true); + } +} diff --git a/src/main/java/net/sf/jsqlparser/parser/CCJSqlParserUtil.java b/src/main/java/net/sf/jsqlparser/parser/CCJSqlParserUtil.java index 81cf095b9..c366cb80e 100644 --- a/src/main/java/net/sf/jsqlparser/parser/CCJSqlParserUtil.java +++ b/src/main/java/net/sf/jsqlparser/parser/CCJSqlParserUtil.java @@ -19,6 +19,9 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Consumer; +import java.util.logging.Level; +import java.util.logging.Logger; + import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.parser.feature.Feature; @@ -33,13 +36,25 @@ @SuppressWarnings("PMD.CyclomaticComplexity") public final class CCJSqlParserUtil { + public final static Logger LOGGER = Logger.getLogger(CCJSqlParserUtil.class.getName()); + static { + LOGGER.setLevel(Level.OFF); + } + public final static int ALLOWED_NESTING_DEPTH = 10; private CCJSqlParserUtil() {} public static Statement parse(Reader statementReader) throws JSQLParserException { + ExecutorService executorService = Executors.newSingleThreadExecutor(); + Statement statement = null; CCJSqlParser parser = new CCJSqlParser(new StreamProvider(statementReader)); - return parseStatement(parser); + try { + statement = parseStatement(parser, executorService); + } finally { + executorService.shutdown(); + } + return statement; } public static Statement parse(String sql) throws JSQLParserException { @@ -62,22 +77,42 @@ public static Statement parse(String sql) throws JSQLParserException { */ public static Statement parse(String sql, Consumer consumer) throws JSQLParserException { + + ExecutorService executorService = Executors.newSingleThreadExecutor(); + Statement statement = null; + try { + statement = parse(sql, executorService, consumer); + } finally { + executorService.shutdown(); + } + return statement; + } + + public static Statement parse(String sql, ExecutorService executorService, + Consumer consumer) + throws JSQLParserException { Statement statement = null; // first, try to parse fast and simple + CCJSqlParser parser = newParser(sql); + if (consumer != null) { + consumer.accept(parser); + } + boolean allowComplex = parser.getConfiguration().getAsBoolean(Feature.allowComplexParsing); + LOGGER.info("Allowed Complex Parsing: " + allowComplex); try { - CCJSqlParser parser = newParser(sql).withAllowComplexParsing(false); - if (consumer != null) { - consumer.accept(parser); - } - statement = parseStatement(parser); + LOGGER.info("Trying SIMPLE parsing " + (allowComplex ? "first" : "only")); + statement = parseStatement(parser.withAllowComplexParsing(false), executorService); } catch (JSQLParserException ex) { - if (getNestingDepth(sql) <= ALLOWED_NESTING_DEPTH) { - CCJSqlParser parser = newParser(sql).withAllowComplexParsing(true); + LOGGER.info("Nesting Depth" + getNestingDepth(sql)); + if (allowComplex && getNestingDepth(sql) <= ALLOWED_NESTING_DEPTH) { + LOGGER.info("Trying COMPLEX parsing when SIMPLE parsing failed"); + // beware: the parser must not be reused, but needs to be re-initiated + parser = newParser(sql); if (consumer != null) { consumer.accept(parser); } - statement = parseStatement(parser); + statement = parseStatement(parser.withAllowComplexParsing(true), executorService); } else { throw ex; } @@ -252,26 +287,28 @@ public static Expression parseCondExpression(String conditionalExpressionStr, } /** - * @param parser - * @return the statement parsed - * @throws JSQLParserException + * @param parser the Parser armed with a Statement text + * @param executorService the Executor Service for parsing within a Thread + * @return the parsed Statement + * @throws JSQLParserException when either the Statement can't be parsed or the configured + * timeout is reached */ - public static Statement parseStatement(CCJSqlParser parser) throws JSQLParserException { + + public static Statement parseStatement(CCJSqlParser parser, ExecutorService executorService) + throws JSQLParserException { Statement statement = null; + Future future = executorService.submit(new Callable() { + @Override + public Statement call() throws Exception { + return parser.Statement(); + } + }); try { - ExecutorService executorService = Executors.newSingleThreadExecutor(); - Future future = executorService.submit(new Callable() { - @Override - public Statement call() throws Exception { - return parser.Statement(); - } - }); - executorService.shutdown(); - - statement = future.get( parser.getConfiguration().getAsLong(Feature.timeOut), TimeUnit.MILLISECONDS); - + statement = future.get(parser.getConfiguration().getAsLong(Feature.timeOut), + TimeUnit.MILLISECONDS); } catch (TimeoutException ex) { parser.interrupted = true; + future.cancel(true); throw new JSQLParserException("Time out occurred.", ex); } catch (Exception ex) { throw new JSQLParserException(ex); @@ -288,57 +325,71 @@ public static Statements parseStatements(String sqls) throws JSQLParserException return parseStatements(sqls, null); } + public static Statements parseStatements(String sqls, Consumer consumer) + throws JSQLParserException { + ExecutorService executorService = Executors.newSingleThreadExecutor(); + final Statements statements = parseStatements(sqls, executorService, consumer); + executorService.shutdown(); + + return statements; + } + /** * Parse a statement list. * * @return the statements parsed */ - public static Statements parseStatements(String sqls, Consumer consumer) + public static Statements parseStatements(String sqls, ExecutorService executorService, + Consumer consumer) throws JSQLParserException { Statements statements = null; + CCJSqlParser parser = newParser(sqls); + if (consumer != null) { + consumer.accept(parser); + } + boolean allowComplex = parser.getConfiguration().getAsBoolean(Feature.allowComplexParsing); + // first, try to parse fast and simple try { - CCJSqlParser parser = newParser(sqls).withAllowComplexParsing(false); - if (consumer != null) { - consumer.accept(parser); - } - statements = parseStatements(parser); + statements = parseStatements(parser.withAllowComplexParsing(false), executorService); } catch (JSQLParserException ex) { // when fast simple parsing fails, try complex parsing but only if it has a chance to // succeed - if (getNestingDepth(sqls) <= ALLOWED_NESTING_DEPTH) { - CCJSqlParser parser = newParser(sqls).withAllowComplexParsing(true); + if (allowComplex && getNestingDepth(sqls) <= ALLOWED_NESTING_DEPTH) { + // beware: parser must not be re-used but needs to be re-initiated + parser = newParser(sqls); if (consumer != null) { consumer.accept(parser); } - statements = parseStatements(parser); + statements = parseStatements(parser.withAllowComplexParsing(true), executorService); } } return statements; } /** - * @param parser - * @return the statements parsed - * @throws JSQLParserException + * @param parser the Parser armed with a Statement text + * @param executorService the Executor Service for parsing within a Thread + * @return the Statements (representing a List of single statements) + * @throws JSQLParserException when either the Statement can't be parsed or the configured + * timeout is reached */ - public static Statements parseStatements(CCJSqlParser parser) throws JSQLParserException { + public static Statements parseStatements(CCJSqlParser parser, ExecutorService executorService) + throws JSQLParserException { Statements statements = null; + Future future = executorService.submit(new Callable() { + @Override + public Statements call() throws Exception { + return parser.Statements(); + } + }); try { - ExecutorService executorService = Executors.newSingleThreadExecutor(); - Future future = executorService.submit(new Callable() { - @Override - public Statements call() throws Exception { - return parser.Statements(); - } - }); - executorService.shutdown(); - - statements = future.get( parser.getConfiguration().getAsLong(Feature.timeOut) , TimeUnit.MILLISECONDS); - + statements = future.get(parser.getConfiguration().getAsLong(Feature.timeOut), + TimeUnit.MILLISECONDS); } catch (TimeoutException ex) { parser.interrupted = true; + future.cancel(true); throw new JSQLParserException("Time out occurred.", ex); } catch (Exception ex) { throw new JSQLParserException(ex); diff --git a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java index 4212b2ede..8d7be17a1 100644 --- a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java +++ b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java @@ -33,7 +33,7 @@ public class ParserKeywordsUtils { public final static int RESTRICTED_ALIAS = 32; public final static int RESTRICTED_SQL2016 = 64; - public final static int RESTRICTED_JSQLPARSER = 128 + public final static int RESTRICTED_JSQLPARSER = 128 | RESTRICTED_FUNCTION | RESTRICTED_SCHEMA | RESTRICTED_TABLE @@ -45,128 +45,75 @@ public class ParserKeywordsUtils { // Classification follows http://www.h2database.com/html/advanced.html#keywords public final static Object[][] ALL_RESERVED_KEYWORDS = { - { "ABSENT", RESTRICTED_JSQLPARSER } - , { "ALL" , RESTRICTED_SQL2016 } - , { "AND" , RESTRICTED_SQL2016 } - , { "ANY" , RESTRICTED_JSQLPARSER } - , { "AS" , RESTRICTED_SQL2016 } - , { "BETWEEN" , RESTRICTED_SQL2016 } - , { "BOTH" , RESTRICTED_SQL2016 } - , { "CASEWHEN" , RESTRICTED_ALIAS } - , { "CHECK" , RESTRICTED_SQL2016 } - , { "CONNECT" , RESTRICTED_ALIAS } - , { "CONNECT_BY_ROOT" , RESTRICTED_JSQLPARSER } - , { "CONSTRAINT" , RESTRICTED_SQL2016 } - , { "CREATE" , RESTRICTED_ALIAS } - , { "CROSS" , RESTRICTED_SQL2016 } - , { "CURRENT" , RESTRICTED_JSQLPARSER } - , { "DISTINCT" , RESTRICTED_SQL2016 } - , { "DOUBLE" , RESTRICTED_ALIAS } - , { "ELSE" , RESTRICTED_JSQLPARSER } - , { "EXCEPT" , RESTRICTED_SQL2016 } - , { "EXISTS" , RESTRICTED_SQL2016 } - , { "FETCH" , RESTRICTED_SQL2016 } - , { "FOR" , RESTRICTED_SQL2016 } - , { "FORCE" , RESTRICTED_SQL2016 } - , { "FOREIGN" , RESTRICTED_SQL2016 } - , { "FROM" , RESTRICTED_SQL2016 } - , { "FULL", RESTRICTED_SQL2016 } - , { "GROUP", RESTRICTED_SQL2016 } - , { "GROUPING" , RESTRICTED_ALIAS } - , { "HAVING" , RESTRICTED_SQL2016 } - , { "IF" , RESTRICTED_SQL2016 } - , { "IIF" , RESTRICTED_ALIAS } - , { "IGNORE" , RESTRICTED_ALIAS } - , { "ILIKE" , RESTRICTED_SQL2016 } - , { "IN" , RESTRICTED_SQL2016 } - , { "INNER" , RESTRICTED_SQL2016 } - , { "INTERSECT" , RESTRICTED_SQL2016 } - , { "INTERVAL", RESTRICTED_SQL2016 } - , { "INTO" , RESTRICTED_JSQLPARSER } - , { "IS" , RESTRICTED_SQL2016 } - , { "JOIN" , RESTRICTED_JSQLPARSER } - , { "LATERAL" , RESTRICTED_SQL2016 } - , { "LEFT", RESTRICTED_SQL2016 } - , { "LIKE" , RESTRICTED_SQL2016 } - , { "LIMIT" , RESTRICTED_SQL2016 } - , { "MINUS" , RESTRICTED_SQL2016 } - , { "NATURAL" , RESTRICTED_SQL2016 } - , { "NOCYCLE" , RESTRICTED_JSQLPARSER } - , { "NOT", RESTRICTED_SQL2016 } - , { "NULL" , RESTRICTED_SQL2016 } - , { "OFFSET" , RESTRICTED_SQL2016 } - , { "ON" , RESTRICTED_SQL2016 } - , { "ONLY" , RESTRICTED_JSQLPARSER } - , { "OPTIMIZE" , RESTRICTED_ALIAS } - , { "OR" , RESTRICTED_SQL2016 } - , { "ORDER" , RESTRICTED_SQL2016 } - , { "OUTER" , RESTRICTED_JSQLPARSER } - , { "OUTPUT" , RESTRICTED_JSQLPARSER } - , { "OPTIMIZE ", RESTRICTED_JSQLPARSER } - , { "PIVOT" , RESTRICTED_JSQLPARSER } - , { "PROCEDURE" , RESTRICTED_ALIAS } - , { "PUBLIC", RESTRICTED_ALIAS } - , { "RECURSIVE" , RESTRICTED_SQL2016 } - , { "REGEXP" , RESTRICTED_SQL2016 } - , { "RETURNING" , RESTRICTED_JSQLPARSER } - , { "RIGHT" , RESTRICTED_SQL2016 } - , { "SEL" , RESTRICTED_ALIAS } - , { "SELECT" , RESTRICTED_ALIAS } - , { "SEMI" , RESTRICTED_JSQLPARSER } - , { "SET" , RESTRICTED_JSQLPARSER } - , { "SOME" , RESTRICTED_JSQLPARSER } - , { "START" , RESTRICTED_JSQLPARSER } - , { "TABLES" , RESTRICTED_ALIAS } - , { "TOP" , RESTRICTED_SQL2016 } - , { "TRAILING", RESTRICTED_SQL2016 } - , { "UNBOUNDED" , RESTRICTED_JSQLPARSER } - , { "UNION" , RESTRICTED_SQL2016 } - , { "UNIQUE" , RESTRICTED_SQL2016 } - , { "UNPIVOT" , RESTRICTED_JSQLPARSER } - , { "USE" , RESTRICTED_JSQLPARSER } - , { "USING" , RESTRICTED_SQL2016 } - , { "SQL_CACHE" , RESTRICTED_JSQLPARSER } - , { "SQL_CALC_FOUND_ROWS" , RESTRICTED_JSQLPARSER } - , { "SQL_NO_CACHE" , RESTRICTED_JSQLPARSER } - , { "STRAIGHT_JOIN" , RESTRICTED_JSQLPARSER } - , { "VALUE", RESTRICTED_JSQLPARSER } - , { "VALUES" , RESTRICTED_SQL2016 } - , { "VARYING" , RESTRICTED_JSQLPARSER } - , { "WHEN" , RESTRICTED_SQL2016 } - , { "WHERE" , RESTRICTED_SQL2016 } - , { "WINDOW" , RESTRICTED_SQL2016 } - , { "WITH" , RESTRICTED_SQL2016 } - , { "XOR", RESTRICTED_JSQLPARSER } - , { "XMLSERIALIZE" , RESTRICTED_JSQLPARSER } + {"ABSENT", RESTRICTED_JSQLPARSER}, {"ALL", RESTRICTED_SQL2016}, + {"AND", RESTRICTED_SQL2016}, {"ANY", RESTRICTED_JSQLPARSER}, {"AS", RESTRICTED_SQL2016}, + {"BETWEEN", RESTRICTED_SQL2016}, {"BOTH", RESTRICTED_SQL2016}, + {"CASEWHEN", RESTRICTED_ALIAS}, {"CHECK", RESTRICTED_SQL2016}, + {"CONNECT", RESTRICTED_ALIAS}, {"CONNECT_BY_ROOT", RESTRICTED_JSQLPARSER}, + {"CONSTRAINT", RESTRICTED_SQL2016}, {"CREATE", RESTRICTED_ALIAS}, + {"CROSS", RESTRICTED_SQL2016}, {"CURRENT", RESTRICTED_JSQLPARSER}, + {"DISTINCT", RESTRICTED_SQL2016}, {"DOUBLE", RESTRICTED_ALIAS}, + {"ELSE", RESTRICTED_JSQLPARSER}, {"EXCEPT", RESTRICTED_SQL2016}, + {"EXISTS", RESTRICTED_SQL2016}, {"FETCH", RESTRICTED_SQL2016}, + {"FINAL", RESTRICTED_JSQLPARSER}, {"FOR", RESTRICTED_SQL2016}, + {"FORCE", RESTRICTED_SQL2016}, {"FOREIGN", RESTRICTED_SQL2016}, + {"FROM", RESTRICTED_SQL2016}, {"FULL", RESTRICTED_SQL2016}, + {"GROUP", RESTRICTED_SQL2016}, {"GROUPING", RESTRICTED_ALIAS}, + {"HAVING", RESTRICTED_SQL2016}, {"IF", RESTRICTED_SQL2016}, {"IIF", RESTRICTED_ALIAS}, + {"IGNORE", RESTRICTED_ALIAS}, {"ILIKE", RESTRICTED_SQL2016}, {"IN", RESTRICTED_SQL2016}, + {"INNER", RESTRICTED_SQL2016}, {"INTERSECT", RESTRICTED_SQL2016}, + {"INTERVAL", RESTRICTED_SQL2016}, {"INTO", RESTRICTED_JSQLPARSER}, + {"IS", RESTRICTED_SQL2016}, {"JOIN", RESTRICTED_JSQLPARSER}, + {"LATERAL", RESTRICTED_SQL2016}, {"LEFT", RESTRICTED_SQL2016}, + {"LIKE", RESTRICTED_SQL2016}, {"LIMIT", RESTRICTED_SQL2016}, + {"MINUS", RESTRICTED_SQL2016}, {"NATURAL", RESTRICTED_SQL2016}, + {"NOCYCLE", RESTRICTED_JSQLPARSER}, {"NOT", RESTRICTED_SQL2016}, + {"NULL", RESTRICTED_SQL2016}, {"OFFSET", RESTRICTED_SQL2016}, + {"ON", RESTRICTED_SQL2016}, {"ONLY", RESTRICTED_JSQLPARSER}, + {"OPTIMIZE", RESTRICTED_ALIAS}, {"OR", RESTRICTED_SQL2016}, + {"ORDER", RESTRICTED_SQL2016}, {"OUTER", RESTRICTED_JSQLPARSER}, + {"OUTPUT", RESTRICTED_JSQLPARSER}, {"OPTIMIZE ", RESTRICTED_JSQLPARSER}, + {"PIVOT", RESTRICTED_JSQLPARSER}, {"PROCEDURE", RESTRICTED_ALIAS}, + {"PUBLIC", RESTRICTED_ALIAS}, {"RECURSIVE", RESTRICTED_SQL2016}, + {"REGEXP", RESTRICTED_SQL2016}, {"RETURNING", RESTRICTED_JSQLPARSER}, + {"RIGHT", RESTRICTED_SQL2016}, {"SEL", RESTRICTED_ALIAS}, {"SELECT", RESTRICTED_ALIAS}, + {"SEMI", RESTRICTED_JSQLPARSER}, {"SET", RESTRICTED_JSQLPARSER}, + {"SOME", RESTRICTED_JSQLPARSER}, {"START", RESTRICTED_JSQLPARSER}, + {"TABLES", RESTRICTED_ALIAS}, {"TOP", RESTRICTED_SQL2016}, + {"TRAILING", RESTRICTED_SQL2016}, {"UNBOUNDED", RESTRICTED_JSQLPARSER}, + {"UNION", RESTRICTED_SQL2016}, {"UNIQUE", RESTRICTED_SQL2016}, + {"UNPIVOT", RESTRICTED_JSQLPARSER}, {"USE", RESTRICTED_JSQLPARSER}, + {"USING", RESTRICTED_SQL2016}, {"SQL_CACHE", RESTRICTED_JSQLPARSER}, + {"SQL_CALC_FOUND_ROWS", RESTRICTED_JSQLPARSER}, {"SQL_NO_CACHE", RESTRICTED_JSQLPARSER}, + {"STRAIGHT_JOIN", RESTRICTED_JSQLPARSER}, {"VALUE", RESTRICTED_JSQLPARSER}, + {"VALUES", RESTRICTED_SQL2016}, {"VARYING", RESTRICTED_JSQLPARSER}, + {"WHEN", RESTRICTED_SQL2016}, {"WHERE", RESTRICTED_SQL2016}, + {"WINDOW", RESTRICTED_SQL2016}, {"WITH", RESTRICTED_SQL2016}, + {"XOR", RESTRICTED_JSQLPARSER}, {"XMLSERIALIZE", RESTRICTED_JSQLPARSER} // add keywords from the composite token definitions: // tk= | tk= | tk= - // we will use the composite tokens instead, which are always hit first before the simple keywords - // @todo: figure out a way to remove these composite tokens, as they do more harm than good - , { "SEL", RESTRICTED_JSQLPARSER } - , { "SELECT", RESTRICTED_JSQLPARSER } - - , { "DATE", RESTRICTED_JSQLPARSER } - , { "TIME" , RESTRICTED_JSQLPARSER } - , { "TIMESTAMP", RESTRICTED_JSQLPARSER } - - , { "YEAR", RESTRICTED_JSQLPARSER } - , { "MONTH", RESTRICTED_JSQLPARSER } - , { "DAY", RESTRICTED_JSQLPARSER } - , { "HOUR", RESTRICTED_JSQLPARSER } - , { "MINUTE" , RESTRICTED_JSQLPARSER } - , { "SECOND", RESTRICTED_JSQLPARSER } - - , { "SUBSTR", RESTRICTED_JSQLPARSER } - , { "SUBSTRING", RESTRICTED_JSQLPARSER } - , { "TRIM", RESTRICTED_JSQLPARSER } - , { "POSITION", RESTRICTED_JSQLPARSER } - , { "OVERLAY", RESTRICTED_JSQLPARSER } - - , { "NEXTVAL", RESTRICTED_JSQLPARSER } - - //@todo: Object Names should not start with Hex-Prefix, we shall not find that Token - , { "0x", RESTRICTED_JSQLPARSER } + // we will use the composite tokens instead, which are always hit first before the + // simple keywords + // @todo: figure out a way to remove these composite tokens, as they do more harm than + // good + , {"SEL", RESTRICTED_JSQLPARSER}, {"SELECT", RESTRICTED_JSQLPARSER} + + , {"DATE", RESTRICTED_JSQLPARSER}, {"TIME", RESTRICTED_JSQLPARSER}, + {"TIMESTAMP", RESTRICTED_JSQLPARSER} + + , {"YEAR", RESTRICTED_JSQLPARSER}, {"MONTH", RESTRICTED_JSQLPARSER}, + {"DAY", RESTRICTED_JSQLPARSER}, {"HOUR", RESTRICTED_JSQLPARSER}, + {"MINUTE", RESTRICTED_JSQLPARSER}, {"SECOND", RESTRICTED_JSQLPARSER} + + , {"SUBSTR", RESTRICTED_JSQLPARSER}, {"SUBSTRING", RESTRICTED_JSQLPARSER}, + {"TRIM", RESTRICTED_JSQLPARSER}, {"POSITION", RESTRICTED_JSQLPARSER}, + {"OVERLAY", RESTRICTED_JSQLPARSER} + + , {"NEXTVAL", RESTRICTED_JSQLPARSER} + + // @todo: Object Names should not start with Hex-Prefix, we shall not find that Token + , {"0x", RESTRICTED_JSQLPARSER} }; @SuppressWarnings({"PMD.ExcessiveMethodLength"}) @@ -176,8 +123,8 @@ public static List getReservedKeywords(int restriction) { int value = (int) data[1]; // test if bit is not set - if ( (value & restriction) == restriction - || (restriction & value) == value ) { + if ((value & restriction) == restriction + || (restriction & value) == value) { keywords.add((String) data[0]); } } @@ -191,7 +138,7 @@ public static List getReservedKeywords(int restriction) { * @throws Exception */ public static void main(String[] args) throws Exception { - if (args.length<2) { + if (args.length < 2) { throw new IllegalArgumentException("No filename provided as parameters ARGS[0]"); } @@ -213,7 +160,9 @@ public static void main(String[] args) throws Exception { } public static TreeSet getAllKeywordsUsingRegex(File file) throws IOException { - Pattern tokenBlockPattern = Pattern.compile("TOKEN\\s*:\\s*(?:/\\*.*\\*/*)\\n\\{(?:[^\\}\\{]+|\\{(?:[^\\}\\{]+|\\{[^\\}\\{]*\\})*\\})*\\}", Pattern.MULTILINE); + Pattern tokenBlockPattern = Pattern.compile( + "TOKEN\\s*:\\s*(?:/\\*.*\\*/*)\\n\\{(?:[^\\}\\{]+|\\{(?:[^\\}\\{]+|\\{[^\\}\\{]*\\})*\\})*\\}", + Pattern.MULTILINE); Pattern tokenStringValuePattern = Pattern.compile("\\\"(\\w{2,})\\\"", Pattern.MULTILINE); TreeSet allKeywords = new TreeSet<>(); @@ -225,9 +174,9 @@ public static TreeSet getAllKeywordsUsingRegex(File file) throws IOExcep Matcher tokenBlockmatcher = tokenBlockPattern.matcher(content); while (tokenBlockmatcher.find()) { String tokenBlock = tokenBlockmatcher.group(0); - Matcher tokenStringValueMatcher= tokenStringValuePattern.matcher(tokenBlock); + Matcher tokenStringValueMatcher = tokenStringValuePattern.matcher(tokenBlock); while (tokenStringValueMatcher.find()) { - String tokenValue=tokenStringValueMatcher.group(1); + String tokenValue = tokenStringValueMatcher.group(1); // test if pure US-ASCII if (CHARSET_ENCODER.canEncode(tokenValue) && tokenValue.matches("[A-Za-z]+")) { allKeywords.add(tokenValue); @@ -239,58 +188,62 @@ public static TreeSet getAllKeywordsUsingRegex(File file) throws IOExcep public static void buildGrammarForRelObjectNameWithoutValue(File file) throws Exception { - Pattern methodBlockPattern = Pattern.compile("String\\W*RelObjectNameWithoutValue\\W*\\(\\W*\\)\\W*:\\s*\\{(?:[^}{]+|\\{(?:[^}{]+|\\{[^}{]*})*})*}\\s*\\{(?:[^}{]+|\\{(?:[^}{]+|\\{[^}{]*})*})*}", Pattern.MULTILINE); + Pattern methodBlockPattern = Pattern.compile( + "String\\W*RelObjectNameWithoutValue\\W*\\(\\W*\\)\\W*:\\s*\\{(?:[^}{]+|\\{(?:[^}{]+|\\{[^}{]*})*})*}\\s*\\{(?:[^}{]+|\\{(?:[^}{]+|\\{[^}{]*})*})*}", + Pattern.MULTILINE); TreeSet allKeywords = getAllKeywords(file); - for (String reserved: getReservedKeywords(RESTRICTED_JSQLPARSER)) { + for (String reserved : getReservedKeywords(RESTRICTED_JSQLPARSER)) { allKeywords.remove(reserved); } StringBuilder builder = new StringBuilder(); builder.append("String RelObjectNameWithoutValue() :\n" - + "{ Token tk = null; }\n" - + "{\n" - //@todo: find a way to avoid those hardcoded compound tokens - + " ( tk= | tk= | tk= | tk= | tk= | tk= | tk= \n" - + " "); + + "{ Token tk = null; }\n" + + "{\n" + // @todo: find a way to avoid those hardcoded compound tokens + + " ( tk= | tk= | tk= | tk= | tk= | tk= | tk= \n" + + " "); - for (String keyword: allKeywords) { + for (String keyword : allKeywords) { builder.append(" | tk=\"").append(keyword).append("\""); } builder.append(" )\n" - + " { return tk.image; }\n" - + "}"); + + " { return tk.image; }\n" + + "}"); replaceInFile(file, methodBlockPattern, builder.toString()); } public static void buildGrammarForRelObjectName(File file) throws Exception { - // Pattern pattern = Pattern.compile("String\\W*RelObjectName\\W*\\(\\W*\\)\\W*:\\s*\\{(?:[^}{]+|\\{(?:[^}{]+|\\{[^}{]*})*})*}\\s*\\{(?:[^}{]+|\\{(?:[^}{]+|\\{[^}{]*})*})*}", Pattern.MULTILINE); + // Pattern pattern = + // Pattern.compile("String\\W*RelObjectName\\W*\\(\\W*\\)\\W*:\\s*\\{(?:[^}{]+|\\{(?:[^}{]+|\\{[^}{]*})*})*}\\s*\\{(?:[^}{]+|\\{(?:[^}{]+|\\{[^}{]*})*})*}", + // Pattern.MULTILINE); TreeSet allKeywords = new TreeSet<>(); - for (String reserved: getReservedKeywords(RESTRICTED_ALIAS)) { + for (String reserved : getReservedKeywords(RESTRICTED_ALIAS)) { allKeywords.add(reserved); } - for (String reserved: getReservedKeywords(RESTRICTED_JSQLPARSER & ~RESTRICTED_ALIAS)) { + for (String reserved : getReservedKeywords(RESTRICTED_JSQLPARSER & ~RESTRICTED_ALIAS)) { allKeywords.remove(reserved); } StringBuilder builder = new StringBuilder(); builder.append("String RelObjectName() :\n" - + "{ Token tk = null; String result = null; }\n" - + "{\n" - + " (result = RelObjectNameWithoutValue()\n" - + " "); + + "{ Token tk = null; String result = null; }\n" + + "{\n" + + " (result = RelObjectNameWithoutValue()\n" + + " "); - for (String keyword: allKeywords) { + for (String keyword : allKeywords) { builder.append(" | tk=\"").append(keyword).append("\""); } builder.append(" )\n" - + " { return tk!=null ? tk.image : result; }\n" - + "}"); + + " { return tk!=null ? tk.image : result; }\n" + + "}"); // @todo: Needs fine-tuning, we are not replacing this part yet // replaceInFile(file, pattern, builder.toString()); @@ -300,7 +253,8 @@ public static TreeSet getAllKeywords(File file) throws Exception { return getAllKeywordsUsingRegex(file); } - private static void replaceInFile(File file, Pattern pattern, String replacement) throws IOException { + private static void replaceInFile(File file, Pattern pattern, String replacement) + throws IOException { Path path = file.toPath(); Charset charset = Charset.defaultCharset(); @@ -322,7 +276,8 @@ public static void writeKeywordsDocumentationFile(File file) throws IOException builder.append("***********************\n"); builder.append("\n"); - builder.append("The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and must not be used for **Naming Objects**: \n"); + builder.append( + "The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and must not be used for **Naming Objects**: \n"); builder.append("\n"); builder.append("+----------------------+-------------+-----------+\n"); @@ -330,11 +285,14 @@ public static void writeKeywordsDocumentationFile(File file) throws IOException builder.append("+----------------------+-------------+-----------+\n"); for (Object[] keywordDefinition : ALL_RESERVED_KEYWORDS) { - builder.append("| ").append(rightPadding(keywordDefinition[0].toString(), ' ', 20)).append(" | "); + builder.append("| ").append(rightPadding(keywordDefinition[0].toString(), ' ', 20)) + .append(" | "); int value = (int) keywordDefinition[1]; int restriction = RESTRICTED_JSQLPARSER; - String s = (value & restriction) == restriction || (restriction & value) == value ? "Yes" : ""; + String s = + (value & restriction) == restriction || (restriction & value) == value ? "Yes" + : ""; builder.append(rightPadding(s, ' ', 11)).append(" | "); restriction = RESTRICTED_SQL2016; diff --git a/src/main/java/net/sf/jsqlparser/parser/feature/Feature.java b/src/main/java/net/sf/jsqlparser/parser/feature/Feature.java index 96a5ff628..e52487454 100644 --- a/src/main/java/net/sf/jsqlparser/parser/feature/Feature.java +++ b/src/main/java/net/sf/jsqlparser/parser/feature/Feature.java @@ -44,7 +44,6 @@ import net.sf.jsqlparser.statement.execute.Execute; import net.sf.jsqlparser.statement.grant.Grant; import net.sf.jsqlparser.statement.merge.Merge; -import net.sf.jsqlparser.statement.replace.Replace; import net.sf.jsqlparser.statement.select.Fetch; import net.sf.jsqlparser.statement.select.First; import net.sf.jsqlparser.statement.select.KSQLWindow; @@ -53,7 +52,6 @@ import net.sf.jsqlparser.statement.select.OptimizeFor; import net.sf.jsqlparser.statement.select.Pivot; import net.sf.jsqlparser.statement.select.PivotXml; -import net.sf.jsqlparser.statement.select.SelectExpressionItem; import net.sf.jsqlparser.statement.select.Skip; import net.sf.jsqlparser.statement.select.TableFunction; import net.sf.jsqlparser.statement.select.Top; @@ -741,7 +739,7 @@ public enum Feature { */ allowUnsupportedStatements(false), - timeOut(6000), + timeOut(8000), /** * allows Backslash '\' as Escape Character diff --git a/src/main/java/net/sf/jsqlparser/schema/Column.java b/src/main/java/net/sf/jsqlparser/schema/Column.java index 482489354..2432676dd 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Column.java +++ b/src/main/java/net/sf/jsqlparser/schema/Column.java @@ -9,11 +9,13 @@ */ package net.sf.jsqlparser.schema; -import java.util.List; +import net.sf.jsqlparser.expression.ArrayConstructor; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import java.util.List; + /** * A column. It can have the table name it belongs to. */ @@ -21,9 +23,9 @@ public class Column extends ASTNodeAccessImpl implements Expression, MultiPartNa private Table table; private String columnName; + private ArrayConstructor arrayConstructor; - public Column() { - } + public Column() {} public Column(Table table, String columnName) { setTable(table); @@ -39,28 +41,41 @@ public Column(String columnName) { this(null, columnName); } + public ArrayConstructor getArrayConstructor() { + return arrayConstructor; + } + + public Column setArrayConstructor(ArrayConstructor arrayConstructor) { + this.arrayConstructor = arrayConstructor; + return this; + } + /** - * Retrieve the information regarding the {@code Table} this {@code Column} does - * belong to, if any can be inferred. - *

- * The inference is based only on local information, and not on the whole SQL command. - * For example, consider the following query: - *

-      *  SELECT x FROM Foo
-      * 
- * Given the {@code Column} called {@code x}, this method would return {@code null}, - * and not the info about the table {@code Foo}. - * On the other hand, consider: - *
-      *  SELECT t.x FROM Foo t
-      * 
- * Here, we will get a {@code Table} object for a table called {@code t}. - * But because the inference is local, such object will not know that {@code t} is - * just an alias for {@code Foo}. - * - * @return an instance of {@link net.sf.jsqlparser.schema.Table} representing the - * table this column does belong to, if it can be inferred. Can be {@code null}. - */ + * Retrieve the information regarding the {@code Table} this {@code Column} does belong to, if + * any can be inferred. + *

+ * The inference is based only on local information, and not on the whole SQL command. For + * example, consider the following query:

+ * + *
+     *  SELECT x FROM Foo
+     * 
+ * + *
Given the {@code Column} called {@code x}, this method would return + * {@code null}, and not the info about the table {@code Foo}. On the other hand, consider: + *
+ * + *
+     *  SELECT t.x FROM Foo t
+     * 
+ * + *
Here, we will get a {@code Table} object for a table called {@code t}. But + * because the inference is local, such object will not know that {@code t} is just an alias for + * {@code Foo}. + * + * @return an instance of {@link net.sf.jsqlparser.schema.Table} representing the table this + * column does belong to, if it can be inferred. Can be {@code null}. + */ public Table getTable() { return table; } @@ -98,6 +113,11 @@ public String getName(boolean aliases) { if (columnName != null) { fqn.append(columnName); } + + if (arrayConstructor != null) { + fqn.append(arrayConstructor); + } + return fqn.toString(); } diff --git a/src/main/java/net/sf/jsqlparser/schema/Sequence.java b/src/main/java/net/sf/jsqlparser/schema/Sequence.java index 0f0ffba56..bc1735277 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Sequence.java +++ b/src/main/java/net/sf/jsqlparser/schema/Sequence.java @@ -1,20 +1,16 @@ /* - * #%L - * JSQLParser library - * %% - * Copyright (C) 2004 - 2020 JSQLParser - * %% - * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 - * #L% + * #%L JSQLParser library %% Copyright (C) 2004 - 2020 JSQLParser %% Dual licensed under GNU LGPL + * 2.1 or Apache License 2.0 #L% */ package net.sf.jsqlparser.schema; +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; -import net.sf.jsqlparser.parser.ASTNodeAccessImpl; /** * Represents the database type for a {@code SEQUENCE} @@ -29,8 +25,7 @@ public class Sequence extends ASTNodeAccessImpl implements MultiPartName { private List parameters; - public Sequence() { - } + public Sequence() {} public Sequence(List partItems) { this.partItems = new ArrayList<>(partItems); @@ -153,23 +148,11 @@ public Sequence addParameters(Collection parameters) { * The available parameters to a sequence */ public enum ParameterType { - INCREMENT_BY, - START_WITH, - RESTART_WITH, - MAXVALUE, - NOMAXVALUE, - MINVALUE, - NOMINVALUE, - CYCLE, - NOCYCLE, - CACHE, - NOCACHE, - ORDER, - NOORDER, - KEEP, - NOKEEP, - SESSION, - GLOBAL + INCREMENT_BY, START_WITH, RESTART_WITH, MAXVALUE, NOMAXVALUE, MINVALUE, NOMINVALUE, CYCLE, NOCYCLE, CACHE, NOCACHE, ORDER, NOORDER, KEEP, NOKEEP, SESSION, GLOBAL; + + public static ParameterType from(String type) { + return Enum.valueOf(ParameterType.class, type.toUpperCase()); + } } /** diff --git a/src/main/java/net/sf/jsqlparser/statement/DeclareType.java b/src/main/java/net/sf/jsqlparser/statement/DeclareType.java index 8e0d7119c..c63c686a4 100644 --- a/src/main/java/net/sf/jsqlparser/statement/DeclareType.java +++ b/src/main/java/net/sf/jsqlparser/statement/DeclareType.java @@ -14,5 +14,9 @@ * @author tobens */ public enum DeclareType { - TABLE, AS, TYPE + TABLE, AS, TYPE; + + public static DeclareType from(String type) { + return Enum.valueOf(DeclareType.class, type.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java b/src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java index b360ac8a1..2957472db 100644 --- a/src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java @@ -53,8 +53,10 @@ public void addOption(Option option) { /** * Returns the first option that matches this optionType + * * @param optionType the option type to retrieve an Option for - * @return an option of that type, or null. In case of duplicate options, the first found option will be returned. + * @return an option of that type, or null. In case of duplicate options, the first found option + * will be returned. */ public Option getOption(OptionType optionType) { if (options == null) { @@ -68,7 +70,8 @@ public String toString() { StringBuilder statementBuilder = new StringBuilder("EXPLAIN"); if (options != null) { statementBuilder.append(" "); - statementBuilder.append(options.values().stream().map(Option::formatOption).collect(Collectors.joining(" "))); + statementBuilder.append(options.values().stream().map(Option::formatOption) + .collect(Collectors.joining(" "))); } statementBuilder.append(" "); @@ -82,11 +85,11 @@ public void accept(StatementVisitor statementVisitor) { } public enum OptionType { - ANALYZE, - VERBOSE, - COSTS, - BUFFERS, - FORMAT + ANALYZE, VERBOSE, COSTS, BUFFERS, FORMAT; + + public static OptionType from(String type) { + return Enum.valueOf(OptionType.class, type.toUpperCase()); + } } public static class Option implements Serializable { @@ -111,9 +114,9 @@ public void setValue(String value) { } public String formatOption() { - return type.name() + ( value != null - ? " " + value - : "" ); + return type.name() + (value != null + ? " " + value + : ""); } public Option withValue(String value) { diff --git a/src/main/java/net/sf/jsqlparser/statement/OutputClause.java b/src/main/java/net/sf/jsqlparser/statement/OutputClause.java index 5d05ead92..fe2fd60ac 100644 --- a/src/main/java/net/sf/jsqlparser/statement/OutputClause.java +++ b/src/main/java/net/sf/jsqlparser/statement/OutputClause.java @@ -21,9 +21,11 @@ /** * T-SQL Output Clause * - * @see OUTPUT Clause (Transact-SQL) + * @see OUTPUT + * Clause (Transact-SQL) * - *
+ *      
  * <OUTPUT_CLAUSE> ::=
  * {
  *     [ OUTPUT <dml_select_list> INTO { @table_variable | output_table } [ ( column_list ) ] ]
@@ -36,26 +38,28 @@
  * <column_name> ::=
  * { DELETED | INSERTED | from_table_name } . { * | column_name }
  *     | $action
- * 
+ *
*/ public class OutputClause implements Serializable { - List selectItemList; + List> selectItemList; UserVariable tableVariable; Table outputTable; List columnList; - public OutputClause(List selectItemList, UserVariable tableVariable, Table outputTable, List columnList) { - this.selectItemList = Objects.requireNonNull(selectItemList, "The Select List of the Output Clause must not be null."); + public OutputClause(List> selectItemList, UserVariable tableVariable, + Table outputTable, List columnList) { + this.selectItemList = Objects.requireNonNull(selectItemList, + "The Select List of the Output Clause must not be null."); this.tableVariable = tableVariable; this.outputTable = outputTable; this.columnList = columnList; } - public List getSelectItemList() { + public List> getSelectItemList() { return selectItemList; } - public void setSelectItemList(List selectItemList) { + public void setSelectItemList(List> selectItemList) { this.selectItemList = selectItemList; } diff --git a/src/main/java/net/sf/jsqlparser/statement/PurgeObjectType.java b/src/main/java/net/sf/jsqlparser/statement/PurgeObjectType.java index 999f29ea1..c9fecb849 100644 --- a/src/main/java/net/sf/jsqlparser/statement/PurgeObjectType.java +++ b/src/main/java/net/sf/jsqlparser/statement/PurgeObjectType.java @@ -14,5 +14,9 @@ * @author Andreas Reichel */ public enum PurgeObjectType { - TABLE, INDEX, RECYCLEBIN, DBA_RECYCLEBIN, TABLESPACE; + TABLE, INDEX, RECYCLEBIN, DBA_RECYCLEBIN, TABLESPACE; + + public static PurgeObjectType from(String type) { + return Enum.valueOf(PurgeObjectType.class, type.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/ReferentialAction.java b/src/main/java/net/sf/jsqlparser/statement/ReferentialAction.java index 353dafb03..16dc9427d 100644 --- a/src/main/java/net/sf/jsqlparser/statement/ReferentialAction.java +++ b/src/main/java/net/sf/jsqlparser/statement/ReferentialAction.java @@ -62,7 +62,8 @@ public int hashCode() { @Override public String toString() { - return new StringBuilder(" ON ").append(getType().name()).append(" ").append(getAction().getAction()) + return new StringBuilder(" ON ").append(getType().name()).append(" ") + .append(getAction().getAction()) .toString(); } @@ -78,37 +79,38 @@ public boolean equals(Object obj) { return false; } ReferentialAction other = (ReferentialAction) obj; -// if (action != other.action) { -// return false; -// } -// if (type != other.type) { -// return false; - return action==other.action && type == other.type; + // if (action != other.action) { + // return false; + // } + // if (type != other.type) { + // return false; + return action == other.action && type == other.type; } public enum Type { - DELETE, - UPDATE + DELETE, UPDATE; + + public static Type from(String name) { + return Enum.valueOf(Type.class, name.toUpperCase()); + } } public enum Action { - CASCADE("CASCADE"), - RESTRICT("RESTRICT"), - NO_ACTION("NO ACTION"), - SET_DEFAULT("SET DEFAULT"), - SET_NULL("SET NULL"); + CASCADE("CASCADE"), RESTRICT("RESTRICT"), NO_ACTION("NO ACTION"), SET_DEFAULT( + "SET DEFAULT"), SET_NULL("SET NULL"); + + private final String action; Action(String action) { this.action = action; } - private final String action; - /** * @param action * @return the {@link Action}, if found, otherwise null */ - public static Action byAction(String action) { + public static Action from(String action) { + // We can't use Enum.valueOf() since there White Space involved for (Action a : values()) { if (a.getAction().equals(action)) { return a; @@ -120,11 +122,6 @@ public static Action byAction(String action) { public String getAction() { return action; } - - @Override - public String toString() { - return action; - } } } diff --git a/src/main/java/net/sf/jsqlparser/statement/ReturningClause.java b/src/main/java/net/sf/jsqlparser/statement/ReturningClause.java new file mode 100644 index 000000000..6d42ffdfc --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/statement/ReturningClause.java @@ -0,0 +1,97 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement; + +import net.sf.jsqlparser.statement.select.SelectItem; + +import java.util.ArrayList; +import java.util.List; + +/** + * RETURNING clause according to + * {@see https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/DELETE.html#GUID-156845A5-B626-412B-9F95-8869B988ABD7 + * } Part of UPDATE, INSERT, DELETE statements + */ + +public class ReturningClause extends ArrayList> { + enum Keyword { + RETURN, RETURNING; + + public static Keyword from(String keyword) { + return Enum.valueOf(Keyword.class, keyword.toUpperCase()); + } + } + + private Keyword keyword; + + /** + * List of output targets like Table or UserVariable + */ + private final List dataItems; + + public ReturningClause(Keyword keyword, List> selectItems, + List dataItems) { + this.keyword = keyword; + this.addAll(selectItems); + this.dataItems = dataItems; + } + + public ReturningClause(String keyword, List> selectItems, + List dataItems) { + this(Keyword.from(keyword), selectItems, dataItems); + } + + public ReturningClause(Keyword keyword, List> selectItems) { + this(keyword, selectItems, null); + } + + public ReturningClause(String keyword, List> selectItems) { + this(Keyword.valueOf(keyword), selectItems, null); + } + + public Keyword getKeyword() { + return keyword; + } + + public ReturningClause setKeyword(Keyword keyword) { + this.keyword = keyword; + return this; + } + + public List getDataItems() { + return dataItems; + } + + public StringBuilder appendTo(StringBuilder builder) { + builder.append(" ").append(keyword).append(" "); + for (int i = 0; i < size(); i++) { + if (i > 0) { + builder.append(", "); + } + builder.append(get(i)); + } + + if (dataItems != null && dataItems.size() > 0) { + builder.append(" INTO "); + for (int i = 0; i < dataItems.size(); i++) { + if (i > 0) { + builder.append(" ,"); + } + builder.append(dataItems.get(i)); + } + } + return builder; + } + + @Override + public String toString() { + return appendTo(new StringBuilder()).toString(); + } +} diff --git a/src/main/java/net/sf/jsqlparser/statement/SetStatement.java b/src/main/java/net/sf/jsqlparser/statement/SetStatement.java index f0614587f..f276f4956 100644 --- a/src/main/java/net/sf/jsqlparser/statement/SetStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/SetStatement.java @@ -9,12 +9,16 @@ */ package net.sf.jsqlparser.statement; -import java.io.Serializable; -import java.util.*; - import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.statement.select.PlainSelect; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + public final class SetStatement implements Statement { private String effectParameter; @@ -24,11 +28,11 @@ public SetStatement() { // empty constructor } - public SetStatement(Object name, List value) { + public SetStatement(Object name, ExpressionList value) { add(name, value, true); } - public void add(Object name, List value, boolean useEqual) { + public void add(Object name, ExpressionList value, boolean useEqual) { values.add(new NameExpr(name, value, useEqual)); } @@ -92,11 +96,11 @@ public List getExpressions() { return getExpressions(0); } - public void setExpressions(int idx, List expressions) { + public void setExpressions(int idx, ExpressionList expressions) { values.get(idx).expressions = expressions; } - public void setExpressions(List expressions) { + public void setExpressions(ExpressionList expressions) { setExpressions(0, expressions); } @@ -148,7 +152,7 @@ public void accept(StatementVisitor statementVisitor) { static class NameExpr implements Serializable { Object name; - List expressions; + ExpressionList expressions; boolean useEqual; public Object getName() { @@ -159,11 +163,11 @@ public void setName(Object name) { this.name = name; } - public List getExpressions() { + public ExpressionList getExpressions() { return expressions; } - public void setExpressions(List expressions) { + public void setExpressions(ExpressionList expressions) { this.expressions = expressions; } @@ -175,7 +179,7 @@ public void setUseEqual(boolean useEqual) { this.useEqual = useEqual; } - public NameExpr(Object name, List expressions, boolean useEqual) { + public NameExpr(Object name, ExpressionList expressions, boolean useEqual) { this.name = name; this.expressions = expressions; this.useEqual = useEqual; diff --git a/src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java b/src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java index b3ddefa95..86621f749 100644 --- a/src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java +++ b/src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java @@ -29,7 +29,6 @@ import net.sf.jsqlparser.statement.grant.Grant; import net.sf.jsqlparser.statement.insert.Insert; import net.sf.jsqlparser.statement.merge.Merge; -import net.sf.jsqlparser.statement.replace.Replace; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.show.ShowIndexStatement; import net.sf.jsqlparser.statement.show.ShowTablesStatement; @@ -55,8 +54,6 @@ public interface StatementVisitor { void visit(Insert insert); - void visit(Replace replace); - void visit(Drop drop); void visit(Truncate truncate); diff --git a/src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java index eae4173ab..251fcc15b 100644 --- a/src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java @@ -29,7 +29,6 @@ import net.sf.jsqlparser.statement.grant.Grant; import net.sf.jsqlparser.statement.insert.Insert; import net.sf.jsqlparser.statement.merge.Merge; -import net.sf.jsqlparser.statement.replace.Replace; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.show.ShowIndexStatement; import net.sf.jsqlparser.statement.show.ShowTablesStatement; @@ -70,11 +69,6 @@ public void visit(Insert insert) { } - @Override - public void visit(Replace replace) { - - } - @Override public void visit(Drop drop) { diff --git a/src/main/java/net/sf/jsqlparser/statement/Statements.java b/src/main/java/net/sf/jsqlparser/statement/Statements.java index 12a1aaff3..5f66f2d6f 100644 --- a/src/main/java/net/sf/jsqlparser/statement/Statements.java +++ b/src/main/java/net/sf/jsqlparser/statement/Statements.java @@ -11,31 +11,33 @@ import java.io.Serializable; import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; import java.util.List; -import java.util.Optional; -public class Statements implements Serializable { - - private List statements; +public class Statements extends ArrayList implements Serializable { + @Deprecated public List getStatements() { - return statements; + return this; } + @Deprecated public void setStatements(List statements) { - this.statements = statements; + this.clear(); + this.addAll(statements); } public void accept(StatementVisitor statementVisitor) { statementVisitor.visit(this); } + public E get(Class type, int index) { + return type.cast(get(index)); + } + @Override public String toString() { StringBuilder b = new StringBuilder(); - for (Statement stmt : statements) { + for (Statement stmt : this) { // IfElseStatements and Blocks control the Semicolons by themselves if (stmt instanceof IfElseStatement || stmt instanceof Block) { b.append(stmt).append("\n"); @@ -45,21 +47,4 @@ public String toString() { } return b.toString(); } - - public Statements withStatements(List statements) { - this.setStatements(statements); - return this; - } - - public Statements addStatements(Statement... statements) { - List collection = Optional.ofNullable(getStatements()).orElseGet(ArrayList::new); - Collections.addAll(collection, statements); - return this.withStatements(collection); - } - - public Statements addStatements(Collection statements) { - List collection = Optional.ofNullable(getStatements()).orElseGet(ArrayList::new); - collection.addAll(statements); - return this.withStatements(collection); - } } diff --git a/src/main/java/net/sf/jsqlparser/statement/UnsupportedStatement.java b/src/main/java/net/sf/jsqlparser/statement/UnsupportedStatement.java index 372204c06..9b47a9e2a 100644 --- a/src/main/java/net/sf/jsqlparser/statement/UnsupportedStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/UnsupportedStatement.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.statement; +import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -22,19 +23,28 @@ public class UnsupportedStatement implements Statement { private List declarations; public UnsupportedStatement(List declarations) { - this.declarations = Objects.requireNonNull(declarations, "The List of Tokens must not be null."); + this.declarations = + Objects.requireNonNull(declarations, "The List of Tokens must not be null."); } - @Override + public UnsupportedStatement(String upfront, List declarations) { + this.declarations = new ArrayList<>(); + this.declarations.add(upfront); + this.declarations.addAll( + Objects.requireNonNull(declarations, "The List of Tokens must not be null.")); + } + + @Override public void accept(StatementVisitor statementVisitor) { statementVisitor.visit(this); } - - @SuppressWarnings({"PMD.MissingBreakInSwitch", "PMD.SwitchStmtsShouldHaveDefault", "PMD.CyclomaticComplexity"}) + + @SuppressWarnings({"PMD.MissingBreakInSwitch", "PMD.SwitchStmtsShouldHaveDefault", + "PMD.CyclomaticComplexity"}) public StringBuilder appendTo(StringBuilder builder) { - int i=0; - for (String s:declarations) { - if (i>0) { + int i = 0; + for (String s : declarations) { + if (i > 0) { builder.append(" "); } builder.append(s); diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java index c1280c715..bb13956f4 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java @@ -11,4 +11,8 @@ public enum AlterOperation { ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, ALGORITHM, RENAME, RENAME_TABLE, COMMENT, UNSPECIFIC; + + public static AlterOperation from(String operation) { + return Enum.valueOf(AlterOperation.class, operation.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterSessionOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterSessionOperation.java index 2efdb1d51..1ab603d59 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterSessionOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterSessionOperation.java @@ -7,21 +7,6 @@ * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 * #L% */ -/* - * Copyright (C) 2021 JSQLParser. - * - * This library is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version - * 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA - */ package net.sf.jsqlparser.statement.alter; @@ -30,24 +15,9 @@ * @author are */ public enum AlterSessionOperation { - ADVISE_COMMIT - , ADVISE_ROLLBACK - , ADVISE_NOTHING - , CLOSE_DATABASE_LINK - , ENABLE_COMMIT_IN_PROCEDURE - , DISABLE_COMMIT_IN_PROCEDURE - , ENABLE_GUARD - , DISABLE_GUARD - , ENABLE_PARALLEL_DML - , DISABLE_PARALLEL_DML - , FORCE_PARALLEL_DML - , ENABLE_PARALLEL_DDL - , DISABLE_PARALLEL_DDL - , FORCE_PARALLEL_DDL - , ENABLE_PARALLEL_QUERY - , DISABLE_PARALLEL_QUERY - , FORCE_PARALLEL_QUERY - , ENABLE_RESUMABLE - , DISABLE_RESUMABLE - , SET + ADVISE_COMMIT, ADVISE_ROLLBACK, ADVISE_NOTHING, CLOSE_DATABASE_LINK, ENABLE_COMMIT_IN_PROCEDURE, DISABLE_COMMIT_IN_PROCEDURE, ENABLE_GUARD, DISABLE_GUARD, ENABLE_PARALLEL_DML, DISABLE_PARALLEL_DML, FORCE_PARALLEL_DML, ENABLE_PARALLEL_DDL, DISABLE_PARALLEL_DDL, FORCE_PARALLEL_DDL, ENABLE_PARALLEL_QUERY, DISABLE_PARALLEL_QUERY, FORCE_PARALLEL_QUERY, ENABLE_RESUMABLE, DISABLE_RESUMABLE, SET; + + public static AlterSessionOperation from(String operation) { + return Enum.valueOf(AlterSessionOperation.class, operation.toUpperCase()); } +} diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterSystemOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterSystemOperation.java index f12411ff4..8cd08ba6b 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterSystemOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterSystemOperation.java @@ -7,52 +7,37 @@ * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 * #L% */ -/* - * Copyright (C) 2021 JSQLParser. - * - * This library is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version - * 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA - */ package net.sf.jsqlparser.statement.alter; /** * * @author Andreas Reichel - * @see ALTER SESSION + * @see ALTER + * SESSION */ public enum AlterSystemOperation { - ARCHIVE_LOG("ARCHIVE LOG") - , CHECKPOINT("CHECKPOINT") - , CHECK_DATAFILES("CHECK DATAFILES") - , DUMP_ACTIVE_SESSION_HISTORY("DUMP ACTIVE SESSION HISTORY") - , ENABLE_DISTRIBUTED_RECOVERY("ENABLE DISTRIBUTED RECOVERY") - , DISABLE_DISTRIBUTED_RECOVERY("DISABLE DISTRIBUTED RECOVERY") - , ENABLE_RESTRICTED_SESSION("ENABLE RESTRICTED SESSION") - , DISABLE_RESTRICTED_SESSION("DISABLE RESTRICTED SESSION") - , FLUSH("FLUSH") - , DISCONNECT_SESSION("DISCONNECT SESSION") - , KILL_SESSION("KILL SESSION") - , SWITCH("SWITCH") - , SUSPEND("SUSPEND") - , RESUME("RESUME") - , QUIESCE("QUIESCE RESTRICTED") - , UNQUIESCE("UNQUIESCE") - , SHUTDOWN("SHUTDOWN") - , REGISTER("REGISTER") - , SET("SET") - , RESET("RESET"); - + ARCHIVE_LOG("ARCHIVE LOG"), CHECKPOINT("CHECKPOINT"), CHECK_DATAFILES( + "CHECK DATAFILES"), DUMP_ACTIVE_SESSION_HISTORY( + "DUMP ACTIVE SESSION HISTORY"), ENABLE_DISTRIBUTED_RECOVERY( + "ENABLE DISTRIBUTED RECOVERY"), DISABLE_DISTRIBUTED_RECOVERY( + "DISABLE DISTRIBUTED RECOVERY"), ENABLE_RESTRICTED_SESSION( + "ENABLE RESTRICTED SESSION"), DISABLE_RESTRICTED_SESSION( + "DISABLE RESTRICTED SESSION"), FLUSH( + "FLUSH"), DISCONNECT_SESSION( + "DISCONNECT SESSION"), KILL_SESSION( + "KILL SESSION"), SWITCH( + "SWITCH"), SUSPEND( + "SUSPEND"), RESUME( + "RESUME"), QUIESCE( + "QUIESCE RESTRICTED"), UNQUIESCE( + "UNQUIESCE"), SHUTDOWN( + "SHUTDOWN"), REGISTER( + "REGISTER"), SET( + "SET"), RESET( + "RESET"); + private final String label; AlterSystemOperation(String label) { @@ -63,6 +48,14 @@ public enum AlterSystemOperation { public String toString() { return label; } - - + + public static AlterSystemOperation from(String operation) { + // We can't use Enum.valueOf() since there White Space involved + for (AlterSystemOperation alterSystemOperation : values()) { + if (alterSystemOperation.toString().equals(operation)) { + return alterSystemOperation; + } + } + return null; + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/ColumnDefinition.java b/src/main/java/net/sf/jsqlparser/statement/create/table/ColumnDefinition.java index 89b27ee38..f19962d8e 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/table/ColumnDefinition.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/ColumnDefinition.java @@ -9,14 +9,14 @@ */ package net.sf.jsqlparser.statement.create.table; +import net.sf.jsqlparser.statement.select.PlainSelect; + import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; -import net.sf.jsqlparser.expression.ExpressionVisitorAdapter; -import net.sf.jsqlparser.statement.select.PlainSelect; /** * Globally used definition class for columns. @@ -27,8 +27,7 @@ public class ColumnDefinition implements Serializable { private ColDataType colDataType; private List columnSpecs; - public ColumnDefinition() { - } + public ColumnDefinition() {} public ColumnDefinition(String columnName, ColDataType colDataType) { this.columnName = columnName; @@ -70,9 +69,9 @@ public String toString() { } public String toStringDataTypeAndSpec() { - return colDataType + ( columnSpecs != null && !columnSpecs.isEmpty() - ? " " + PlainSelect.getStringList(columnSpecs, false, false) - : "" ); + return colDataType + (columnSpecs != null && !columnSpecs.isEmpty() + ? " " + PlainSelect.getStringList(columnSpecs, false, false) + : ""); } public ColumnDefinition withColumnName(String columnName) { @@ -101,8 +100,4 @@ public ColumnDefinition addColumnSpecs(Collection columnSpecs) { collection.addAll(columnSpecs); return this.withColumnSpecs(collection); } - - public void accept(ExpressionVisitorAdapter expressionVisitor) { - expressionVisitor.visit(this); - } } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/ForeignKeyIndex.java b/src/main/java/net/sf/jsqlparser/statement/create/table/ForeignKeyIndex.java index 3ece350be..eb9f20c4b 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/table/ForeignKeyIndex.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/ForeignKeyIndex.java @@ -9,6 +9,12 @@ */ package net.sf.jsqlparser.statement.create.table; +import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.ReferentialAction; +import net.sf.jsqlparser.statement.ReferentialAction.Action; +import net.sf.jsqlparser.statement.ReferentialAction.Type; +import net.sf.jsqlparser.statement.select.PlainSelect; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -16,11 +22,6 @@ import java.util.List; import java.util.Optional; import java.util.Set; -import net.sf.jsqlparser.schema.Table; -import net.sf.jsqlparser.statement.ReferentialAction; -import net.sf.jsqlparser.statement.ReferentialAction.Action; -import net.sf.jsqlparser.statement.ReferentialAction.Type; -import net.sf.jsqlparser.statement.select.PlainSelect; public class ForeignKeyIndex extends NamedConstraint { @@ -69,7 +70,8 @@ public void removeReferentialAction(Type type) { * @return */ public ReferentialAction getReferentialAction(Type type) { - return referentialActions.stream().filter(ra -> type.equals(ra.getType())).findFirst().orElse(null); + return referentialActions.stream().filter(ra -> type.equals(ra.getType())).findFirst() + .orElse(null); } private void setReferentialAction(Type type, Action action, boolean set) { @@ -96,7 +98,7 @@ public void setOnDeleteReferenceOption(String onDeleteReferenceOption) { if (onDeleteReferenceOption == null) { removeReferentialAction(Type.DELETE); } else { - setReferentialAction(Type.DELETE, Action.byAction(onDeleteReferenceOption)); + setReferentialAction(Type.DELETE, Action.from(onDeleteReferenceOption)); } } @@ -111,7 +113,7 @@ public void setOnUpdateReferenceOption(String onUpdateReferenceOption) { if (onUpdateReferenceOption == null) { removeReferentialAction(Type.UPDATE); } else { - setReferentialAction(Type.UPDATE, Action.byAction(onUpdateReferenceOption)); + setReferentialAction(Type.UPDATE, Action.from(onUpdateReferenceOption)); } } @@ -144,13 +146,15 @@ public ForeignKeyIndex withOnUpdateReferenceOption(String onUpdateReferenceOptio } public ForeignKeyIndex addReferencedColumnNames(String... referencedColumnNames) { - List collection = Optional.ofNullable(getReferencedColumnNames()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getReferencedColumnNames()).orElseGet(ArrayList::new); Collections.addAll(collection, referencedColumnNames); return this.withReferencedColumnNames(collection); } public ForeignKeyIndex addReferencedColumnNames(Collection referencedColumnNames) { - List collection = Optional.ofNullable(getReferencedColumnNames()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getReferencedColumnNames()).orElseGet(ArrayList::new); collection.addAll(referencedColumnNames); return this.withReferencedColumnNames(collection); } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/RowMovementMode.java b/src/main/java/net/sf/jsqlparser/statement/create/table/RowMovementMode.java index 443e5a1c2..9d6066f7a 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/table/RowMovementMode.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/RowMovementMode.java @@ -11,5 +11,9 @@ public enum RowMovementMode { ENABLE, DISABLE; + + public static RowMovementMode from(String mode) { + return Enum.valueOf(RowMovementMode.class, mode.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/view/AutoRefreshOption.java b/src/main/java/net/sf/jsqlparser/statement/create/view/AutoRefreshOption.java index ba33f18c9..69e354d82 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/view/AutoRefreshOption.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/view/AutoRefreshOption.java @@ -10,9 +10,9 @@ package net.sf.jsqlparser.statement.create.view; public enum AutoRefreshOption { - NONE, + NONE, YES, NO; - YES, - - NO + public static AutoRefreshOption from(String option) { + return Enum.valueOf(AutoRefreshOption.class, option.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/view/ForceOption.java b/src/main/java/net/sf/jsqlparser/statement/create/view/ForceOption.java index 66d3a9622..379690b63 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/view/ForceOption.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/view/ForceOption.java @@ -10,9 +10,9 @@ package net.sf.jsqlparser.statement.create.view; public enum ForceOption { - NONE, - - FORCE, - - NO_FORCE + NONE, FORCE, NO_FORCE; + + public static ForceOption from(String option) { + return Enum.valueOf(ForceOption.class, option.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/view/TemporaryOption.java b/src/main/java/net/sf/jsqlparser/statement/create/view/TemporaryOption.java index 31b1721f1..4caae850e 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/view/TemporaryOption.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/view/TemporaryOption.java @@ -10,9 +10,9 @@ package net.sf.jsqlparser.statement.create.view; public enum TemporaryOption { - NONE, - - TEMP, - - TEMPORARY + NONE, TEMP, TEMPORARY; + + public static TemporaryOption from(String option) { + return Enum.valueOf(TemporaryOption.class, option.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java b/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java index ac811b018..c28a4a0d8 100644 --- a/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java +++ b/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java @@ -9,27 +9,28 @@ */ package net.sf.jsqlparser.statement.delete; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; - -import static java.util.stream.Collectors.joining; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.OracleHint; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.OutputClause; +import net.sf.jsqlparser.statement.ReturningClause; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; import net.sf.jsqlparser.statement.select.Join; import net.sf.jsqlparser.statement.select.Limit; import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.PlainSelect; -import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.WithItem; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +import static java.util.stream.Collectors.joining; + public class Delete implements Statement { private List withItemsList; @@ -45,7 +46,8 @@ public class Delete implements Statement { private DeleteModifierPriority modifierPriority; private boolean modifierIgnore; private boolean modifierQuick; - private List returningExpressionList = null; + + private ReturningClause returningClause; private OutputClause outputClause; public OutputClause getOutputClause() { @@ -56,16 +58,12 @@ public void setOutputClause(OutputClause outputClause) { this.outputClause = outputClause; } - public List getReturningExpressionList() { - return returningExpressionList; + public ReturningClause getReturningClause() { + return returningClause; } - public void setReturningExpressionList(List returningExpressionList) { - this.returningExpressionList = returningExpressionList; - } - - public Delete withReturningExpressionList(List returningExpressionList) { - this.returningExpressionList = returningExpressionList; + public Delete setReturningClause(ReturningClause returningClause) { + this.returningClause = returningClause; return this; } @@ -81,15 +79,17 @@ public Delete withWithItemsList(List withItemsList) { this.setWithItemsList(withItemsList); return this; } - - public Delete addWithItemsList(WithItem... withItemsList) { - List collection = Optional.ofNullable(getWithItemsList()).orElseGet(ArrayList::new); + + public Delete addWithItemsList(WithItem... withItemsList) { + List collection = + Optional.ofNullable(getWithItemsList()).orElseGet(ArrayList::new); Collections.addAll(collection, withItemsList); return this.withWithItemsList(collection); } public Delete addWithItemsList(Collection withItemsList) { - List collection = Optional.ofNullable(getWithItemsList()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getWithItemsList()).orElseGet(ArrayList::new); collection.addAll(withItemsList); return this.withWithItemsList(collection); } @@ -122,7 +122,7 @@ public void setTable(Table name) { public void setWhere(Expression expression) { where = expression; } - + public OracleHint getOracleHint() { return oracleHint; } @@ -186,7 +186,7 @@ public String toString() { b.append(" "); } } - + b.append("DELETE"); if (modifierPriority != null) { @@ -206,7 +206,7 @@ public String toString() { .collect(joining(", "))); } - if (outputClause!=null) { + if (outputClause != null) { outputClause.appendTo(b); } @@ -216,7 +216,7 @@ public String toString() { } b.append(" ").append(table); - if (usingList != null && usingList.size()>0) { + if (usingList != null && usingList.size() > 0) { b.append(" USING "); b.append(usingList.stream() .map(Table::toString) @@ -245,9 +245,8 @@ public String toString() { b.append(limit); } - if (getReturningExpressionList() != null) { - b.append(" RETURNING ").append(PlainSelect. - getStringList(getReturningExpressionList(), true, false)); + if (returningClause != null) { + returningClause.appendTo(b); } return b.toString(); @@ -293,17 +292,17 @@ public Delete withHasFrom(boolean hasFrom) { return this; } - public Delete withModifierPriority(DeleteModifierPriority modifierPriority){ + public Delete withModifierPriority(DeleteModifierPriority modifierPriority) { this.setModifierPriority(modifierPriority); return this; } - public Delete withModifierIgnore(boolean modifierIgnore){ + public Delete withModifierIgnore(boolean modifierIgnore) { this.setModifierIgnore(modifierIgnore); return this; } - public Delete withModifierQuick(boolean modifierQuick){ + public Delete withModifierQuick(boolean modifierQuick) { this.setModifierQuick(modifierQuick); return this; } @@ -369,13 +368,15 @@ public Delete addJoins(Collection joins) { } public Delete addOrderByElements(OrderByElement... orderByElements) { - List collection = Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new); Collections.addAll(collection, orderByElements); return this.withOrderByElements(collection); } public Delete addOrderByElements(Collection orderByElements) { - List collection = Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new); collection.addAll(orderByElements); return this.withOrderByElements(collection); } diff --git a/src/main/java/net/sf/jsqlparser/statement/delete/DeleteModifierPriority.java b/src/main/java/net/sf/jsqlparser/statement/delete/DeleteModifierPriority.java index 7fdb58039..f02772287 100644 --- a/src/main/java/net/sf/jsqlparser/statement/delete/DeleteModifierPriority.java +++ b/src/main/java/net/sf/jsqlparser/statement/delete/DeleteModifierPriority.java @@ -10,5 +10,9 @@ package net.sf.jsqlparser.statement.delete; public enum DeleteModifierPriority { - LOW_PRIORITY + LOW_PRIORITY; + + public static DeleteModifierPriority from(String priority) { + return Enum.valueOf(DeleteModifierPriority.class, priority.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/execute/Execute.java b/src/main/java/net/sf/jsqlparser/statement/execute/Execute.java index bc0eb16a4..366a982e6 100644 --- a/src/main/java/net/sf/jsqlparser/statement/execute/Execute.java +++ b/src/main/java/net/sf/jsqlparser/statement/execute/Execute.java @@ -9,18 +9,19 @@ */ package net.sf.jsqlparser.statement.execute; -import java.util.List; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; import net.sf.jsqlparser.statement.select.PlainSelect; +import java.util.List; + public class Execute implements Statement { private ExecType execType = ExecType.EXECUTE; private String name; private ExpressionList exprList; - private boolean parenthesis = false; public String getName() { return name; @@ -56,12 +57,9 @@ public void setExecType(ExecType execType) { this.execType = execType; } + @Deprecated public boolean isParenthesis() { - return parenthesis; - } - - public void setParenthesis(boolean parenthesis) { - this.parenthesis = parenthesis; + return exprList instanceof ParenthesedExpressionList; } @Override @@ -72,8 +70,10 @@ public void accept(StatementVisitor statementVisitor) { @Override public String toString() { return execType.name() + " " + name - + (exprList != null && exprList.getExpressions() != null ? " " - + PlainSelect.getStringList(exprList.getExpressions(), true, parenthesis) : ""); + + (exprList != null + ? " " + PlainSelect.getStringList(exprList, true, + exprList instanceof ParenthesedExpressionList) + : ""); } public Execute withExecType(ExecType execType) { @@ -91,14 +91,11 @@ public Execute withExprList(ExpressionList exprList) { return this; } - public Execute withParenthesis(boolean parenthesis) { - this.setParenthesis(parenthesis); - return this; - } - public enum ExecType { - EXECUTE, - EXEC, - CALL + EXECUTE, EXEC, CALL; + + public static ExecType from(String type) { + return Enum.valueOf(ExecType.class, type.toUpperCase()); + } } } diff --git a/src/main/java/net/sf/jsqlparser/statement/insert/ConflictActionType.java b/src/main/java/net/sf/jsqlparser/statement/insert/ConflictActionType.java index 3461ab8a7..69d6532f0 100644 --- a/src/main/java/net/sf/jsqlparser/statement/insert/ConflictActionType.java +++ b/src/main/java/net/sf/jsqlparser/statement/insert/ConflictActionType.java @@ -10,5 +10,9 @@ package net.sf.jsqlparser.statement.insert; public enum ConflictActionType { - DO_NOTHING, DO_UPDATE + DO_NOTHING, DO_UPDATE; + + public static ConflictActionType from(String type) { + return Enum.valueOf(ConflictActionType.class, type.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java b/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java index b045f5bf9..398c7c138 100644 --- a/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java +++ b/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java @@ -9,25 +9,23 @@ */ package net.sf.jsqlparser.statement.insert; -import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.OracleHint; -import net.sf.jsqlparser.expression.RowConstructor; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.expression.operators.relational.ItemsList; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.OutputClause; +import net.sf.jsqlparser.statement.ReturningClause; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectItem; -import net.sf.jsqlparser.statement.select.WithItem; +import net.sf.jsqlparser.statement.select.SetOperationList; import net.sf.jsqlparser.statement.select.Values; +import net.sf.jsqlparser.statement.select.WithItem; +import net.sf.jsqlparser.statement.update.UpdateSet; -import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Optional; @@ -37,25 +35,36 @@ public class Insert implements Statement { private Table table; private OracleHint oracleHint = null; - private List columns; + private ExpressionList columns; private Select select; - private boolean useDuplicate = false; - private List duplicateUpdateColumns; - private List duplicateUpdateExpressionList; + private List duplicateUpdateSets = null; private InsertModifierPriority modifierPriority = null; private boolean modifierIgnore = false; - - private List returningExpressionList = null; - - private boolean useSet = false; - private List setColumns; - private List setExpressionList; + private ReturningClause returningClause; + private List setUpdateSets = null; private List withItemsList; - private OutputClause outputClause; private InsertConflictTarget conflictTarget; private InsertConflictAction conflictAction; + public List getDuplicateUpdateSets() { + return duplicateUpdateSets; + } + + public List getSetUpdateSets() { + return setUpdateSets; + } + + public Insert withDuplicateUpdateSets(List duplicateUpdateSets) { + this.duplicateUpdateSets = duplicateUpdateSets; + return this; + } + + public Insert withSetUpdateSets(List setUpdateSets) { + this.setUpdateSets = setUpdateSets; + return this; + } + public OutputClause getOutputClause() { return outputClause; } @@ -85,54 +94,26 @@ public void setOracleHint(OracleHint oracleHint) { this.oracleHint = oracleHint; } - public List getColumns() { + public ExpressionList getColumns() { return columns; } - public void setColumns(List list) { + public void setColumns(ExpressionList list) { columns = list; } - /** - * Get the values (as VALUES (...) or SELECT) - * - * @return the values of the insert - */ - @Deprecated - public ItemsList getItemsList() { - if (select instanceof Values) { - Values valuesStatement = (Values) select; - if (valuesStatement.getExpressions() instanceof ExpressionList) { - ExpressionList expressionList = - (ExpressionList) valuesStatement.getExpressions(); - - if (expressionList.getExpressions().size() == 1 - && expressionList.getExpressions().get(0) instanceof RowConstructor) { - RowConstructor rowConstructor = - (RowConstructor) expressionList.getExpressions().get(0); - return rowConstructor.getExprList(); - } else { - return expressionList; - } - } else { - return valuesStatement.getExpressions(); - } - } - return null; - } - - @Deprecated public boolean isUseValues() { return select != null && select instanceof Values; } - public List getReturningExpressionList() { - return returningExpressionList; + public ReturningClause getReturningClause() { + return returningClause; } - public void setReturningExpressionList(List returningExpressionList) { - this.returningExpressionList = returningExpressionList; + public Insert setReturningClause(ReturningClause returningClause) { + this.returningClause = returningClause; + return this; } public Select getSelect() { @@ -143,33 +124,26 @@ public void setSelect(Select select) { this.select = select; } - @Deprecated - public boolean isUseSelectBrackets() { - return false; - } - - public boolean isUseDuplicate() { - return useDuplicate; - } - - public void setUseDuplicate(boolean useDuplicate) { - this.useDuplicate = useDuplicate; + public Values getValues() { + return select.getValues(); } - public List getDuplicateUpdateColumns() { - return duplicateUpdateColumns; + public PlainSelect getPlainSelect() { + return select.getPlainSelect(); } - public void setDuplicateUpdateColumns(List duplicateUpdateColumns) { - this.duplicateUpdateColumns = duplicateUpdateColumns; + public SetOperationList getSetOperationList() { + return select.getSetOperationList(); } - public List getDuplicateUpdateExpressionList() { - return duplicateUpdateExpressionList; + @Deprecated + public boolean isUseSelectBrackets() { + return false; } - public void setDuplicateUpdateExpressionList(List duplicateUpdateExpressionList) { - this.duplicateUpdateExpressionList = duplicateUpdateExpressionList; + @Deprecated + public boolean isUseDuplicate() { + return duplicateUpdateSets != null && !duplicateUpdateSets.isEmpty(); } public InsertModifierPriority getModifierPriority() { @@ -188,28 +162,10 @@ public void setModifierIgnore(boolean modifierIgnore) { this.modifierIgnore = modifierIgnore; } - public void setUseSet(boolean useSet) { - this.useSet = useSet; - } + @Deprecated public boolean isUseSet() { - return useSet; - } - - public void setSetColumns(List setColumns) { - this.setColumns = setColumns; - } - - public List getSetColumns() { - return setColumns; - } - - public void setSetExpressionList(List setExpressionList) { - this.setExpressionList = setExpressionList; - } - - public List getSetExpressionList() { - return setExpressionList; + return setUpdateSets != null && !setUpdateSets.isEmpty(); } public List getWithItemsList() { @@ -282,26 +238,14 @@ public String toString() { sql.append(select); } - if (useSet) { + if (setUpdateSets != null && !setUpdateSets.isEmpty()) { sql.append("SET "); - for (int i = 0; i < getSetColumns().size(); i++) { - if (i != 0) { - sql.append(", "); - } - sql.append(setColumns.get(i)).append(" = "); - sql.append(setExpressionList.get(i)); - } + sql = UpdateSet.appendUpdateSetsTo(sql, setUpdateSets); } - if (useDuplicate) { + if (duplicateUpdateSets != null && !duplicateUpdateSets.isEmpty()) { sql.append(" ON DUPLICATE KEY UPDATE "); - for (int i = 0; i < getDuplicateUpdateColumns().size(); i++) { - if (i != 0) { - sql.append(", "); - } - sql.append(duplicateUpdateColumns.get(i)).append(" = "); - sql.append(duplicateUpdateExpressionList.get(i)); - } + sql = UpdateSet.appendUpdateSetsTo(sql, duplicateUpdateSets); } if (conflictAction != null) { @@ -313,9 +257,8 @@ public String toString() { conflictAction.appendTo(sql); } - if (getReturningExpressionList() != null) { - sql.append(" RETURNING ") - .append(PlainSelect.getStringList(getReturningExpressionList(), true, false)); + if (returningClause != null) { + returningClause.appendTo(sql); } return sql.toString(); @@ -331,22 +274,6 @@ public Insert withSelect(Select select) { return this; } - public Insert withUseDuplicate(boolean useDuplicate) { - this.setUseDuplicate(useDuplicate); - return this; - } - - public Insert withDuplicateUpdateColumns(List duplicateUpdateColumns) { - this.setDuplicateUpdateColumns(duplicateUpdateColumns); - return this; - } - - public Insert withDuplicateUpdateExpressionList( - List duplicateUpdateExpressionList) { - this.setDuplicateUpdateExpressionList(duplicateUpdateExpressionList); - return this; - } - public Insert withModifierPriority(InsertModifierPriority modifierPriority) { this.setModifierPriority(modifierPriority); return this; @@ -357,124 +284,24 @@ public Insert withModifierIgnore(boolean modifierIgnore) { return this; } - public Insert withReturningExpressionList(List returningExpressionList) { - this.setReturningExpressionList(returningExpressionList); - return this; - } - - public Insert withUseSet(boolean useSet) { - this.setUseSet(useSet); - return this; - } - - public Insert withUseSetColumns(List setColumns) { - this.setSetColumns(setColumns); - return this; - } - - public Insert withSetExpressionList(List setExpressionList) { - this.setSetExpressionList(setExpressionList); - return this; - } - public Insert withTable(Table table) { this.setTable(table); return this; } - public Insert withColumns(List columns) { + public Insert withColumns(ExpressionList columns) { this.setColumns(columns); return this; } - public Insert withSetColumns(List columns) { - this.setSetColumns(columns); - return this; - } - public Insert addColumns(Column... columns) { - List collection = Optional.ofNullable(getColumns()).orElseGet(ArrayList::new); - Collections.addAll(collection, columns); - return this.withColumns(collection); + return addColumns(Arrays.asList(columns)); } - public Insert addColumns(Collection columns) { - List collection = Optional.ofNullable(getColumns()).orElseGet(ArrayList::new); + public Insert addColumns(Collection columns) { + ExpressionList collection = + Optional.ofNullable(getColumns()).orElseGet(ExpressionList::new); collection.addAll(columns); return this.withColumns(collection); } - - public Insert addDuplicateUpdateColumns(Column... duplicateUpdateColumns) { - List collection = - Optional.ofNullable(getDuplicateUpdateColumns()).orElseGet(ArrayList::new); - Collections.addAll(collection, duplicateUpdateColumns); - return this.withDuplicateUpdateColumns(collection); - } - - public Insert addDuplicateUpdateColumns(Collection duplicateUpdateColumns) { - List collection = - Optional.ofNullable(getDuplicateUpdateColumns()).orElseGet(ArrayList::new); - collection.addAll(duplicateUpdateColumns); - return this.withDuplicateUpdateColumns(collection); - } - - public Insert addDuplicateUpdateExpressionList(Expression... duplicateUpdateExpressionList) { - List collection = - Optional.ofNullable(getDuplicateUpdateExpressionList()).orElseGet(ArrayList::new); - Collections.addAll(collection, duplicateUpdateExpressionList); - return this.withDuplicateUpdateExpressionList(collection); - } - - public Insert addDuplicateUpdateExpressionList( - Collection duplicateUpdateExpressionList) { - List collection = - Optional.ofNullable(getDuplicateUpdateExpressionList()).orElseGet(ArrayList::new); - collection.addAll(duplicateUpdateExpressionList); - return this.withDuplicateUpdateExpressionList(collection); - } - - public Insert addReturningExpressionList(SelectItem... returningExpressionList) { - List collection = - Optional.ofNullable(getReturningExpressionList()).orElseGet(ArrayList::new); - Collections.addAll(collection, returningExpressionList); - return this.withReturningExpressionList(collection); - } - - public Insert addReturningExpressionList( - Collection returningExpressionList) { - List collection = - Optional.ofNullable(getReturningExpressionList()).orElseGet(ArrayList::new); - collection.addAll(returningExpressionList); - return this.withReturningExpressionList(collection); - } - - public Insert addSetColumns(Column... setColumns) { - List collection = Optional.ofNullable(getSetColumns()).orElseGet(ArrayList::new); - Collections.addAll(collection, setColumns); - return this.withSetColumns(collection); - } - - public Insert addSetColumns(Collection setColumns) { - List collection = Optional.ofNullable(getSetColumns()).orElseGet(ArrayList::new); - collection.addAll(setColumns); - return this.withSetColumns(collection); - } - - public Insert addSetExpressionList(Expression... setExpressionList) { - List collection = - Optional.ofNullable(getSetExpressionList()).orElseGet(ArrayList::new); - Collections.addAll(collection, setExpressionList); - return this.withSetExpressionList(collection); - } - - public Insert addSetExpressionList(Collection setExpressionList) { - List collection = - Optional.ofNullable(getSetExpressionList()).orElseGet(ArrayList::new); - collection.addAll(setExpressionList); - return this.withSetExpressionList(collection); - } - - public E getItemsList(Class type) { - return type.cast(getItemsList()); - } } diff --git a/src/main/java/net/sf/jsqlparser/statement/insert/InsertConflictAction.java b/src/main/java/net/sf/jsqlparser/statement/insert/InsertConflictAction.java index 9542a7b75..8bbba83b7 100644 --- a/src/main/java/net/sf/jsqlparser/statement/insert/InsertConflictAction.java +++ b/src/main/java/net/sf/jsqlparser/statement/insert/InsertConflictAction.java @@ -16,10 +16,12 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Objects; /** * https://www.postgresql.org/docs/current/sql-insert.html + * *
  * conflict_action is one of:
  *
@@ -35,23 +37,35 @@
 public class InsertConflictAction implements Serializable {
     ConflictActionType conflictActionType;
 
-    private final ArrayList updateSets = new ArrayList<>();
+    private List updateSets;
 
     Expression whereExpression;
+
     public InsertConflictAction(ConflictActionType conflictActionType) {
-        this.conflictActionType = Objects.requireNonNull(conflictActionType, "The Conflict Action Type is mandatory and must not be Null.");
+        this.conflictActionType = Objects.requireNonNull(conflictActionType,
+                "The Conflict Action Type is mandatory and must not be Null.");
     }
 
-    public ArrayList getUpdateSets() {
+    public List getUpdateSets() {
         return updateSets;
     }
 
+    public void setUpdateSets(List updateSets) {
+        this.updateSets = updateSets;
+    }
+
+    public InsertConflictAction withUpdateSets(List updateSets) {
+        this.setUpdateSets(updateSets);
+        return this;
+    }
+
     public ConflictActionType getConflictActionType() {
         return conflictActionType;
     }
 
     public void setConflictActionType(ConflictActionType conflictActionType) {
-        this.conflictActionType = Objects.requireNonNull(conflictActionType, "The Conflict Action Type is mandatory and must not be Null.");
+        this.conflictActionType = Objects.requireNonNull(conflictActionType,
+                "The Conflict Action Type is mandatory and must not be Null.");
     }
 
     public InsertConflictAction withConflictActionType(ConflictActionType conflictActionType) {
@@ -60,18 +74,19 @@ public InsertConflictAction withConflictActionType(ConflictActionType conflictAc
     }
 
     public InsertConflictAction addUpdateSet(Column column, Expression expression) {
-        this.updateSets.add(new UpdateSet(column, expression));
-        return this;
+        return this.addUpdateSet(new UpdateSet());
     }
 
     public InsertConflictAction addUpdateSet(UpdateSet updateSet) {
+        if (updateSets == null) {
+            updateSets = new ArrayList<>();
+        }
         this.updateSets.add(updateSet);
         return this;
     }
 
     public InsertConflictAction withUpdateSets(Collection updateSets) {
-        this.updateSets.clear();
-        this.updateSets.addAll(updateSets);
+        this.setUpdateSets(new ArrayList<>(updateSets));
         return this;
     }
 
@@ -95,10 +110,10 @@ public StringBuilder appendTo(StringBuilder builder) {
                 builder.append(" DO NOTHING");
                 break;
             case DO_UPDATE:
-                builder.append(" DO UPDATE ");
+                builder.append(" DO UPDATE SET ");
                 UpdateSet.appendUpdateSetsTo(builder, updateSets);
 
-                if (whereExpression!=null) {
+                if (whereExpression != null) {
                     builder.append(" WHERE ").append(whereExpression);
                 }
                 break;
diff --git a/src/main/java/net/sf/jsqlparser/statement/insert/InsertModifierPriority.java b/src/main/java/net/sf/jsqlparser/statement/insert/InsertModifierPriority.java
index 534281e8f..1e132893f 100644
--- a/src/main/java/net/sf/jsqlparser/statement/insert/InsertModifierPriority.java
+++ b/src/main/java/net/sf/jsqlparser/statement/insert/InsertModifierPriority.java
@@ -10,5 +10,9 @@
 package net.sf.jsqlparser.statement.insert;
 
 public enum InsertModifierPriority {
-    LOW_PRIORITY, DELAYED, HIGH_PRIORITY, IGNORE
+    LOW_PRIORITY, DELAYED, HIGH_PRIORITY, IGNORE;
+
+    public final static InsertModifierPriority from(String priority) {
+        return Enum.valueOf(InsertModifierPriority.class, priority.toUpperCase());
+    }
 }
diff --git a/src/main/java/net/sf/jsqlparser/statement/merge/MergeInsert.java b/src/main/java/net/sf/jsqlparser/statement/merge/MergeInsert.java
index 45b21c593..bc9ea695a 100644
--- a/src/main/java/net/sf/jsqlparser/statement/merge/MergeInsert.java
+++ b/src/main/java/net/sf/jsqlparser/statement/merge/MergeInsert.java
@@ -9,38 +9,37 @@
  */
 package net.sf.jsqlparser.statement.merge;
 
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
+import net.sf.jsqlparser.schema.Column;
+
 import java.io.Serializable;
-import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
 import java.util.Optional;
-import net.sf.jsqlparser.expression.Expression;
-import net.sf.jsqlparser.schema.Column;
-import net.sf.jsqlparser.statement.select.PlainSelect;
 
 public class MergeInsert implements Serializable {
 
-    private List columns = null;
-    private List values = null;
+    private ExpressionList columns;
+    private ExpressionList values;
     private Expression whereCondition;
 
-    public List getColumns() {
+    public ExpressionList getColumns() {
         return columns;
     }
 
-    public void setColumns(List columns) {
+    public void setColumns(ExpressionList columns) {
         this.columns = columns;
     }
 
-    public List getValues() {
+    public ExpressionList getValues() {
         return values;
     }
 
-    public void setValues(List values) {
+    public void setValues(ExpressionList values) {
         this.values = values;
     }
-    
+
     public Expression getWhereCondition() {
         return whereCondition;
     }
@@ -52,53 +51,51 @@ public void setWhereCondition(Expression whereCondition) {
     @Override
     public String toString() {
         return " WHEN NOT MATCHED THEN INSERT "
-                + (columns.isEmpty() ? "" : PlainSelect.getStringList(columns, true, true))
-                + " VALUES " + PlainSelect.getStringList(values, true, true)
-                + ( whereCondition != null 
+                + (columns != null ? columns.toString() : "")
+                + " VALUES " + values.toString()
+                + (whereCondition != null
                         ? " WHERE " + whereCondition
-                        : "" );
+                        : "");
     }
 
-    public MergeInsert withColumns(List columns) {
+    public MergeInsert withColumns(ExpressionList columns) {
         this.setColumns(columns);
         return this;
     }
 
-    public MergeInsert withValues(List values) {
+    public MergeInsert withValues(ExpressionList values) {
         this.setValues(values);
         return this;
     }
 
     public MergeInsert addColumns(Column... columns) {
-        List collection = Optional.ofNullable(getColumns()).orElseGet(ArrayList::new);
-        Collections.addAll(collection, columns);
-        return this.withColumns(collection);
+        return this.addColumns(Arrays.asList(columns));
     }
 
     public MergeInsert addColumns(Collection columns) {
-        List collection = Optional.ofNullable(getColumns()).orElseGet(ArrayList::new);
+        ExpressionList collection =
+                Optional.ofNullable(getColumns()).orElseGet(ExpressionList::new);
         collection.addAll(columns);
         return this.withColumns(collection);
     }
 
     public MergeInsert addValues(Expression... values) {
-        List collection = Optional.ofNullable(getValues()).orElseGet(ArrayList::new);
-        Collections.addAll(collection, values);
-        return this.withValues(collection);
+        return this.addValues(Arrays.asList(values));
     }
 
     public MergeInsert addValues(Collection values) {
-        List collection = Optional.ofNullable(getValues()).orElseGet(ArrayList::new);
+        ExpressionList collection =
+                Optional.ofNullable(getValues()).orElseGet(ExpressionList::new);
         collection.addAll(values);
         return this.withValues(collection);
     }
-    
-     public MergeInsert withWhereCondition(Expression whereCondition) {
+
+    public MergeInsert withWhereCondition(Expression whereCondition) {
         this.setWhereCondition(whereCondition);
         return this;
     }
-     
-     public  E getWhereCondition(Class type) {
+
+    public  E getWhereCondition(Class type) {
         return type.cast(getWhereCondition());
     }
 }
diff --git a/src/main/java/net/sf/jsqlparser/statement/merge/MergeUpdate.java b/src/main/java/net/sf/jsqlparser/statement/merge/MergeUpdate.java
index 799e664f4..e69c595f9 100644
--- a/src/main/java/net/sf/jsqlparser/statement/merge/MergeUpdate.java
+++ b/src/main/java/net/sf/jsqlparser/statement/merge/MergeUpdate.java
@@ -9,36 +9,29 @@
  */
 package net.sf.jsqlparser.statement.merge;
 
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.statement.update.UpdateSet;
+
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
-import java.util.Optional;
-import net.sf.jsqlparser.expression.Expression;
-import net.sf.jsqlparser.schema.Column;
 
 public class MergeUpdate implements Serializable {
 
-    private List columns = null;
-    private List values = null;
+    private List updateSets;
     private Expression whereCondition;
     private Expression deleteWhereCondition;
 
-    public List getColumns() {
-        return columns;
+    public MergeUpdate(List updateSets) {
+        this.updateSets = updateSets;
     }
 
-    public void setColumns(List columns) {
-        this.columns = columns;
+    public List getUpdateSets() {
+        return updateSets;
     }
 
-    public List getValues() {
-        return values;
-    }
-
-    public void setValues(List values) {
-        this.values = values;
+    public MergeUpdate setUpdateSets(List updateSets) {
+        this.updateSets = updateSets;
+        return this;
     }
 
     public Expression getWhereCondition() {
@@ -61,12 +54,8 @@ public void setDeleteWhereCondition(Expression deleteWhereCondition) {
     public String toString() {
         StringBuilder b = new StringBuilder();
         b.append(" WHEN MATCHED THEN UPDATE SET ");
-        for (int i = 0; i < columns.size(); i++) {
-            if (i != 0) {
-                b.append(", ");
-            }
-            b.append(columns.get(i).toString()).append(" = ").append(values.get(i).toString());
-        }
+        UpdateSet.appendUpdateSetsTo(b, updateSets);
+
         if (whereCondition != null) {
             b.append(" WHERE ").append(whereCondition.toString());
         }
@@ -76,16 +65,6 @@ public String toString() {
         return b.toString();
     }
 
-    public MergeUpdate withColumns(List columns) {
-        this.setColumns(columns);
-        return this;
-    }
-
-    public MergeUpdate withValues(List values) {
-        this.setValues(values);
-        return this;
-    }
-
     public MergeUpdate withWhereCondition(Expression whereCondition) {
         this.setWhereCondition(whereCondition);
         return this;
@@ -96,30 +75,6 @@ public MergeUpdate withDeleteWhereCondition(Expression deleteWhereCondition) {
         return this;
     }
 
-    public MergeUpdate addColumns(Column... columns) {
-        List collection = Optional.ofNullable(getColumns()).orElseGet(ArrayList::new);
-        Collections.addAll(collection, columns);
-        return this.withColumns(collection);
-    }
-
-    public MergeUpdate addColumns(Collection columns) {
-        List collection = Optional.ofNullable(getColumns()).orElseGet(ArrayList::new);
-        collection.addAll(columns);
-        return this.withColumns(collection);
-    }
-
-    public MergeUpdate addValues(Expression... values) {
-        List collection = Optional.ofNullable(getValues()).orElseGet(ArrayList::new);
-        Collections.addAll(collection, values);
-        return this.withValues(collection);
-    }
-
-    public MergeUpdate addValues(Collection values) {
-        List collection = Optional.ofNullable(getValues()).orElseGet(ArrayList::new);
-        collection.addAll(values);
-        return this.withValues(collection);
-    }
-
     public  E getWhereCondition(Class type) {
         return type.cast(getWhereCondition());
     }
diff --git a/src/main/java/net/sf/jsqlparser/statement/replace/Replace.java b/src/main/java/net/sf/jsqlparser/statement/replace/Replace.java
deleted file mode 100644
index 3c1f6a289..000000000
--- a/src/main/java/net/sf/jsqlparser/statement/replace/Replace.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*-
- * #%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.replace;
-
-import net.sf.jsqlparser.expression.Expression;
-import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
-import net.sf.jsqlparser.statement.upsert.Upsert;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-
-/**
- * Not Standard compliant REPLACE Statement
- * @deprecated
- * This class has been merged into the UPSERT statement and should not longer been used.
- * 

Use {@link Upsert} instead. - * - */ - -@Deprecated -public class Replace extends Upsert { - - @Deprecated - public boolean isUseIntoTables() { - return super.isUsingInto(); - } - - @Deprecated - public void setUseIntoTables(boolean useIntoTables) { - super.setUsingInto( useIntoTables ); - } - - @Deprecated - /** - * A list of {@link net.sf.jsqlparser.expression.Expression}s (from a "REPLACE mytab SET - * col1=exp1, col2=exp2").
- * it is null in case of a "REPLACE mytab (col1, col2) [...]" - */ - public List getExpressions() { - return super.getSetExpressions(); - } - - @Deprecated - public void setExpressions(List list) { - super.setItemsList( new ExpressionList(list) ); - } - - @Deprecated - public Replace withUseIntoTables(boolean useIntoTables) { - super.setUsingInto(useIntoTables); - return this; - } - - @Deprecated - public Replace withExpressions(List expressions) { - super.setItemsList( new ExpressionList(expressions) ); - return this; - } - - @Deprecated - public Replace addExpressions(Expression... expressions) { - List collection = Optional.ofNullable( super.getSetExpressions() ).orElseGet(ArrayList::new); - Collections.addAll(collection, expressions); - return this.withExpressions(collection); - } - - @Deprecated - public Replace addExpressions(Collection expressions) { - List collection = Optional.ofNullable( super.getSetExpressions() ).orElseGet(ArrayList::new); - collection.addAll(expressions); - return this.withExpressions(collection); - } -} diff --git a/src/main/java/net/sf/jsqlparser/statement/select/AllColumns.java b/src/main/java/net/sf/jsqlparser/statement/select/AllColumns.java index 31b1cc452..8a4771ab2 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/AllColumns.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/AllColumns.java @@ -13,13 +13,7 @@ import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; -public class AllColumns extends ASTNodeAccessImpl implements SelectItem, Expression { - - @Override - public void accept(SelectItemVisitor selectItemVisitor) { - selectItemVisitor.visit(this); - } - +public class AllColumns extends ASTNodeAccessImpl implements Expression { @Override public String toString() { return "*"; diff --git a/src/main/java/net/sf/jsqlparser/statement/select/AllTableColumns.java b/src/main/java/net/sf/jsqlparser/statement/select/AllTableColumns.java index 8e6d533d8..6e5df9807 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/AllTableColumns.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/AllTableColumns.java @@ -14,12 +14,11 @@ import net.sf.jsqlparser.parser.ASTNodeAccessImpl; import net.sf.jsqlparser.schema.*; -public class AllTableColumns extends ASTNodeAccessImpl implements SelectItem, Expression { +public class AllTableColumns extends ASTNodeAccessImpl implements Expression { private Table table; - public AllTableColumns() { - } + public AllTableColumns() {} public AllTableColumns(Table tableName) { this.table = tableName; @@ -33,11 +32,6 @@ public void setTable(Table table) { this.table = table; } - @Override - public void accept(SelectItemVisitor selectItemVisitor) { - selectItemVisitor.visit(this); - } - @Override public String toString() { return table + ".*"; diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Distinct.java b/src/main/java/net/sf/jsqlparser/statement/select/Distinct.java index 6a1113bcd..37f64ad81 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Distinct.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Distinct.java @@ -18,21 +18,20 @@ public class Distinct implements Serializable { - private List onSelectItems; + private List> onSelectItems; private boolean useUnique = false; - public Distinct() { - } + public Distinct() {} public Distinct(boolean useUnique) { this.useUnique = useUnique; } - public List getOnSelectItems() { + public List> getOnSelectItems() { return onSelectItems; } - public void setOnSelectItems(List list) { + public void setOnSelectItems(List> list) { onSelectItems = list; } @@ -55,7 +54,7 @@ public String toString() { return sql; } - public Distinct withOnSelectItems(List onSelectItems) { + public Distinct withOnSelectItems(List> onSelectItems) { this.setOnSelectItems(onSelectItems); return this; } @@ -65,14 +64,16 @@ public Distinct withUseUnique(boolean useUnique) { return this; } - public Distinct addOnSelectItems(SelectItem... onSelectItems) { - List collection = Optional.ofNullable(getOnSelectItems()).orElseGet(ArrayList::new); + public Distinct addOnSelectItems(SelectItem... onSelectItems) { + List> collection = + Optional.ofNullable(getOnSelectItems()).orElseGet(ArrayList::new); Collections.addAll(collection, onSelectItems); return this.withOnSelectItems(collection); } - public Distinct addOnSelectItems(Collection onSelectItems) { - List collection = Optional.ofNullable(getOnSelectItems()).orElseGet(ArrayList::new); + public Distinct addOnSelectItems(Collection> onSelectItems) { + List> collection = + Optional.ofNullable(getOnSelectItems()).orElseGet(ArrayList::new); collection.addAll(onSelectItems); return this.withOnSelectItems(collection); } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/ExpressionListItem.java b/src/main/java/net/sf/jsqlparser/statement/select/ExpressionListItem.java deleted file mode 100644 index 0a8fee08c..000000000 --- a/src/main/java/net/sf/jsqlparser/statement/select/ExpressionListItem.java +++ /dev/null @@ -1,52 +0,0 @@ -/*- - * #%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.select; - -import net.sf.jsqlparser.expression.Alias; -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; - -import java.io.Serializable; - -public class ExpressionListItem implements Serializable { - - private ExpressionList expressionList; - private Alias alias; - - public ExpressionList getExpressionList() { - return expressionList; - } - - public void setExpressionList(ExpressionList expressionList) { - this.expressionList = expressionList; - } - - public Alias getAlias() { - return alias; - } - - public void setAlias(Alias alias) { - this.alias = alias; - } - - @Override - public String toString() { - return expressionList + ((alias != null) ? alias.toString() : ""); - } - - public ExpressionListItem withExpressionList(ExpressionList expressionList) { - this.setExpressionList(expressionList); - return this; - } - - public ExpressionListItem withAlias(Alias alias) { - this.setAlias(alias); - return this; - } -} diff --git a/src/main/java/net/sf/jsqlparser/statement/select/First.java b/src/main/java/net/sf/jsqlparser/statement/select/First.java index 8a54cdf47..b6d872941 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/First.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/First.java @@ -16,8 +16,11 @@ public class First implements Serializable { public enum Keyword { - FIRST, - LIMIT + FIRST, LIMIT; + + public static Keyword from(String keyword) { + return Enum.valueOf(Keyword.class, keyword.toUpperCase()); + } } private Keyword keyword; @@ -71,7 +74,7 @@ public String toString() { return result; } - + public First withKeyword(Keyword keyword) { this.setKeyword(keyword); return this; diff --git a/src/main/java/net/sf/jsqlparser/statement/select/FunctionItem.java b/src/main/java/net/sf/jsqlparser/statement/select/FunctionItem.java deleted file mode 100644 index 63ea3fbb8..000000000 --- a/src/main/java/net/sf/jsqlparser/statement/select/FunctionItem.java +++ /dev/null @@ -1,51 +0,0 @@ -/*- - * #%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.select; - -import net.sf.jsqlparser.Model; -import net.sf.jsqlparser.expression.Alias; -import net.sf.jsqlparser.expression.Function; - -public class FunctionItem implements Model { - - private Function function; - private Alias alias; - - public Alias getAlias() { - return alias; - } - - public void setAlias(Alias alias) { - this.alias = alias; - } - - public Function getFunction() { - return function; - } - - public void setFunction(Function function) { - this.function = function; - } - - @Override - public String toString() { - return function + ((alias != null) ? alias.toString() : ""); - } - - public FunctionItem withFunction(Function function) { - this.setFunction(function); - return this; - } - - public FunctionItem withAlias(Alias alias) { - this.setAlias(alias); - return this; - } -} diff --git a/src/main/java/net/sf/jsqlparser/statement/select/GroupByElement.java b/src/main/java/net/sf/jsqlparser/statement/select/GroupByElement.java index 19400ce12..4aa45bbf0 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/GroupByElement.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/GroupByElement.java @@ -9,75 +9,59 @@ */ package net.sf.jsqlparser.statement.select; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; + import java.io.Serializable; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; -import net.sf.jsqlparser.expression.Expression; -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; public class GroupByElement implements Serializable { - // ExpressionList has 'usingBrackets = true' and so we need to switch it off explicitly - private ExpressionList groupByExpressions = new ExpressionList().withUsingBrackets(false); - private List groupingSets = new ArrayList(); + private ExpressionList groupByExpressions = new ExpressionList(); + private List groupingSets = new ArrayList<>(); public boolean isUsingBrackets() { return groupByExpressions.isUsingBrackets(); } - public void setUsingBrackets(boolean usingBrackets) { - this.groupByExpressions.setUsingBrackets(usingBrackets); - } - - public GroupByElement withUsingBrackets(boolean usingBrackets) { - this.groupByExpressions.setUsingBrackets(usingBrackets); - return this; - } - public void accept(GroupByVisitor groupByVisitor) { groupByVisitor.visit(this); } - + public ExpressionList getGroupByExpressionList() { return groupByExpressions; } - - public void setGroupByExpressionList(ExpressionList groupByExpressions) { - this.groupByExpressions=groupByExpressions; - } - - @Deprecated - public List getGroupByExpressions() { - return groupByExpressions.getExpressions(); + + public void setGroupByExpressions(ExpressionList groupByExpressions) { + this.groupByExpressions = groupByExpressions; } @Deprecated - public void setGroupByExpressions(List groupByExpressions) { - this.groupByExpressions.setExpressions(groupByExpressions); + public ExpressionList getGroupByExpressions() { + return groupByExpressions; } @Deprecated public void addGroupByExpression(Expression groupByExpression) { - if (groupByExpressions.getExpressions()==null) { + if (groupByExpressions.getExpressions() == null) { groupByExpressions.setExpressions(new ArrayList()); } groupByExpressions.getExpressions().add(groupByExpression); } - public List getGroupingSets() { + public List getGroupingSets() { return groupingSets; } - public void setGroupingSets(List groupingSets) { + public void setGroupingSets(List groupingSets) { this.groupingSets = groupingSets; } - public void addGroupingSet(Expression expr) { - this.groupingSets.add(expr); - } - public void addGroupingSet(ExpressionList list) { this.groupingSets.add(list); } @@ -88,36 +72,20 @@ public String toString() { StringBuilder b = new StringBuilder(); b.append("GROUP BY "); - if (groupByExpressions.getExpressions()!=null && groupByExpressions.getExpressions().size() > 0) { - if (groupByExpressions.isUsingBrackets()) { - b.append("( "); - } - b.append(PlainSelect.getStringList(groupByExpressions.getExpressions())); - if (groupByExpressions.isUsingBrackets()) { - b.append(" )"); - } - } else if (groupByExpressions.isUsingBrackets()) { - b.append("()"); + if (groupByExpressions != null) { + b.append(groupByExpressions.toString()); } + int i = 0; if (groupingSets.size() > 0) { if (b.charAt(b.length() - 1) != ' ') { b.append(' '); } b.append("GROUPING SETS ("); - boolean first = true; - for (Object o : groupingSets) { - if (first) { - first = false; - } else { - b.append(", "); - } - if (o instanceof Expression) { - b.append(o.toString()); - } else if (o instanceof ExpressionList) { - ExpressionList list = (ExpressionList) o; - b.append(list.getExpressions() == null ? "()" : list.toString()); - } + for (ExpressionList expressionList : groupingSets) { + b.append(i++ > 0 ? ", " : "").append(Select.getStringList( + expressionList, + true, expressionList instanceof ParenthesedExpressionList)); } b.append(")"); } @@ -125,7 +93,7 @@ public String toString() { return b.toString(); } - public GroupByElement withGroupByExpressions(List groupByExpressions) { + public GroupByElement withGroupByExpressions(ExpressionList groupByExpressions) { this.setGroupByExpressions(groupByExpressions); return this; } @@ -136,16 +104,14 @@ public GroupByElement withGroupingSets(List groupingSets) { } public GroupByElement addGroupByExpressions(Expression... groupByExpressions) { - List collection - = Optional.ofNullable(getGroupByExpressions()).orElseGet(ArrayList::new); - Collections.addAll(collection, groupByExpressions); - return this.withGroupByExpressions(collection); + return this.addGroupByExpressions(Arrays.asList(groupByExpressions)); } - public GroupByElement addGroupByExpressions(Collection groupByExpressions) { - List collection - = Optional.ofNullable(getGroupByExpressions()).orElseGet(ArrayList::new); - collection.addAll(groupByExpressions); + public GroupByElement addGroupByExpressions( + Collection groupByExpressions) { + ExpressionList collection = + Optional.ofNullable(getGroupByExpressions()).orElseGet(ExpressionList::new); + Collections.addAll(collection, groupByExpressions); return this.withGroupByExpressions(collection); } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Join.java b/src/main/java/net/sf/jsqlparser/statement/select/Join.java index 7aea9c8a3..96f908c6a 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Join.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Join.java @@ -52,6 +52,29 @@ public void setSimple(boolean b) { simple = b; } + /** + * A JOIN means INNER when the INNER keyword is set or when no other qualifier has been set. + * + * @return Tells, if a JOIN means a qualified INNER JOIN. + * + */ + public boolean isInnerJoin() { + return inner + || !( + /* Qualified Joins */ + left || right || full || outer + + /* Cross Join */ + || cross + + /* Natural Join */ + || natural); + } + + /** + * + * @return Tells, if the INNER keyword has been set. + */ public boolean isInner() { return inner; } @@ -61,7 +84,18 @@ public Join withInner(boolean b) { return this; } + /** + * + * @return Sets the INNER keyword and switches off any contradicting qualifiers automatically. + */ public void setInner(boolean b) { + if (b) { + left = false; + right = false; + outer = false; + cross = false; + natural = false; + } inner = b; } @@ -92,7 +126,14 @@ public Join withOuter(boolean b) { return this; } + /** + * + * @return Sets the OUTER keyword and switches off any contradicting qualifiers automatically. + */ public void setOuter(boolean b) { + if (b) { + inner = false; + } outer = b; } @@ -141,7 +182,15 @@ public Join withLeft(boolean b) { return this; } + /** + * + * @return Sets the LEFT keyword and switches off any contradicting qualifiers automatically. + */ public void setLeft(boolean b) { + if (b) { + inner = false; + right = false; + } left = b; } @@ -159,7 +208,15 @@ public Join withRight(boolean b) { return this; } + /** + * + * @return Sets the RIGHT keyword and switches off any contradicting qualifiers automatically. + */ public void setRight(boolean b) { + if (b) { + inner = false; + left = false; + } right = b; } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/KSQLJoinWindow.java b/src/main/java/net/sf/jsqlparser/statement/select/KSQLJoinWindow.java index e473a16a6..a1598aac8 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/KSQLJoinWindow.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/KSQLJoinWindow.java @@ -10,32 +10,10 @@ package net.sf.jsqlparser.statement.select; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import static net.sf.jsqlparser.statement.select.KSQLWindow.TimeUnit; public class KSQLJoinWindow extends ASTNodeAccessImpl { - public enum TimeUnit { - DAY ("DAY"), - HOUR ("HOUR"), - MINUTE ("MINUTE"), - SECOND ("SECOND"), - MILLISECOND ("MILLISECOND"), - DAYS ("DAYS"), - HOURS ("HOURS"), - MINUTES ("MINUTES"), - SECONDS ("SECONDS"), - MILLISECONDS ("MILLISECONDS"); - - private String timeUnit; - - TimeUnit(String timeUnit) { - this.timeUnit = timeUnit; - } - - public String getTimeUnit() { - return timeUnit; - } - } - private boolean beforeAfter; private long duration; private TimeUnit timeUnit; @@ -44,9 +22,6 @@ public String getTimeUnit() { private long afterDuration; private TimeUnit afterTimeUnit; - public KSQLJoinWindow() { - } - public boolean isBeforeAfterWindow() { return beforeAfter; } @@ -106,7 +81,8 @@ public void setAfterTimeUnit(TimeUnit afterTimeUnit) { @Override public String toString() { if (isBeforeAfterWindow()) { - return "(" + beforeDuration + " " + beforeTimeUnit + ", " + afterDuration + " " + afterTimeUnit + ")"; + return "(" + beforeDuration + " " + beforeTimeUnit + ", " + afterDuration + " " + + afterTimeUnit + ")"; } return "(" + duration + " " + timeUnit + ")"; } @@ -140,4 +116,8 @@ public KSQLJoinWindow withAfterTimeUnit(TimeUnit afterTimeUnit) { this.setAfterTimeUnit(afterTimeUnit); return this; } + + public final static TimeUnit from(String timeUnitStr) { + return Enum.valueOf(TimeUnit.class, timeUnitStr.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/KSQLWindow.java b/src/main/java/net/sf/jsqlparser/statement/select/KSQLWindow.java index 133bd3bdf..79d0b5492 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/KSQLWindow.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/KSQLWindow.java @@ -14,32 +14,15 @@ public class KSQLWindow extends ASTNodeAccessImpl { public enum TimeUnit { - DAY ("DAY"), - HOUR ("HOUR"), - MINUTE ("MINUTE"), - SECOND ("SECOND"), - MILLISECOND ("MILLISECOND"), - DAYS ("DAYS"), - HOURS ("HOURS"), - MINUTES ("MINUTES"), - SECONDS ("SECONDS"), - MILLISECONDS ("MILLISECONDS"); - - private String timeUnit; - - TimeUnit(String timeUnit) { - this.timeUnit = timeUnit; - } + DAY, HOUR, MINUTE, SECOND, MILLISECOND, DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS; - public String getTimeUnit() { - return timeUnit; + public static TimeUnit from(String unit) { + return Enum.valueOf(TimeUnit.class, unit.toUpperCase()); } } public enum WindowType { - HOPPING ("HOPPING"), - SESSION ("SESSION"), - TUMBLING ("TUMBLING"); + HOPPING("HOPPING"), SESSION("SESSION"), TUMBLING("TUMBLING"); private String windowType; @@ -50,6 +33,10 @@ public enum WindowType { public String getWindowType() { return windowType; } + + public static WindowType from(String type) { + return Enum.valueOf(WindowType.class, type.toUpperCase()); + } } private boolean hopping; @@ -116,8 +103,7 @@ public void setAdvanceTimeUnit(TimeUnit advanceTimeUnit) { this.advanceTimeUnit = advanceTimeUnit; } - public KSQLWindow() { - } + public KSQLWindow() {} @Override public String toString() { diff --git a/src/main/java/net/sf/jsqlparser/statement/select/LateralView.java b/src/main/java/net/sf/jsqlparser/statement/select/LateralView.java new file mode 100644 index 000000000..0336d4028 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/statement/select/LateralView.java @@ -0,0 +1,106 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement.select; + +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.expression.Function; + +import java.io.Serializable; + +public class LateralView implements Serializable { + private boolean isUsingOuter = false; + private Function generatorFunction; + private Alias tableAlias = null; + private Alias columnAlias; + + public LateralView(boolean useOuter, Function generatorFunction, Alias tableAlias, + Alias columnAlias) { + this.isUsingOuter = useOuter; + this.generatorFunction = generatorFunction; + this.tableAlias = tableAlias; + this.columnAlias = columnAlias; + } + + public boolean isUsingOuter() { + return isUsingOuter; + } + + public void setUsingOuter(boolean useOuter) { + this.isUsingOuter = useOuter; + } + + public LateralView withOuter(boolean useOuter) { + this.setUsingOuter(useOuter); + return this; + } + + public Function getGeneratorFunction() { + return generatorFunction; + } + + public void setGeneratorFunction(Function generatorFunction) { + this.generatorFunction = generatorFunction; + } + + public LateralView withGeneratorFunction(Function generatorFunction) { + this.setGeneratorFunction(generatorFunction); + return this; + } + + public Alias getTableAlias() { + return tableAlias; + } + + public void setTableAlias(Alias tableAlias) { + this.tableAlias = tableAlias; + } + + public LateralView withTableAlias(Alias tableAlias) { + // "AS" is not allowed here, so overwrite hard + this.setTableAlias(tableAlias != null ? tableAlias.withUseAs(false) : null); + return this; + } + + public Alias getColumnAlias() { + return columnAlias; + } + + public void setColumnAlias(Alias columnAlias) { + this.columnAlias = columnAlias; + } + + public LateralView withColumnAlias(Alias columnAlias) { + // "AS" is required here, so overwrite + this.setColumnAlias(columnAlias.withUseAs(true)); + return this; + } + + public StringBuilder appendTo(StringBuilder builder) { + builder.append("LATERAL VIEW"); + + if (isUsingOuter) { + builder.append(" OUTER"); + } + + builder.append(" ").append(generatorFunction); + if (tableAlias != null) { + builder.append(" ").append(tableAlias); + } + + builder.append(" ").append(columnAlias); + + return builder; + } + + @Override + public String toString() { + return appendTo(new StringBuilder()).toString(); + } +} diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Limit.java b/src/main/java/net/sf/jsqlparser/statement/select/Limit.java index bc625b3df..0c39bde05 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Limit.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Limit.java @@ -12,13 +12,26 @@ import net.sf.jsqlparser.expression.AllValue; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.NullValue; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import java.util.Arrays; + public class Limit extends ASTNodeAccessImpl { private Expression rowCount; private Expression offset; + /** + * A query with the LIMIT n BY expressions clause selects the first n rows for each distinct + * value of expressions. The key for LIMIT BY can contain any number of expressions. + * + * @see ClickHouse + * LIMIT BY Clause + */ + private ExpressionList byExpressions; + public Expression getOffset() { return offset; } @@ -75,6 +88,10 @@ public String toString() { } } + if (byExpressions != null) { + retVal += " BY " + byExpressions.toString(); + } + return retVal; } @@ -107,4 +124,32 @@ public E getOffset(Class type) { public E getRowCount(Class type) { return type.cast(getRowCount()); } + + public ExpressionList getByExpressions() { + return byExpressions; + } + + public void setByExpressions(ExpressionList byExpressions) { + this.byExpressions = byExpressions; + } + + public void setByExpressions(Expression... byExpressions) { + this.setByExpressions(new ExpressionList<>(byExpressions)); + } + + public void addByExpression(Expression byExpression) { + if (byExpression == null) { + byExpressions = new ExpressionList<>(); + } + byExpressions.add(byExpression); + } + + public Limit withByExpressions(ExpressionList byExpressions) { + this.setByExpressions(byExpressions); + return this; + } + + public Limit withByExpressions(Expression... byExpressions) { + return withByExpressions(new ExpressionList<>(Arrays.asList(byExpressions))); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/MySqlSqlCacheFlags.java b/src/main/java/net/sf/jsqlparser/statement/select/MySqlSqlCacheFlags.java index e4723e735..de7ba026e 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/MySqlSqlCacheFlags.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/MySqlSqlCacheFlags.java @@ -14,5 +14,9 @@ * @author tw */ public enum MySqlSqlCacheFlags { - SQL_CACHE, SQL_NO_CACHE + SQL_CACHE, SQL_NO_CACHE; + + public static MySqlSqlCacheFlags from(String flag) { + return Enum.valueOf(MySqlSqlCacheFlags.class, flag.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/OrderByElement.java b/src/main/java/net/sf/jsqlparser/statement/select/OrderByElement.java index d9d1c6f85..acba858fd 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/OrderByElement.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/OrderByElement.java @@ -16,8 +16,11 @@ public class OrderByElement implements Serializable { public enum NullOrdering { - NULLS_FIRST, - NULLS_LAST + NULLS_FIRST, NULLS_LAST; + + public static NullOrdering from(String ordering) { + return Enum.valueOf(NullOrdering.class, ordering.toUpperCase()); + } } private Expression expression; diff --git a/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java b/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java index 516b9ca8b..e9ae400b6 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java @@ -1,3 +1,12 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ package net.sf.jsqlparser.statement.select; import net.sf.jsqlparser.expression.Alias; diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Pivot.java b/src/main/java/net/sf/jsqlparser/statement/select/Pivot.java index f95474854..fd6f43035 100755 --- a/src/main/java/net/sf/jsqlparser/statement/select/Pivot.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Pivot.java @@ -9,56 +9,60 @@ */ package net.sf.jsqlparser.statement.select; +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.expression.Function; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; +import net.sf.jsqlparser.schema.Column; + import java.io.Serializable; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; -import net.sf.jsqlparser.expression.Alias; -import net.sf.jsqlparser.schema.Column; public class Pivot implements Serializable { - private List functionItems; - private List forColumns; - private List singleInItems; - private List multiInItems; + private List> functionItems; + private ExpressionList forColumns; + private List> singleInItems; + private List> multiInItems; private Alias alias; public void accept(PivotVisitor pivotVisitor) { pivotVisitor.visit(this); } - public List getSingleInItems() { + public List> getSingleInItems() { return singleInItems; } - public void setSingleInItems(List singleInItems) { + public void setSingleInItems(List> singleInItems) { this.singleInItems = singleInItems; } - public List getMultiInItems() { + public List> getMultiInItems() { return multiInItems; } - public void setMultiInItems(List multiInItems) { + public void setMultiInItems(List> multiInItems) { this.multiInItems = multiInItems; } - public List getFunctionItems() { + public List> getFunctionItems() { return functionItems; } - public void setFunctionItems(List functionItems) { + public void setFunctionItems(List> functionItems) { this.functionItems = functionItems; } - public List getForColumns() { + public ExpressionList getForColumns() { return forColumns; } - public void setForColumns(List forColumns) { + public void setForColumns(ExpressionList forColumns) { this.forColumns = forColumns; } @@ -78,28 +82,29 @@ public void setAlias(Alias alias) { public String toString() { return "PIVOT (" + PlainSelect.getStringList(functionItems) - + " FOR " + PlainSelect. - getStringList(forColumns, true, forColumns != null && forColumns.size() > 1) + + " FOR " + + PlainSelect.getStringList(forColumns, true, + forColumns != null && forColumns.size() > 1) + " IN " + PlainSelect.getStringList(getInItems(), true, true) + ")" - + (alias!=null?alias.toString():""); + + (alias != null ? alias.toString() : ""); } - public Pivot withFunctionItems(List functionItems) { + public Pivot withFunctionItems(List> functionItems) { this.setFunctionItems(functionItems); return this; } - public Pivot withForColumns(List forColumns) { + public Pivot withForColumns(ExpressionList forColumns) { this.setForColumns(forColumns); return this; } - public Pivot withSingleInItems(List singleInItems) { + public Pivot withSingleInItems(List> singleInItems) { this.setSingleInItems(singleInItems); return this; } - public Pivot withMultiInItems(List multiInItems) { + public Pivot withMultiInItems(List> multiInItems) { this.setMultiInItems(multiInItems); return this; } @@ -109,50 +114,55 @@ public Pivot withAlias(Alias alias) { return this; } - public Pivot addFunctionItems(FunctionItem... functionItems) { - List collection = Optional.ofNullable(getFunctionItems()).orElseGet(ArrayList::new); + public Pivot addFunctionItems(SelectItem... functionItems) { + List> collection = + Optional.ofNullable(getFunctionItems()).orElseGet(ArrayList::new); Collections.addAll(collection, functionItems); return this.withFunctionItems(collection); } - public Pivot addFunctionItems(Collection functionItems) { - List collection = Optional.ofNullable(getFunctionItems()).orElseGet(ArrayList::new); + public Pivot addFunctionItems(Collection> functionItems) { + List> collection = + Optional.ofNullable(getFunctionItems()).orElseGet(ArrayList::new); collection.addAll(functionItems); return this.withFunctionItems(collection); } public Pivot addForColumns(Column... forColumns) { - List collection = Optional.ofNullable(getForColumns()).orElseGet(ArrayList::new); - Collections.addAll(collection, forColumns); - return this.withForColumns(collection); + return this.addForColumns(Arrays.asList(forColumns)); } public Pivot addForColumns(Collection forColumns) { - List collection = Optional.ofNullable(getForColumns()).orElseGet(ArrayList::new); + ExpressionList collection = + Optional.ofNullable(getForColumns()).orElseGet(ExpressionList::new); collection.addAll(forColumns); return this.withForColumns(collection); } - public Pivot addSingleInItems(SelectExpressionItem... singleInItems) { - List collection = Optional.ofNullable(getSingleInItems()).orElseGet(ArrayList::new); + public Pivot addSingleInItems(SelectItem... singleInItems) { + List> collection = + Optional.ofNullable(getSingleInItems()).orElseGet(ArrayList::new); Collections.addAll(collection, singleInItems); return this.withSingleInItems(collection); } - public Pivot addSingleInItems(Collection singleInItems) { - List collection = Optional.ofNullable(getSingleInItems()).orElseGet(ArrayList::new); + public Pivot addSingleInItems(Collection> singleInItems) { + List> collection = + Optional.ofNullable(getSingleInItems()).orElseGet(ArrayList::new); collection.addAll(singleInItems); return this.withSingleInItems(collection); } - public Pivot addMultiInItems(ExpressionListItem... multiInItems) { - List collection = Optional.ofNullable(getMultiInItems()).orElseGet(ArrayList::new); + public Pivot addMultiInItems(SelectItem... multiInItems) { + List> collection = + Optional.ofNullable(getMultiInItems()).orElseGet(ArrayList::new); Collections.addAll(collection, multiInItems); return this.withMultiInItems(collection); } - public Pivot addMultiInItems(Collection multiInItems) { - List collection = Optional.ofNullable(getMultiInItems()).orElseGet(ArrayList::new); + public Pivot addMultiInItems(Collection> multiInItems) { + List> collection = + Optional.ofNullable(getMultiInItems()).orElseGet(ArrayList::new); collection.addAll(multiInItems); return this.withMultiInItems(collection); } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/PivotXml.java b/src/main/java/net/sf/jsqlparser/statement/select/PivotXml.java index e4c524550..0c6929c40 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/PivotXml.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/PivotXml.java @@ -9,12 +9,14 @@ */ package net.sf.jsqlparser.statement.select; -import java.util.Collection; -import java.util.List; - import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.expression.Function; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.schema.Column; +import java.util.Collection; +import java.util.List; + public class PivotXml extends Pivot { private Select inSelect; @@ -74,32 +76,32 @@ public PivotXml withAlias(Alias alias) { } @Override - public PivotXml withFunctionItems(List functionItems) { + public PivotXml withFunctionItems(List> functionItems) { return (PivotXml) super.withFunctionItems(functionItems); } @Override - public PivotXml withForColumns(List forColumns) { + public PivotXml withForColumns(ExpressionList forColumns) { return (PivotXml) super.withForColumns(forColumns); } @Override - public PivotXml withSingleInItems(List singleInItems) { + public PivotXml withSingleInItems(List> singleInItems) { return (PivotXml) super.withSingleInItems(singleInItems); } @Override - public PivotXml withMultiInItems(List multiInItems) { + public PivotXml withMultiInItems(List> multiInItems) { return (PivotXml) super.withMultiInItems(multiInItems); } @Override - public PivotXml addFunctionItems(Collection functionItems) { + public PivotXml addFunctionItems(Collection> functionItems) { return (PivotXml) super.addFunctionItems(functionItems); } @Override - public PivotXml addFunctionItems(FunctionItem... functionItems) { + public PivotXml addFunctionItems(SelectItem... functionItems) { return (PivotXml) super.addFunctionItems(functionItems); } @@ -114,22 +116,22 @@ public PivotXml addForColumns(Column... forColumns) { } @Override - public PivotXml addSingleInItems(Collection singleInItems) { + public PivotXml addSingleInItems(Collection> singleInItems) { return (PivotXml) super.addSingleInItems(singleInItems); } @Override - public PivotXml addSingleInItems(SelectExpressionItem... singleInItems) { + public PivotXml addSingleInItems(SelectItem... singleInItems) { return (PivotXml) super.addSingleInItems(singleInItems); } @Override - public PivotXml addMultiInItems(ExpressionListItem... multiInItems) { + public PivotXml addMultiInItems(SelectItem... multiInItems) { return (PivotXml) super.addMultiInItems(multiInItems); } @Override - public PivotXml addMultiInItems(Collection multiInItems) { + public PivotXml addMultiInItems(Collection> multiInItems) { return (PivotXml) super.addMultiInItems(multiInItems); } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java b/src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java index fe11e5f0c..87b755754 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java @@ -9,6 +9,7 @@ */ package net.sf.jsqlparser.statement.select; +import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.OracleHierarchicalExpression; import net.sf.jsqlparser.expression.OracleHint; @@ -16,6 +17,7 @@ import net.sf.jsqlparser.schema.Table; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; @@ -28,9 +30,10 @@ public class PlainSelect extends Select { private Distinct distinct = null; - private List selectItems; + private List> selectItems; private List intoTables; private FromItem fromItem; + private List lateralViews; private List joins; private Expression where; private GroupByElement groupBy; @@ -55,6 +58,13 @@ public class PlainSelect extends Select { private List windowDefinitions; + /** + * @see Clickhouse + * FINAL + */ + private boolean isUsingFinal = false; + @Deprecated public boolean isUseBrackets() { return false; @@ -68,7 +78,7 @@ public List
getIntoTables() { return intoTables; } - public List getSelectItems() { + public List> getSelectItems() { return selectItems; } @@ -89,25 +99,75 @@ public void setIntoTables(List
intoTables) { this.intoTables = intoTables; } - public PlainSelect withSelectItems(List list) { + public PlainSelect withSelectItems(List> list) { this.setSelectItems(list); return this; } - public void setSelectItems(List list) { + public void setSelectItems(List> list) { selectItems = list; } - public PlainSelect addSelectItems(SelectItem... items) { - List list = Optional.ofNullable(getSelectItems()).orElseGet(ArrayList::new); - Collections.addAll(list, items); - return withSelectItems(list); + public PlainSelect addSelectItems(SelectItem... items) { + selectItems = Optional.ofNullable(selectItems).orElseGet(ArrayList::new); + selectItems.addAll(Arrays.asList(items)); + return this; + } + + public PlainSelect addSelectItems(Expression... expressions) { + selectItems = Optional.ofNullable(selectItems).orElseGet(ArrayList::new); + for (Expression expression : expressions) { + selectItems.add(SelectItem.from(expression)); + } + return this; + } + + public PlainSelect addSelectItem(Expression expression, Alias alias) { + selectItems = Optional.ofNullable(selectItems).orElseGet(ArrayList::new); + selectItems.add(new SelectItem(expression, alias)); + return this; + } + + public PlainSelect addSelectItem(Expression expression) { + return addSelectItem(expression, null); } public void setWhere(Expression where) { this.where = where; } + public List getLateralViews() { + return lateralViews; + } + + public void setLateralViews(Collection lateralViews) { + if (this.lateralViews == null && lateralViews != null) { + this.lateralViews = new ArrayList<>(); + } else { + this.lateralViews.clear(); + } + + if (lateralViews != null) { + this.lateralViews.addAll(lateralViews); + } else { + this.lateralViews = null; + } + } + + public PlainSelect addLateralView(LateralView lateralView) { + if (this.lateralViews == null) { + this.lateralViews = new ArrayList<>(); + } + + this.lateralViews.add(lateralView); + return this; + } + + public PlainSelect withLateralViews(Collection lateralViews) { + this.setLateralViews(lateralViews); + return this; + } + /** * The list of {@link Join}s * @@ -132,6 +192,19 @@ public void setJoins(List list) { joins = list; } + public boolean isUsingFinal() { + return isUsingFinal; + } + + public void setUsingFinal(boolean usingFinal) { + this.isUsingFinal = usingFinal; + } + + public PlainSelect withUsingFinal(boolean usingFinal) { + this.setUsingFinal(usingFinal); + return this; + } + @Override public void accept(SelectVisitor selectVisitor) { selectVisitor.visit(this); @@ -208,8 +281,8 @@ public void setGroupByElement(GroupByElement groupBy) { } public PlainSelect addGroupByColumnReference(Expression expr) { - groupBy = Optional.ofNullable(groupBy).orElseGet(GroupByElement::new); - groupBy.addGroupByExpression(expr); + this.groupBy = Optional.ofNullable(groupBy).orElseGet(GroupByElement::new); + this.groupBy.addGroupByExpression(expr); return this; } @@ -350,6 +423,11 @@ public StringBuilder appendSelectBodyTo(StringBuilder builder) { if (fromItem != null) { builder.append(" FROM ").append(fromItem); + if (lateralViews != null) { + for (LateralView lateralView : lateralViews) { + builder.append(" ").append(lateralView); + } + } if (joins != null) { for (Join join : joins) { if (join.isSimple()) { @@ -360,6 +438,10 @@ public StringBuilder appendSelectBodyTo(StringBuilder builder) { } } + if (isUsingFinal) { + builder.append(" FINAL"); + } + if (ksqlWindow != null) { builder.append(" WINDOW ").append(ksqlWindow); } @@ -557,8 +639,8 @@ public PlainSelect withWait(Wait wait) { return this; } - public PlainSelect addSelectItems(Collection selectItems) { - List collection = + public PlainSelect addSelectItems(Collection> selectItems) { + List> collection = Optional.ofNullable(getSelectItems()).orElseGet(ArrayList::new); collection.addAll(selectItems); return this.withSelectItems(collection); diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Select.java b/src/main/java/net/sf/jsqlparser/statement/select/Select.java index 8cdd567f0..757adb5b4 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Select.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Select.java @@ -24,6 +24,7 @@ public abstract class Select extends ASTNodeAccessImpl implements Statement, Expression { List withItemsList; + Limit limitBy; Limit limit; Offset offset; Fetch fetch; @@ -190,6 +191,19 @@ public Select withLimit(Limit limit) { return this; } + public Limit getLimitBy() { + return limitBy; + } + + public void setLimitBy(Limit limitBy) { + this.limitBy = limitBy; + } + + public E withLimitBy(Class type, Limit limitBy) { + this.setLimitBy(limitBy); + return type.cast(this); + } + public Offset getOffset() { return offset; } @@ -231,6 +245,7 @@ public Select withIsolation(WithIsolation isolation) { public abstract StringBuilder appendSelectBodyTo(StringBuilder builder); + @SuppressWarnings({"PMD.CyclomaticComplexity"}) public StringBuilder appendTo(StringBuilder builder) { if (withItemsList != null && !withItemsList.isEmpty()) { builder.append("WITH "); @@ -248,6 +263,9 @@ public StringBuilder appendTo(StringBuilder builder) { builder.append(orderByToString(oracleSiblings, orderByElements)); + if (limitBy != null) { + builder.append(limitBy); + } if (limit != null) { builder.append(limit); } @@ -285,8 +303,19 @@ public Select getSelectBody() { return this; } - @Deprecated - public E getSelectBody(Class type) { + public Values getValues() { + return (Values) this; + } + + public PlainSelect getPlainSelect() { + return (PlainSelect) this; + } + + public SetOperationList getSetOperationList() { + return (SetOperationList) this; + } + + public E as(Class type) { return type.cast(this); } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SelectExpressionItem.java b/src/main/java/net/sf/jsqlparser/statement/select/SelectExpressionItem.java deleted file mode 100644 index a0b8fde6d..000000000 --- a/src/main/java/net/sf/jsqlparser/statement/select/SelectExpressionItem.java +++ /dev/null @@ -1,67 +0,0 @@ -/*- - * #%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.select; - -import net.sf.jsqlparser.expression.Alias; -import net.sf.jsqlparser.expression.Expression; -import net.sf.jsqlparser.parser.ASTNodeAccessImpl; - -public class SelectExpressionItem extends ASTNodeAccessImpl implements SelectItem { - - private Expression expression; - private Alias alias; - - public SelectExpressionItem() { - } - - public SelectExpressionItem(Expression expression) { - this.expression = expression; - } - - public Alias getAlias() { - return alias; - } - - public Expression getExpression() { - return expression; - } - - public void setAlias(Alias alias) { - this.alias = alias; - } - - public void setExpression(Expression expression) { - this.expression = expression; - } - - @Override - public void accept(SelectItemVisitor selectItemVisitor) { - selectItemVisitor.visit(this); - } - - @Override - public String toString() { - return expression + ((alias != null) ? alias.toString() : ""); - } - - public SelectExpressionItem withExpression(Expression expression) { - this.setExpression(expression); - return this; - } - - public SelectExpressionItem withAlias(Alias alias) { - this.setAlias(alias); - return this; - } - - public E getExpression(Class type) { - return type.cast(getExpression()); - } -} diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SelectItem.java b/src/main/java/net/sf/jsqlparser/statement/select/SelectItem.java index 27b29097c..dfad00219 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SelectItem.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SelectItem.java @@ -9,9 +9,72 @@ */ package net.sf.jsqlparser.statement.select; -import net.sf.jsqlparser.parser.ASTNodeAccess; +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; -public interface SelectItem extends ASTNodeAccess { +public class SelectItem extends ASTNodeAccessImpl { - void accept(SelectItemVisitor selectItemVisitor); + private T expression; + private Alias alias; + + public SelectItem(T expression, Alias alias) { + this.expression = expression; + this.alias = alias; + } + + public SelectItem() { + this(null, null); + } + + public SelectItem(T expression) { + this(expression, null); + } + + public static SelectItem from(Expression expression, Alias alias) { + return new SelectItem(expression, alias); + } + + public static SelectItem from(Expression expression) { + return from(expression, null); + } + + public Alias getAlias() { + return alias; + } + + public void setAlias(Alias alias) { + this.alias = alias; + } + + public T getExpression() { + return expression; + } + + public void setExpression(T expression) { + this.expression = expression; + } + + public void accept(SelectItemVisitor selectItemVisitor) { + selectItemVisitor.visit(this); + } + + @Override + public String toString() { + return expression + ((alias != null) ? alias.toString() : ""); + } + + public SelectItem withExpression(T expression) { + this.setExpression(expression); + return this; + } + + public SelectItem withAlias(Alias alias) { + this.setAlias(alias); + return this; + } + + public E getExpression(Class type) { + return type.cast(getExpression()); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitor.java b/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitor.java index 4ea463b36..2f12539e2 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitor.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitor.java @@ -10,10 +10,5 @@ package net.sf.jsqlparser.statement.select; public interface SelectItemVisitor { - - void visit(AllColumns allColumns); - - void visit(AllTableColumns allTableColumns); - - void visit(SelectExpressionItem selectExpressionItem); + void visit(SelectItem selectItem); } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitorAdapter.java index 4173950ae..eeb2d1b61 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitorAdapter.java @@ -11,19 +11,8 @@ @SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) public class SelectItemVisitorAdapter implements SelectItemVisitor { - - @Override - public void visit(AllColumns columns) { - - } - - @Override - public void visit(AllTableColumns columns) { - - } - @Override - public void visit(SelectExpressionItem item) { + public void visit(SelectItem item) { } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SetOperationList.java b/src/main/java/net/sf/jsqlparser/statement/select/SetOperationList.java index 1dbc5d96f..79a03b802 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SetOperationList.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SetOperationList.java @@ -109,6 +109,10 @@ public SetOperationList addOperations(Collection operati } public enum SetOperationType { - INTERSECT, EXCEPT, MINUS, UNION + INTERSECT, EXCEPT, MINUS, UNION; + + public static SetOperationType from(String type) { + return Enum.valueOf(SetOperationType.class, type.toUpperCase()); + } } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/TableFunction.java b/src/main/java/net/sf/jsqlparser/statement/select/TableFunction.java index 5d8638a0d..8dcfacecb 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/TableFunction.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/TableFunction.java @@ -13,7 +13,7 @@ import net.sf.jsqlparser.expression.Function; @SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) -public class TableFunction extends FunctionItem implements FromItem { +public class TableFunction extends SelectItem implements FromItem { @Override public void accept(FromItemVisitor fromItemVisitor) { @@ -46,8 +46,8 @@ public TableFunction withAlias(Alias alias) { } @Override - public TableFunction withFunction(Function function) { - return (TableFunction) super.withFunction(function); + public TableFunction withExpression(Function function) { + return (TableFunction) super.withExpression(function); } @Override diff --git a/src/main/java/net/sf/jsqlparser/statement/select/UnPivot.java b/src/main/java/net/sf/jsqlparser/statement/select/UnPivot.java index 3ae7acf50..8d39f831e 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/UnPivot.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/UnPivot.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.statement.select; import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.schema.Column; import java.io.Serializable; @@ -19,9 +20,9 @@ public class UnPivot implements Serializable { private boolean includeNulls = false; private boolean includeNullsSpecified = false; - private List unpivotClause; - private List unpivotForClause; - private List unpivotInClause; + private ExpressionList unpivotClause; + private ExpressionList unpivotForClause; + private List> unpivotInClause; private Alias alias; public void accept(PivotVisitor pivotVisitor) { @@ -45,7 +46,7 @@ public List getUnPivotClause() { return unpivotClause; } - public void setUnPivotClause(List unpivotClause) { + public void setUnPivotClause(ExpressionList unpivotClause) { this.unpivotClause = unpivotClause; } @@ -53,15 +54,15 @@ public List getUnPivotForClause() { return unpivotForClause; } - public void setUnPivotForClause(List forColumns) { + public void setUnPivotForClause(ExpressionList forColumns) { this.unpivotForClause = forColumns; } - public List getUnPivotInClause() { + public List> getUnPivotInClause() { return unpivotInClause; } - public void setUnPivotInClause(List unpivotInClause) { + public void setUnPivotInClause(List> unpivotInClause) { this.unpivotInClause = unpivotInClause; } @@ -70,10 +71,12 @@ public String toString() { return "UNPIVOT" + (includeNullsSpecified && includeNulls ? " INCLUDE NULLS" : "") + (includeNullsSpecified && !includeNulls ? " EXCLUDE NULLS" : "") - + " (" + PlainSelect.getStringList(unpivotClause, true, unpivotClause != null && unpivotClause.size() > 1) - + " FOR " + PlainSelect.getStringList(unpivotForClause, true, unpivotForClause != null && unpivotForClause.size() > 1) + + " (" + + unpivotClause.toString() + + " FOR " + + unpivotForClause.toString() + " IN " + PlainSelect.getStringList(unpivotInClause, true, true) + ")" - + (alias!=null ? alias.toString() : ""); + + (alias != null ? alias.toString() : ""); } public UnPivot withIncludeNulls(boolean includeNulls) { diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Values.java b/src/main/java/net/sf/jsqlparser/statement/select/Values.java index 9360abe2a..67853a54d 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Values.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Values.java @@ -11,28 +11,29 @@ import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.expression.operators.relational.ItemsList; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; -import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; public class Values extends Select { - private ItemsList expressions; + private ExpressionList expressions; public Values() { // empty constructor } - public Values(ItemsList expressions) { + public Values(ExpressionList expressions) { this.expressions = expressions; } - public ItemsList getExpressions() { + public ExpressionList getExpressions() { return expressions; } - public void setExpressions(ItemsList expressions) { + + public void setExpressions(ExpressionList expressions) { this.expressions = expressions; } @@ -48,26 +49,20 @@ public void accept(SelectVisitor selectVisitor) { selectVisitor.visit(this); } - public Values withExpressions(ItemsList expressions) { + public Values withExpressions(ExpressionList expressions) { this.setExpressions(expressions); return this; } - public Values addExpressions(Expression... addExpressions) { - if (expressions != null && expressions instanceof ExpressionList) { - ((ExpressionList) expressions).addExpressions(addExpressions); - return this; - } else { - return this.withExpressions(new ExpressionList(addExpressions)); - } + public Values addExpressions(Expression... expressions) { + return this.addExpressions(Arrays.asList(expressions)); } - public Values addExpressions(Collection addExpressions) { - if (expressions != null && expressions instanceof ExpressionList) { - ((ExpressionList) expressions).addExpressions(addExpressions); - return this; - } else { - return this.withExpressions(new ExpressionList(new ArrayList<>(addExpressions))); + public Values addExpressions(Collection expressions) { + if (this.expressions == null) { + this.expressions = new ParenthesedExpressionList(); } + this.expressions.addAll(expressions); + return this; } } 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 d89c184f7..de673f491 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java @@ -17,7 +17,7 @@ public class WithItem extends ParenthesedSelect { - private List withItemList; + private List> withItemList; private boolean recursive = false; @@ -35,11 +35,11 @@ public void setRecursive(boolean recursive) { * * @return a list of {@link SelectItem}s */ - public List getWithItemList() { + public List> getWithItemList() { return withItemList; } - public void setWithItemList(List withItemList) { + public void setWithItemList(List> withItemList) { this.withItemList = withItemList; } @@ -64,7 +64,7 @@ public void accept(SelectVisitor visitor) { } - public WithItem withWithItemList(List withItemList) { + public WithItem withWithItemList(List> withItemList) { this.setWithItemList(withItemList); return this; } @@ -74,15 +74,15 @@ public WithItem withRecursive(boolean recursive) { return this; } - public WithItem addWithItemList(SelectItem... withItemList) { - List collection = + public WithItem addWithItemList(SelectItem... withItemList) { + List> collection = Optional.ofNullable(getWithItemList()).orElseGet(ArrayList::new); Collections.addAll(collection, withItemList); return this.withWithItemList(collection); } - public WithItem addWithItemList(Collection withItemList) { - List collection = + public WithItem addWithItemList(Collection> withItemList) { + List> collection = Optional.ofNullable(getWithItemList()).orElseGet(ArrayList::new); collection.addAll(withItemList); return this.withWithItemList(collection); diff --git a/src/main/java/net/sf/jsqlparser/statement/show/ShowTablesStatement.java b/src/main/java/net/sf/jsqlparser/statement/show/ShowTablesStatement.java index 9024c564e..16106b823 100644 --- a/src/main/java/net/sf/jsqlparser/statement/show/ShowTablesStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/show/ShowTablesStatement.java @@ -17,6 +17,7 @@ /** * A {@code SHOW TABLES} statement + * * @see MySQL show tables */ public class ShowTablesStatement implements Statement { @@ -102,10 +103,18 @@ public void accept(StatementVisitor statementVisitor) { } public enum SelectionMode { - FROM, IN + FROM, IN; + + public static SelectionMode from(String mode) { + return Enum.valueOf(SelectionMode.class, mode.toUpperCase()); + } } public enum Modifiers { - EXTENDED, FULL + EXTENDED, FULL; + + public static Modifiers from(String modifier) { + return Enum.valueOf(Modifiers.class, modifier.toUpperCase()); + } } } 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 4b638060b..0ba506ea6 100644 --- a/src/main/java/net/sf/jsqlparser/statement/update/Update.java +++ b/src/main/java/net/sf/jsqlparser/statement/update/Update.java @@ -14,6 +14,7 @@ import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.OutputClause; +import net.sf.jsqlparser.statement.ReturningClause; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; import net.sf.jsqlparser.statement.select.FromItem; @@ -22,10 +23,10 @@ import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.WithItem; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; @@ -38,14 +39,14 @@ public class Update implements Statement { private List withItemsList; private Table table; private Expression where; - private final ArrayList updateSets = new ArrayList<>(); + private List updateSets; private FromItem fromItem; private List joins; private List startJoins; private OracleHint oracleHint = null; private List orderByElements; private Limit limit; - private List returningExpressionList = null; + private ReturningClause returningClause; private UpdateModifierPriority modifierPriority; private boolean modifierIgnore; @@ -59,10 +60,19 @@ public void setOutputClause(OutputClause outputClause) { this.outputClause = outputClause; } - public ArrayList getUpdateSets() { + public List getUpdateSets() { return updateSets; } + public void setUpdateSets(List updateSets) { + this.updateSets = updateSets; + } + + public Update withUpdateSets(List updateSets) { + this.setUpdateSets(updateSets); + return this; + } + @Override public void accept(StatementVisitor statementVisitor) { statementVisitor.visit(this); @@ -119,12 +129,16 @@ public void setOracleHint(OracleHint oracleHint) { this.oracleHint = oracleHint; } - public void addUpdateSet(Column column, Expression expression) { - updateSets.add(new UpdateSet(column, expression)); + public Update addUpdateSet(Column column, Expression expression) { + return this.addUpdateSet(new UpdateSet(column, expression)); } - public void addUpdateSet(UpdateSet updateSet) { - updateSets.add(updateSet); + public Update addUpdateSet(UpdateSet updateSet) { + if (this.updateSets == null) { + this.updateSets = new ArrayList<>(); + } + this.updateSets.add(updateSet); + return this; } @Deprecated @@ -134,7 +148,7 @@ public List getColumns() { @Deprecated public List getExpressions() { - return updateSets.get(0).expressions; + return updateSets.get(0).values; } @Deprecated @@ -148,8 +162,8 @@ public void setColumns(List list) { @Deprecated public void setExpressions(List list) { - updateSets.get(0).expressions.clear(); - updateSets.get(0).expressions.addAll(list); + updateSets.get(0).values.clear(); + updateSets.get(0).values.addAll(list); } public FromItem getFromItem() { @@ -179,8 +193,8 @@ public void setStartJoins(List startJoins) { @Deprecated public Select getSelect() { Select select = null; - if (updateSets.get(0).expressions.get(0) instanceof Select) { - select = (Select) updateSets.get(0).expressions.get(0); + if (updateSets.get(0).values.get(0) instanceof Select) { + select = (Select) updateSets.get(0).values.get(0); } return select; @@ -189,23 +203,21 @@ public Select getSelect() { @Deprecated public void setSelect(Select select) { if (select != null) { - if (updateSets.get(0).expressions.isEmpty()) { - updateSets.get(0).expressions.add(select); + if (updateSets.get(0).values.isEmpty()) { + updateSets.get(0).values.add(select); } else { - updateSets.get(0).expressions.set(0, select); + updateSets.get(0).values.set(0, select); } } } @Deprecated public boolean isUseColumnsBrackets() { - return updateSets.get(0).usingBracketsForColumns; + return false; } @Deprecated - public void setUseColumnsBrackets(boolean useColumnsBrackets) { - updateSets.get(0).usingBracketsForColumns = useColumnsBrackets; - } + public void setUseColumnsBrackets(boolean useColumnsBrackets) {} @Deprecated public boolean isUseSelect() { @@ -233,12 +245,13 @@ public Limit getLimit() { return limit; } - public List getReturningExpressionList() { - return returningExpressionList; + public ReturningClause getReturningClause() { + return returningClause; } - public void setReturningExpressionList(List returningExpressionList) { - this.returningExpressionList = returningExpressionList; + public Update setReturningClause(ReturningClause returningClause) { + this.returningClause = returningClause; + return this; } public UpdateModifierPriority getModifierPriority() { @@ -292,6 +305,7 @@ public String toString() { } } + b.append(" SET "); UpdateSet.appendUpdateSetsTo(b, updateSets); if (outputClause != null) { @@ -322,9 +336,8 @@ public String toString() { b.append(limit); } - if (getReturningExpressionList() != null) { - b.append(" RETURNING ") - .append(PlainSelect.getStringList(getReturningExpressionList(), true, false)); + if (returningClause != null) { + returningClause.appendTo(b); } return b.toString(); @@ -375,11 +388,6 @@ public Update withLimit(Limit limit) { return this; } - public Update withReturningExpressionList(List returningExpressionList) { - this.setReturningExpressionList(returningExpressionList); - return this; - } - public Update withWhere(Expression where) { this.setWhere(where); return this; @@ -406,31 +414,25 @@ public Update withModifierIgnore(boolean modifierIgnore) { } public Update addColumns(Column... columns) { - List collection = - new ArrayList<>(Optional.ofNullable(getColumns()).orElseGet(ArrayList::new)); - Collections.addAll(collection, columns); - return this.withColumns(collection); + return addColumns(Arrays.asList(columns)); } public Update addColumns(Collection columns) { - List collection = - new ArrayList<>(Optional.ofNullable(getColumns()).orElseGet(ArrayList::new)); - collection.addAll(columns); - return this.withColumns(collection); + for (Column column : columns) { + updateSets.get(updateSets.size() - 1).add(column); + } + return this; } public Update addExpressions(Expression... expressions) { - List collection = - new ArrayList<>(Optional.ofNullable(getExpressions()).orElseGet(ArrayList::new)); - Collections.addAll(collection, expressions); - return this.withExpressions(collection); + return addExpressions(Arrays.asList(expressions)); } public Update addExpressions(Collection expressions) { - List collection = - new ArrayList<>(Optional.ofNullable(getExpressions()).orElseGet(ArrayList::new)); - collection.addAll(expressions); - return this.withExpressions(collection); + for (Expression expression : expressions) { + updateSets.get(updateSets.size() - 1).add(expression); + } + return this; } public Update addJoins(Join... joins) { @@ -471,21 +473,6 @@ public Update addOrderByElements(Collection orderByEle return this.withOrderByElements(collection); } - public Update addReturningExpressionList(SelectItem... returningExpressionList) { - List collection = - Optional.ofNullable(getReturningExpressionList()).orElseGet(ArrayList::new); - Collections.addAll(collection, returningExpressionList); - return this.withReturningExpressionList(collection); - } - - public Update addReturningExpressionList( - Collection returningExpressionList) { - List collection = - Optional.ofNullable(getReturningExpressionList()).orElseGet(ArrayList::new); - collection.addAll(returningExpressionList); - return this.withReturningExpressionList(collection); - } - public E getWhere(Class type) { return type.cast(getWhere()); } diff --git a/src/main/java/net/sf/jsqlparser/statement/update/UpdateModifierPriority.java b/src/main/java/net/sf/jsqlparser/statement/update/UpdateModifierPriority.java index 7e6f84654..39856bbca 100644 --- a/src/main/java/net/sf/jsqlparser/statement/update/UpdateModifierPriority.java +++ b/src/main/java/net/sf/jsqlparser/statement/update/UpdateModifierPriority.java @@ -10,5 +10,9 @@ package net.sf.jsqlparser.statement.update; public enum UpdateModifierPriority { - LOW_PRIORITY + LOW_PRIORITY; + + public static UpdateModifierPriority from(String priority) { + return Enum.valueOf(UpdateModifierPriority.class, priority.toUpperCase()); + } } 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 3cb26eaea..564a1559d 100644 --- a/src/main/java/net/sf/jsqlparser/statement/update/UpdateSet.java +++ b/src/main/java/net/sf/jsqlparser/statement/update/UpdateSet.java @@ -11,18 +11,17 @@ import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.statement.select.Select; import java.io.Serializable; -import java.util.ArrayList; import java.util.Collection; import java.util.Objects; public class UpdateSet implements Serializable { - protected boolean usingBracketsForColumns = false; - protected boolean usingBracketsForValues = false; - protected ArrayList columns = new ArrayList<>(); - protected ArrayList expressions = new ArrayList<>(); + protected ExpressionList columns = new ExpressionList<>(); + protected ExpressionList values = new ExpressionList(); public UpdateSet() { @@ -32,63 +31,64 @@ public UpdateSet(Column column) { this.columns.add(column); } - public UpdateSet(Column column, Expression expression) { + public UpdateSet(Column column, Expression value) { this.columns.add(column); - this.expressions.add(expression); + this.values.add(value); } - public boolean isUsingBracketsForValues() { - return usingBracketsForValues; - } - - public void setUsingBracketsForValues(boolean usingBracketsForValues) { - this.usingBracketsForValues = usingBracketsForValues; - } - - public boolean isUsingBracketsForColumns() { - return usingBracketsForColumns; - } - - public void setUsingBracketsForColumns(boolean usingBracketsForColumns) { - this.usingBracketsForColumns = usingBracketsForColumns; - } - - public ArrayList getColumns() { + public ExpressionList getColumns() { return columns; } - public void setColumns(ArrayList columns) { + public void setColumns(ExpressionList columns) { this.columns = Objects.requireNonNull(columns); } - public ArrayList getExpressions() { - return expressions; + public ExpressionList getValues() { + return values; } - public void setExpressions(ArrayList expressions) { - this.expressions = Objects.requireNonNull(expressions); + public void setValues(ExpressionList values) { + this.values = Objects.requireNonNull(values); } - public void add(Column column, Expression expression) { - columns.add(column); - expressions.add(expression); + public void add(Column column, Expression value) { + this.add(column); + this.add(value); } + /** + * Add another column to the existing column list. Transform this list into a + * ParenthesedExpression list when needed. + * + * @param column + */ public void add(Column column) { + if (columns.size() < 2 && !(columns instanceof ParenthesedExpressionList)) { + columns = new ParenthesedExpressionList<>(columns); + } columns.add(column); } + /** + * Add another expression to the existing value list. Transform this list into a + * ParenthesedExpression list when needed. + * + * @param expression + */ public void add(Expression expression) { - expressions.add(expression); + if (values.size() < 2 && !(values instanceof ParenthesedExpressionList)) { + values = new ParenthesedExpressionList<>(values); + } + values.add(expression); } public void add(ExpressionList expressionList) { - expressions.addAll(expressionList.getExpressions()); + values.addAll(expressionList.getExpressions()); } - public final static StringBuilder appendUpdateSetsTo(StringBuilder builder, Collection updateSets) { - builder.append(" SET "); - + public final static StringBuilder appendUpdateSetsTo(StringBuilder builder, + Collection updateSets) { int j = 0; for (UpdateSet updateSet : updateSets) { updateSet.appendTo(builder, j); @@ -102,38 +102,11 @@ StringBuilder appendTo(StringBuilder builder, int j) { if (j > 0) { builder.append(", "); } - - if (usingBracketsForColumns) { - builder.append("("); - } - - for (int i = 0; i < columns.size(); i++) { - if (i > 0) { - builder.append(", "); - } - builder.append(columns.get(i)); - } - - if (usingBracketsForColumns) { - builder.append(")"); - } - + builder.append( + Select.getStringList(columns, true, columns instanceof ParenthesedExpressionList)); builder.append(" = "); - - if (usingBracketsForValues) { - builder.append("("); - } - - for (int i = 0; i < expressions.size(); i++) { - if (i > 0) { - builder.append(", "); - } - builder.append(expressions.get(i)); - } - if (usingBracketsForValues) { - builder.append(")"); - } - + builder.append( + Select.getStringList(values, true, values instanceof ParenthesedExpressionList)); return builder; } diff --git a/src/main/java/net/sf/jsqlparser/statement/upsert/Upsert.java b/src/main/java/net/sf/jsqlparser/statement/upsert/Upsert.java index ed602836e..4e63782d2 100644 --- a/src/main/java/net/sf/jsqlparser/statement/upsert/Upsert.java +++ b/src/main/java/net/sf/jsqlparser/statement/upsert/Upsert.java @@ -9,41 +9,54 @@ */ package net.sf.jsqlparser.statement.upsert; -import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.expression.operators.relational.ItemsList; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.statement.select.SetOperationList; +import net.sf.jsqlparser.statement.select.Values; +import net.sf.jsqlparser.statement.update.UpdateSet; -import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Optional; public class Upsert implements Statement { private Table table; - private List columns; - private ItemsList itemsList; - private boolean useValues = true; + private ExpressionList columns; + private ExpressionList expressions; private Select select; - private boolean useSelectBrackets = true; - private boolean useDuplicate = false; - private List duplicateUpdateColumns; - private List duplicateUpdateExpressionList; - + private List updateSets; + private List duplicateUpdateSets; private UpsertType upsertType = UpsertType.UPSERT; - private boolean isUsingInto; + public List getUpdateSets() { + return updateSets; + } + + public Upsert setUpdateSets(List updateSets) { + this.updateSets = updateSets; + return this; + } + + public List getDuplicateUpdateSets() { + return duplicateUpdateSets; + } + + public Upsert setDuplicateUpdateSets(List duplicateUpdateSets) { + this.duplicateUpdateSets = duplicateUpdateSets; + return this; + } + @Override public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + statementVisitor.visit(this); } public UpsertType getUpsertType() { @@ -51,7 +64,7 @@ public UpsertType getUpsertType() { } public void setUpsertType(UpsertType upsertType) { - this.upsertType=upsertType; + this.upsertType = upsertType; } public Upsert withUpsertType(UpsertType upsertType) { @@ -71,88 +84,56 @@ public Upsert withUsingInto(boolean useInto) { setUsingInto(useInto); return this; } - - public void setTable(Table name) { - table = name; - } - + public Table getTable() { return table; } - - public void setColumns(List list) { - columns = list; + + public void setTable(Table name) { + table = name; } - - public List getColumns() { + + public ExpressionList getColumns() { return columns; } - - public void setItemsList(ItemsList list) { - itemsList = list; - } - - public ItemsList getItemsList() { - return itemsList; - } - public List getSetExpressions() { - List expressions = null; - if (itemsList instanceof ExpressionList) { - ExpressionList expressionList = (ExpressionList) itemsList; - expressions= expressionList.getExpressions(); - } - return expressions; + public void setColumns(ExpressionList list) { + columns = list; } - - public void setUseValues(boolean useValues) { - this.useValues = useValues; + + public ExpressionList getExpressions() { + return expressions; } - - public boolean isUseValues() { - return useValues; + + public void setExpressions(ExpressionList list) { + expressions = list; } - - public void setSelect(Select select) { - this.select = select; + + @Deprecated + public ExpressionList getSetExpressions() { + return expressions; } - + public Select getSelect() { return select; } - - public void setUseSelectBrackets(boolean useSelectBrackets) { - this.useSelectBrackets = useSelectBrackets; - } - - public boolean isUseSelectBrackets() { - return useSelectBrackets; - } - - public void setUseDuplicate(boolean useDuplicate) { - this.useDuplicate = useDuplicate; - } - - public boolean isUseDuplicate() { - return useDuplicate; - } - - public void setDuplicateUpdateColumns(List duplicateUpdateColumns) { - this.duplicateUpdateColumns = duplicateUpdateColumns; + + public void setSelect(Select select) { + this.select = select; } - - public List getDuplicateUpdateColumns() { - return duplicateUpdateColumns; + + public Values getValues() { + return select.getValues(); } - - public void setDuplicateUpdateExpressionList(List duplicateUpdateExpressionList) { - this.duplicateUpdateExpressionList = duplicateUpdateExpressionList; + + public PlainSelect getPlainSelect() { + return select.getPlainSelect(); } - - public List getDuplicateUpdateExpressionList() { - return duplicateUpdateExpressionList; + + public SetOperationList getSetOperationList() { + return select.getSetOperationList(); } - + @Override @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"}) public String toString() { @@ -182,62 +163,30 @@ public String toString() { default: sb.append("UPSERT "); } - + if (isUsingInto) { sb.append("INTO "); } sb.append(table).append(" "); - if (upsertType==UpsertType.REPLACE_SET) { + if (updateSets != null) { sb.append("SET "); - // each element from expressions match up with a column from columns. - List expressions = getSetExpressions(); - for (int i = 0, s = columns.size(); i < s; i++) { - sb.append(columns.get(i)).append("=").append(expressions.get(i)); - sb.append( i < s - 1 - ? ", " - : "" ); - } + UpdateSet.appendUpdateSetsTo(sb, updateSets); } else { if (columns != null) { - sb.append(PlainSelect.getStringList(columns, true, true)).append(" "); + sb.append(columns).append(" "); } - if (useValues) { - sb.append("VALUES "); - } - - if (itemsList != null) { - sb.append(itemsList); - } else { - if (useSelectBrackets) { - sb.append("("); - } - if (select != null) { - sb.append(select); - } - if (useSelectBrackets) { - sb.append(")"); - } + if (select != null) { + sb.append(select); } } - if (useDuplicate) { + if (duplicateUpdateSets != null) { sb.append(" ON DUPLICATE KEY UPDATE "); - for (int i = 0; i < getDuplicateUpdateColumns().size(); i++) { - if (i != 0) { - sb.append(", "); - } - sb.append(duplicateUpdateColumns.get(i)).append(" = "); - sb.append(duplicateUpdateExpressionList.get(i)); - } + UpdateSet.appendUpdateSetsTo(sb, duplicateUpdateSets); } - - return sb.toString(); - } - public Upsert withUseValues(boolean useValues) { - this.setUseValues(useValues); - return this; + return sb.toString(); } public Upsert withSelect(Select select) { @@ -245,78 +194,29 @@ public Upsert withSelect(Select select) { return this; } - public Upsert withUseSelectBrackets(boolean useSelectBrackets) { - this.setUseSelectBrackets(useSelectBrackets); - return this; - } - - public Upsert withUseDuplicate(boolean useDuplicate) { - this.setUseDuplicate(useDuplicate); - return this; - } - - public Upsert withDuplicateUpdateColumns(List duplicateUpdateColumns) { - this.setDuplicateUpdateColumns(duplicateUpdateColumns); - return this; - } - - public Upsert withDuplicateUpdateExpressionList(List duplicateUpdateExpressionList) { - this.setDuplicateUpdateExpressionList(duplicateUpdateExpressionList); - return this; - } - public Upsert withTable(Table table) { this.setTable(table); return this; } - public Upsert withColumns(List columns) { + public Upsert withColumns(ExpressionList columns) { this.setColumns(columns); return this; } - public Upsert withItemsList(ItemsList itemsList) { - this.setItemsList(itemsList); + public Upsert withExpressions(ExpressionList expressions) { + this.setExpressions(expressions); return this; } public Upsert addColumns(Column... columns) { - List collection = Optional.ofNullable(getColumns()).orElseGet(ArrayList::new); - Collections.addAll(collection, columns); - return this.withColumns(collection); + return this.addColumns(Arrays.asList(columns)); } public Upsert addColumns(Collection columns) { - List collection = Optional.ofNullable(getColumns()).orElseGet(ArrayList::new); + ExpressionList collection = + Optional.ofNullable(getColumns()).orElseGet(ExpressionList::new); collection.addAll(columns); return this.withColumns(collection); } - - public Upsert addDuplicateUpdateColumns(Column... duplicateUpdateColumns) { - List collection = Optional.ofNullable(getDuplicateUpdateColumns()).orElseGet(ArrayList::new); - Collections.addAll(collection, duplicateUpdateColumns); - return this.withDuplicateUpdateColumns(collection); - } - - public Upsert addDuplicateUpdateColumns(Collection duplicateUpdateColumns) { - List collection = Optional.ofNullable(getDuplicateUpdateColumns()).orElseGet(ArrayList::new); - collection.addAll(duplicateUpdateColumns); - return this.withDuplicateUpdateColumns(collection); - } - - public Upsert addDuplicateUpdateExpressionList(Expression... duplicateUpdateExpressionList) { - List collection = Optional.ofNullable(getDuplicateUpdateExpressionList()).orElseGet(ArrayList::new); - Collections.addAll(collection, duplicateUpdateExpressionList); - return this.withDuplicateUpdateExpressionList(collection); - } - - public Upsert addDuplicateUpdateExpressionList(Collection duplicateUpdateExpressionList) { - List collection = Optional.ofNullable(getDuplicateUpdateExpressionList()).orElseGet(ArrayList::new); - collection.addAll(duplicateUpdateExpressionList); - return this.withDuplicateUpdateExpressionList(collection); - } - - public E getItemsList(Class type) { - return type.cast(getItemsList()); - } } diff --git a/src/main/java/net/sf/jsqlparser/statement/upsert/UpsertType.java b/src/main/java/net/sf/jsqlparser/statement/upsert/UpsertType.java index 63f34785a..e60255170 100644 --- a/src/main/java/net/sf/jsqlparser/statement/upsert/UpsertType.java +++ b/src/main/java/net/sf/jsqlparser/statement/upsert/UpsertType.java @@ -10,12 +10,9 @@ package net.sf.jsqlparser.statement.upsert; public enum UpsertType { - UPSERT - , REPLACE - , REPLACE_SET - , INSERT_OR_ABORT - , INSERT_OR_FAIL - , INSERT_OR_IGNORE - , INSERT_OR_REPLACE - , INSERT_OR_ROLLBACK + UPSERT, REPLACE, REPLACE_SET, INSERT_OR_ABORT, INSERT_OR_FAIL, INSERT_OR_IGNORE, INSERT_OR_REPLACE, INSERT_OR_ROLLBACK; + + public static UpsertType from(String type) { + return Enum.valueOf(UpsertType.class, type.toUpperCase()); + } } diff --git a/src/main/java/net/sf/jsqlparser/util/AddAliasesVisitor.java b/src/main/java/net/sf/jsqlparser/util/AddAliasesVisitor.java index 23ddd869c..3303c091f 100644 --- a/src/main/java/net/sf/jsqlparser/util/AddAliasesVisitor.java +++ b/src/main/java/net/sf/jsqlparser/util/AddAliasesVisitor.java @@ -10,19 +10,16 @@ package net.sf.jsqlparser.util; import net.sf.jsqlparser.expression.Alias; -import net.sf.jsqlparser.statement.select.AllColumns; -import net.sf.jsqlparser.statement.select.AllTableColumns; import net.sf.jsqlparser.statement.select.LateralSubSelect; import net.sf.jsqlparser.statement.select.ParenthesedSelect; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectExpressionItem; import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.SelectItemVisitor; import net.sf.jsqlparser.statement.select.SelectVisitor; import net.sf.jsqlparser.statement.select.SetOperationList; -import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.statement.select.Values; +import net.sf.jsqlparser.statement.select.WithItem; import java.util.LinkedList; import java.util.List; @@ -69,19 +66,13 @@ public void visit(SetOperationList setOpList) { } @Override - public void visit(AllTableColumns allTableColumns) { - - } - - @Override - public void visit(SelectExpressionItem selectExpressionItem) { + public void visit(SelectItem selectExpressionItem) { if (firstRun) { if (selectExpressionItem.getAlias() != null) { aliases.add(selectExpressionItem.getAlias().getName().toUpperCase()); } } else { if (selectExpressionItem.getAlias() == null) { - while (true) { String alias = getNextAlias().toUpperCase(); if (!aliases.contains(alias)) { @@ -110,13 +101,6 @@ public void visit(WithItem withItem) { // Templates. } - @Override - public void visit(AllColumns allColumns) { - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); // To change body of generated - // methods, choose Tools | - // Templates. - } - @Override public void visit(Values aThis) { throw new UnsupportedOperationException("Not supported yet."); // To change body of diff --git a/src/main/java/net/sf/jsqlparser/util/ConnectExpressionsVisitor.java b/src/main/java/net/sf/jsqlparser/util/ConnectExpressionsVisitor.java index eac4eec22..479bc3c3e 100644 --- a/src/main/java/net/sf/jsqlparser/util/ConnectExpressionsVisitor.java +++ b/src/main/java/net/sf/jsqlparser/util/ConnectExpressionsVisitor.java @@ -11,19 +11,16 @@ import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.BinaryExpression; -import net.sf.jsqlparser.statement.select.AllColumns; -import net.sf.jsqlparser.statement.select.AllTableColumns; import net.sf.jsqlparser.statement.select.LateralSubSelect; import net.sf.jsqlparser.statement.select.ParenthesedSelect; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectExpressionItem; import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.SelectItemVisitor; import net.sf.jsqlparser.statement.select.SelectVisitor; import net.sf.jsqlparser.statement.select.SetOperationList; -import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.statement.select.Values; +import net.sf.jsqlparser.statement.select.WithItem; import java.util.LinkedList; import java.util.List; @@ -39,7 +36,7 @@ public abstract class ConnectExpressionsVisitor implements SelectVisitor, SelectItemVisitor { private String alias = "expr"; - private final List itemsExpr = new LinkedList(); + private final List itemsExpr = new LinkedList(); public ConnectExpressionsVisitor() {} @@ -76,14 +73,14 @@ public void visit(PlainSelect plainSelect) { } binExpr.setRightExpression(itemsExpr.get(itemsExpr.size() - 1).getExpression()); - SelectExpressionItem sei = new SelectExpressionItem(); + SelectItem sei = new SelectItem(); sei.setExpression(binExpr); plainSelect.getSelectItems().clear(); plainSelect.getSelectItems().add(sei); } - ((SelectExpressionItem) plainSelect.getSelectItems().get(0)).setAlias(new Alias(alias)); + plainSelect.getSelectItems().get(0).setAlias(new Alias(alias)); } @Override @@ -97,18 +94,8 @@ public void visit(SetOperationList setOpList) { public void visit(WithItem withItem) {} @Override - public void visit(AllTableColumns allTableColumns) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void visit(AllColumns allColumns) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void visit(SelectExpressionItem selectExpressionItem) { - itemsExpr.add(selectExpressionItem); + public void visit(SelectItem selectItem) { + itemsExpr.add(selectItem); } @Override diff --git a/src/main/java/net/sf/jsqlparser/util/SelectUtils.java b/src/main/java/net/sf/jsqlparser/util/SelectUtils.java index 0b42bab8c..88c641fdb 100644 --- a/src/main/java/net/sf/jsqlparser/util/SelectUtils.java +++ b/src/main/java/net/sf/jsqlparser/util/SelectUtils.java @@ -17,7 +17,6 @@ import net.sf.jsqlparser.statement.select.Join; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectExpressionItem; import net.sf.jsqlparser.statement.select.SelectItem; public final class SelectUtils { @@ -29,7 +28,7 @@ private SelectUtils() {} public static Select buildSelectFromTableAndExpressions(Table table, Expression... expr) { SelectItem[] list = new SelectItem[expr.length]; for (int i = 0; i < expr.length; i++) { - list[i] = new SelectExpressionItem(expr[i]); + list[i] = new SelectItem(expr[i]); } return buildSelectFromTableAndSelectItems(table, list); } @@ -38,7 +37,7 @@ public static Select buildSelectFromTableAndExpressions(Table table, String... e throws JSQLParserException { SelectItem[] list = new SelectItem[expr.length]; for (int i = 0; i < expr.length; i++) { - list[i] = new SelectExpressionItem(CCJSqlParserUtil.parseExpression(expr[i])); + list[i] = new SelectItem(CCJSqlParserUtil.parseExpression(expr[i])); } return buildSelectFromTableAndSelectItems(table, list); } @@ -56,7 +55,7 @@ public static Select buildSelectFromTableAndSelectItems(Table table, * @return */ public static Select buildSelectFromTable(Table table) { - return buildSelectFromTableAndSelectItems(table, new AllColumns()); + return buildSelectFromTableAndSelectItems(table, SelectItem.from(new AllColumns())); } /** @@ -67,7 +66,7 @@ public static Select buildSelectFromTable(Table table) { */ public static void addExpression(Select select, final Expression expr) { if (select instanceof PlainSelect) { - ((PlainSelect) select).getSelectItems().add(new SelectExpressionItem(expr)); + ((PlainSelect) select).addSelectItem(expr); } else { throw new UnsupportedOperationException(NOT_SUPPORTED_YET); } diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index 7f9476157..3c77176a0 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -46,18 +46,18 @@ import net.sf.jsqlparser.expression.OracleNamedFunctionParameter; import net.sf.jsqlparser.expression.OverlapsCondition; import net.sf.jsqlparser.expression.Parenthesis; +import net.sf.jsqlparser.expression.RangeExpression; import net.sf.jsqlparser.expression.RowConstructor; import net.sf.jsqlparser.expression.RowGetExpression; -import net.sf.jsqlparser.expression.SafeCastExpression; import net.sf.jsqlparser.expression.SignedExpression; import net.sf.jsqlparser.expression.StringValue; import net.sf.jsqlparser.expression.TimeKeyExpression; import net.sf.jsqlparser.expression.TimeValue; import net.sf.jsqlparser.expression.TimestampValue; import net.sf.jsqlparser.expression.TimezoneExpression; -import net.sf.jsqlparser.expression.TryCastExpression; +import net.sf.jsqlparser.expression.TranscodingFunction; +import net.sf.jsqlparser.expression.TrimFunction; import net.sf.jsqlparser.expression.UserVariable; -import net.sf.jsqlparser.expression.ValueListExpression; import net.sf.jsqlparser.expression.VariableAssignment; import net.sf.jsqlparser.expression.WhenClause; import net.sf.jsqlparser.expression.XMLSerializeExpr; @@ -88,14 +88,12 @@ import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression; import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression; import net.sf.jsqlparser.expression.operators.relational.IsNullExpression; -import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor; import net.sf.jsqlparser.expression.operators.relational.JsonOperator; import net.sf.jsqlparser.expression.operators.relational.LikeExpression; import net.sf.jsqlparser.expression.operators.relational.Matches; +import net.sf.jsqlparser.expression.operators.relational.MemberOfExpression; import net.sf.jsqlparser.expression.operators.relational.MinorThan; import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals; -import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; -import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList; import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo; import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator; import net.sf.jsqlparser.expression.operators.relational.RegExpMySQLOperator; @@ -142,7 +140,6 @@ import net.sf.jsqlparser.statement.grant.Grant; import net.sf.jsqlparser.statement.insert.Insert; import net.sf.jsqlparser.statement.merge.Merge; -import net.sf.jsqlparser.statement.replace.Replace; import net.sf.jsqlparser.statement.select.AllColumns; import net.sf.jsqlparser.statement.select.AllTableColumns; import net.sf.jsqlparser.statement.select.FromItemVisitor; @@ -152,19 +149,18 @@ import net.sf.jsqlparser.statement.select.ParenthesedSelect; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectExpressionItem; import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.SelectItemVisitor; import net.sf.jsqlparser.statement.select.SelectVisitor; import net.sf.jsqlparser.statement.select.SetOperationList; import net.sf.jsqlparser.statement.select.TableFunction; +import net.sf.jsqlparser.statement.select.Values; import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.statement.show.ShowIndexStatement; import net.sf.jsqlparser.statement.show.ShowTablesStatement; import net.sf.jsqlparser.statement.truncate.Truncate; import net.sf.jsqlparser.statement.update.Update; import net.sf.jsqlparser.statement.upsert.Upsert; -import net.sf.jsqlparser.statement.select.Values; import java.util.ArrayList; import java.util.List; @@ -178,7 +174,7 @@ */ @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.UncommentedEmptyMethodBody"}) public class TablesNamesFinder implements SelectVisitor, FromItemVisitor, ExpressionVisitor, - ItemsListVisitor, SelectItemVisitor, StatementVisitor { + SelectItemVisitor, StatementVisitor { private static final String NOT_SUPPORTED_YET = "Not supported yet."; private List tables; @@ -203,6 +199,27 @@ public void visit(Select select) { select.accept((SelectVisitor) this); } + @Override + public void visit(TranscodingFunction transcodingFunction) { + transcodingFunction.getExpression().accept(this); + } + + @Override + public void visit(TrimFunction trimFunction) { + if (trimFunction.getExpression() != null) { + trimFunction.getExpression().accept(this); + } + if (trimFunction.getFromExpression() != null) { + trimFunction.getFromExpression().accept(this); + } + } + + @Override + public void visit(RangeExpression rangeExpression) { + rangeExpression.getStartExpression().accept(this); + rangeExpression.getEndExpression().accept(this); + } + /** * Main entry for this Tool class. A list of found tables is returned. */ @@ -355,14 +372,8 @@ public void visit(GreaterThanEquals greaterThanEquals) { @Override public void visit(InExpression inExpression) { - if (inExpression.getLeftExpression() != null) { - inExpression.getLeftExpression().accept(this); - } - if (inExpression.getRightExpression() != null) { - inExpression.getRightExpression().accept(this); - } else if (inExpression.getRightItemsList() != null) { - inExpression.getRightItemsList().accept(this); - } + inExpression.getLeftExpression().accept(this); + inExpression.getRightExpression().accept(this); } @Override @@ -400,6 +411,12 @@ public void visit(ExistsExpression existsExpression) { existsExpression.getRightExpression().accept(this); } + @Override + public void visit(MemberOfExpression memberOfExpression) { + memberOfExpression.getLeftExpression().accept(this); + memberOfExpression.getRightExpression().accept(this); + } + @Override public void visit(LongValue longValue) { @@ -476,19 +493,12 @@ public void visitBinaryExpression(BinaryExpression binaryExpression) { } @Override - public void visit(ExpressionList expressionList) { + public void visit(ExpressionList expressionList) { for (Expression expression : expressionList.getExpressions()) { expression.accept(this); } } - @Override - public void visit(NamedExpressionList namedExpressionList) { - for (Expression expression : namedExpressionList.getExpressions()) { - expression.accept(this); - } - } - @Override public void visit(DateValue dateValue) { @@ -543,7 +553,7 @@ public void visit(WhenClause whenClause) { @Override public void visit(AnyComparisonExpression anyComparisonExpression) { - anyComparisonExpression.getSubSelect().getSelect().accept((SelectVisitor) this); + anyComparisonExpression.getSelect().accept((ExpressionVisitor) this); } @Override @@ -576,16 +586,6 @@ public void visit(CastExpression cast) { cast.getLeftExpression().accept(this); } - @Override - public void visit(TryCastExpression cast) { - cast.getLeftExpression().accept(this); - } - - @Override - public void visit(SafeCastExpression cast) { - cast.getLeftExpression().accept(this); - } - @Override public void visit(Modulo modulo) { visitBinaryExpression(modulo); @@ -619,13 +619,6 @@ public void visit(LateralSubSelect lateralSubSelect) { lateralSubSelect.getSelect().accept((SelectVisitor) this); } - @Override - public void visit(MultiExpressionList multiExprList) { - for (ExpressionList exprList : multiExprList.getExprList()) { - exprList.accept(this); - } - } - /** * Initializes table names collector. Important is the usage of Column instances to find table * names. This is only allowed for expression parsing, where a better place for tablenames could @@ -702,7 +695,7 @@ public void visit(IsDistinctExpression isDistinctExpression) { } @Override - public void visit(SelectExpressionItem item) { + public void visit(SelectItem item) { item.getExpression().accept(this); } @@ -727,11 +720,6 @@ public void visit(MySQLGroupConcat groupConcat) { } - @Override - public void visit(ValueListExpression valueList) { - valueList.getExpressionList().accept(this); - } - @Override public void visit(Delete delete) { visit(delete.getTable()); @@ -785,27 +773,11 @@ public void visit(Update update) { @Override public void visit(Insert insert) { visit(insert.getTable()); - if (insert.getItemsList() != null) { - insert.getItemsList().accept(this); - } if (insert.getSelect() != null) { visit(insert.getSelect()); } } - @Override - public void visit(Replace replace) { - visit(replace.getTable()); - if (replace.getExpressions() != null) { - for (Expression expression : replace.getExpressions()) { - expression.accept(this); - } - } - if (replace.getItemsList() != null) { - replace.getItemsList().accept(this); - } - } - public void visit(Analyze analyze) { visit(analyze.getTable()); } @@ -879,8 +851,8 @@ public void visit(ShowIndexStatement showIndex) { } @Override - public void visit(RowConstructor rowConstructor) { - for (Expression expr : rowConstructor.getExprList().getExpressions()) { + public void visit(RowConstructor rowConstructor) { + for (Expression expr : rowConstructor) { expr.accept(this); } } @@ -937,8 +909,8 @@ public void visit(Commit commit) { @Override public void visit(Upsert upsert) { visit(upsert.getTable()); - if (upsert.getItemsList() != null) { - upsert.getItemsList().accept(this); + if (upsert.getExpressions() != null) { + upsert.getExpressions().accept(this); } if (upsert.getSelect() != null) { visit(upsert.getSelect()); diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/AbstractDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/AbstractDeParser.java index 9eda54d66..4a31a7ace 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/AbstractDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/AbstractDeParser.java @@ -9,6 +9,11 @@ */ package net.sf.jsqlparser.util.deparser; +import net.sf.jsqlparser.expression.ExpressionVisitor; +import net.sf.jsqlparser.statement.update.UpdateSet; + +import java.util.List; + /** * A base for a Statement DeParser * @@ -21,6 +26,23 @@ protected AbstractDeParser(StringBuilder buffer) { this.buffer = buffer; } + public static void deparseUpdateSets(List updateSets, StringBuilder buffer, + ExpressionVisitor visitor) { + ExpressionListDeParser expressionListDeParser = + new ExpressionListDeParser(visitor, buffer); + int j = 0; + if (updateSets != null) { + for (UpdateSet updateSet : updateSets) { + if (j++ > 0) { + buffer.append(", "); + } + expressionListDeParser.deParse(updateSet.getColumns()); + buffer.append(" = "); + expressionListDeParser.deParse(updateSet.getValues()); + } + } + } + public StringBuilder getBuffer() { return buffer; } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java index e6f425bd4..b97794af4 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java @@ -9,17 +9,17 @@ */ package net.sf.jsqlparser.util.deparser; -import java.util.Iterator; -import static java.util.stream.Collectors.joining; - import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.expression.ExpressionVisitorAdapter; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.delete.Delete; import net.sf.jsqlparser.statement.select.Join; -import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.WithItem; +import java.util.Iterator; + +import static java.util.stream.Collectors.joining; + public class DeleteDeParser extends AbstractDeParser { private ExpressionVisitor expressionVisitor = new ExpressionVisitorAdapter(); @@ -36,17 +36,17 @@ public DeleteDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) @Override @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"}) public void deParse(Delete delete) { - if (delete.getWithItemsList() != null && !delete.getWithItemsList().isEmpty()) { - buffer.append("WITH "); - for (Iterator iter = delete.getWithItemsList().iterator(); iter.hasNext(); ) { - WithItem withItem = iter.next(); - buffer.append(withItem); - if (iter.hasNext()) { - buffer.append(","); + if (delete.getWithItemsList() != null && !delete.getWithItemsList().isEmpty()) { + buffer.append("WITH "); + for (Iterator iter = delete.getWithItemsList().iterator(); iter.hasNext();) { + WithItem withItem = iter.next(); + buffer.append(withItem); + if (iter.hasNext()) { + buffer.append(","); + } + buffer.append(" "); + } } - buffer.append(" "); - } - } buffer.append("DELETE"); if (delete.getModifierPriority() != null) { buffer.append(" ").append(delete.getModifierPriority()); @@ -59,10 +59,11 @@ public void deParse(Delete delete) { } if (delete.getTables() != null && !delete.getTables().isEmpty()) { buffer.append( - delete.getTables().stream().map(Table::getFullyQualifiedName).collect(joining(", ", " ", ""))); + delete.getTables().stream().map(Table::getFullyQualifiedName) + .collect(joining(", ", " ", ""))); } - if (delete.getOutputClause()!=null) { + if (delete.getOutputClause() != null) { delete.getOutputClause().appendTo(buffer); } @@ -73,7 +74,8 @@ public void deParse(Delete delete) { if (delete.getUsingList() != null && !delete.getUsingList().isEmpty()) { buffer.append(" USING").append( - delete.getUsingList().stream().map(Table::toString).collect(joining(", ", " ", ""))); + delete.getUsingList().stream().map(Table::toString) + .collect(joining(", ", " ", ""))); } if (delete.getJoins() != null) { for (Join join : delete.getJoins()) { @@ -94,12 +96,11 @@ public void deParse(Delete delete) { new OrderByDeParser(expressionVisitor, buffer).deParse(delete.getOrderByElements()); } if (delete.getLimit() != null) { - new LimitDeparser(buffer).deParse(delete.getLimit()); + new LimitDeparser(expressionVisitor, buffer).deParse(delete.getLimit()); } - if (delete.getReturningExpressionList() != null) { - buffer.append(" RETURNING ").append(PlainSelect. - getStringList(delete.getReturningExpressionList(), true, false)); + if (delete.getReturningClause() != null) { + delete.getReturningClause().appendTo(buffer); } } 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 f1e75ae61..2b9818130 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -46,18 +46,18 @@ import net.sf.jsqlparser.expression.OracleNamedFunctionParameter; import net.sf.jsqlparser.expression.OverlapsCondition; import net.sf.jsqlparser.expression.Parenthesis; +import net.sf.jsqlparser.expression.RangeExpression; import net.sf.jsqlparser.expression.RowConstructor; import net.sf.jsqlparser.expression.RowGetExpression; -import net.sf.jsqlparser.expression.SafeCastExpression; import net.sf.jsqlparser.expression.SignedExpression; import net.sf.jsqlparser.expression.StringValue; import net.sf.jsqlparser.expression.TimeKeyExpression; import net.sf.jsqlparser.expression.TimeValue; import net.sf.jsqlparser.expression.TimestampValue; import net.sf.jsqlparser.expression.TimezoneExpression; -import net.sf.jsqlparser.expression.TryCastExpression; +import net.sf.jsqlparser.expression.TranscodingFunction; +import net.sf.jsqlparser.expression.TrimFunction; import net.sf.jsqlparser.expression.UserVariable; -import net.sf.jsqlparser.expression.ValueListExpression; import net.sf.jsqlparser.expression.VariableAssignment; import net.sf.jsqlparser.expression.WhenClause; import net.sf.jsqlparser.expression.WindowElement; @@ -89,14 +89,12 @@ import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression; import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression; import net.sf.jsqlparser.expression.operators.relational.IsNullExpression; -import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor; import net.sf.jsqlparser.expression.operators.relational.JsonOperator; import net.sf.jsqlparser.expression.operators.relational.LikeExpression; import net.sf.jsqlparser.expression.operators.relational.Matches; +import net.sf.jsqlparser.expression.operators.relational.MemberOfExpression; import net.sf.jsqlparser.expression.operators.relational.MinorThan; import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals; -import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; -import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList; import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo; import net.sf.jsqlparser.expression.operators.relational.OldOracleJoinBinaryExpression; import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator; @@ -105,12 +103,10 @@ import net.sf.jsqlparser.expression.operators.relational.SupportsOldOracleJoinSyntax; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; -import net.sf.jsqlparser.statement.create.table.ColumnDefinition; import net.sf.jsqlparser.statement.select.AllColumns; import net.sf.jsqlparser.statement.select.AllTableColumns; import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.ParenthesedSelect; -import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.select.SelectVisitor; import net.sf.jsqlparser.statement.select.WithItem; @@ -123,7 +119,7 @@ @SuppressWarnings({"PMD.CyclomaticComplexity"}) public class ExpressionDeParser extends AbstractDeParser // FIXME maybe we should implement an ItemsListDeparser too? - implements ExpressionVisitor, ItemsListVisitor { + implements ExpressionVisitor { private static final String NOT = "NOT "; private SelectVisitor selectVisitor; @@ -256,11 +252,7 @@ public void visit(InExpression inExpression) { buffer.append(" NOT"); } buffer.append(" IN "); - if (inExpression.getRightExpression() != null) { - inExpression.getRightExpression().accept(this); - } else { - inExpression.getRightItemsList().accept(this); - } + inExpression.getRightExpression().accept(this); } @Override @@ -355,6 +347,17 @@ public void visit(ExistsExpression existsExpression) { existsExpression.getRightExpression().accept(this); } + @Override + public void visit(MemberOfExpression memberOfExpression) { + memberOfExpression.getLeftExpression().accept(this); + if (memberOfExpression.isNot()) { + buffer.append(" NOT MEMBER OF "); + } else { + buffer.append(" MEMBER OF "); + } + memberOfExpression.getRightExpression().accept(this); + } + @Override public void visit(LongValue longValue) { buffer.append(longValue.getStringValue()); @@ -452,6 +455,41 @@ public void visit(Select selectBody) { } } + @Override + public void visit(TranscodingFunction transcodingFunction) { + buffer.append("CONVERT( "); + transcodingFunction.getExpression().accept(this); + buffer.append(" USING ") + .append(transcodingFunction.getTranscodingName()) + .append(" )"); + } + + public void visit(TrimFunction trimFunction) { + buffer.append("Trim("); + + if (trimFunction.getTrimSpecification() != null) { + buffer.append(" ").append(trimFunction.getTrimSpecification()); + } + + if (trimFunction.getExpression() != null) { + buffer.append(" "); + trimFunction.getExpression().accept(this); + } + + if (trimFunction.getFromExpression() != null) { + buffer.append(trimFunction.isUsingFromKeyword() ? " FROM " : ", "); + trimFunction.getFromExpression().accept(this); + } + buffer.append(" )"); + } + + @Override + public void visit(RangeExpression rangeExpression) { + rangeExpression.getStartExpression().accept(this); + buffer.append(":"); + rangeExpression.getEndExpression().accept(this); + } + @Override public void visit(Column tableColumn) { final Table table = tableColumn.getTable(); @@ -468,6 +506,10 @@ public void visit(Column tableColumn) { } buffer.append(tableColumn.getColumnName()); + + if (tableColumn.getArrayConstructor() != null) { + tableColumn.getArrayConstructor().accept(this); + } } @Override @@ -490,10 +532,10 @@ public void visit(Function function) { buffer.append("UNIQUE "); } if (function.getNamedParameters() != null) { - visit(function.getNamedParameters()); + function.getNamedParameters().accept(this); } if (function.getParameters() != null) { - visit(function.getParameters()); + function.getParameters().accept(this); } if (function.getOrderByElements() != null) { buffer.append(" ORDER BY "); @@ -529,29 +571,6 @@ public void visit(ParenthesedSelect selectBody) { selectBody.getSelect().accept(this); } - @Override - public void visit(ExpressionList expressionList) { - new ExpressionListDeParser(this, buffer, expressionList.isUsingBrackets(), true) - .deParse(expressionList.getExpressions()); - } - - @Override - public void visit(NamedExpressionList namedExpressionList) { - List names = namedExpressionList.getNames(); - List expressions = namedExpressionList.getExpressions(); - for (int i = 0; i < names.size(); i++) { - if (i > 0) { - buffer.append(" "); - } - String name = names.get(i); - if (!name.equals("")) { - buffer.append(name); - buffer.append(" "); - } - expressions.get(i).accept(this); - } - } - public SelectVisitor getSelectVisitor() { return selectVisitor; } @@ -609,17 +628,10 @@ public void visit(WhenClause whenClause) { @Override public void visit(AnyComparisonExpression anyComparisonExpression) { - buffer.append(anyComparisonExpression.getAnyType().name()).append(" ( "); - ParenthesedSelect subSelect = anyComparisonExpression.getSubSelect(); - if (subSelect != null) { - subSelect.accept((ExpressionVisitor) this); - } else { - ExpressionList expressionList = (ExpressionList) anyComparisonExpression.getItemsList(); - buffer.append("VALUES "); - buffer.append(PlainSelect.getStringList(expressionList.getExpressions(), true, - anyComparisonExpression.isUsingBracketsForValues())); - } - buffer.append(" ) "); + buffer.append(anyComparisonExpression.getAnyType().name()); + + // VALUES or SELECT + anyComparisonExpression.getSelect().accept((ExpressionVisitor) this); } @Override @@ -650,50 +662,19 @@ public void visit(BitwiseXor bitwiseXor) { @Override public void visit(CastExpression cast) { if (cast.isUseCastKeyword()) { - buffer.append("CAST("); - cast.getLeftExpression().accept(this); - buffer.append(" AS "); - buffer.append( - cast.getRowConstructor() != null ? cast.getRowConstructor() : cast.getType()); - buffer.append(")"); - } else { - cast.getLeftExpression().accept(this); - buffer.append("::"); - buffer.append(cast.getType()); - } - } - - @Override - public void visit(TryCastExpression cast) { - if (cast.isUseCastKeyword()) { - buffer.append("TRY_CAST("); - cast.getLeftExpression().accept(this); - buffer.append(" AS "); - buffer.append( - cast.getRowConstructor() != null ? cast.getRowConstructor() : cast.getType()); - buffer.append(")"); - } else { - cast.getLeftExpression().accept(this); - buffer.append("::"); - buffer.append(cast.getType()); - } - } - - @Override - public void visit(SafeCastExpression cast) { - if (cast.isUseCastKeyword()) { - buffer.append("SAFE_CAST("); + buffer.append(cast.keyword).append("("); cast.getLeftExpression().accept(this); buffer.append(" AS "); buffer.append( - cast.getRowConstructor() != null ? cast.getRowConstructor() : cast.getType()); + cast.getColumnDefinitions().size() > 1 + ? "ROW(" + Select.getStringList(cast.getColumnDefinitions()) + ")" + : cast.getColDataType().toString()); buffer.append(")"); } else { cast.getLeftExpression().accept(this); buffer.append("::"); - buffer.append(cast.getType()); + buffer.append(cast.getColDataType()); } - } @Override @@ -834,16 +815,6 @@ public void visit(ExtractExpression eexpr) { buffer.append(')'); } - @Override - public void visit(MultiExpressionList multiExprList) { - for (Iterator it = multiExprList.getExprList().iterator(); it.hasNext();) { - it.next().accept(this); - if (it.hasNext()) { - buffer.append(", "); - } - } - } - @Override public void visit(IntervalExpression iexpr) { buffer.append(iexpr.toString()); @@ -900,9 +871,10 @@ public void visit(MySQLGroupConcat groupConcat) { } @Override - public void visit(ValueListExpression valueList) { - ExpressionList expressionList = valueList.getExpressionList(); - expressionList.accept(this); + public void visit(ExpressionList expressionList) { + ExpressionListDeParser expressionListDeParser = + new ExpressionListDeParser<>(this, buffer); + expressionListDeParser.deParse(expressionList); } @Override @@ -910,28 +882,9 @@ public void visit(RowConstructor rowConstructor) { if (rowConstructor.getName() != null) { buffer.append(rowConstructor.getName()); } - buffer.append("("); - - if (rowConstructor.getColumnDefinitions().size() > 0) { - buffer.append("("); - int i = 0; - for (ColumnDefinition columnDefinition : rowConstructor.getColumnDefinitions()) { - buffer.append(i > 0 ? ", " : "").append(columnDefinition.toString()); - i++; - } - buffer.append(")"); - } else { - boolean first = true; - for (Expression expr : rowConstructor.getExprList().getExpressions()) { - if (first) { - first = false; - } else { - buffer.append(", "); - } - expr.accept(this); - } - } - buffer.append(")"); + ExpressionListDeParser expressionListDeParser = + new ExpressionListDeParser<>(this, buffer); + expressionListDeParser.deParse(rowConstructor); } @Override diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionListDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionListDeParser.java index 0a39e6cdd..f13066ff2 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionListDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionListDeParser.java @@ -11,40 +11,55 @@ import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; +import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; -import java.util.Collection; +import java.util.Collections; +import java.util.List; -public class ExpressionListDeParser extends AbstractDeParser> { +public class ExpressionListDeParser + extends AbstractDeParser> { private final ExpressionVisitor expressionVisitor; - private final boolean useBrackets; - private final boolean useComma; - public ExpressionListDeParser(ExpressionVisitor expressionVisitor, StringBuilder builder, boolean useBrackets, boolean useComma) { + public ExpressionListDeParser(ExpressionVisitor expressionVisitor, StringBuilder builder) { super(builder); this.expressionVisitor = expressionVisitor; - this.useBrackets = useBrackets; - this.useComma = useComma; } @Override - public void deParse(Collection expressions) { - if (expressions != null) { - String comma = useComma ? ", " : " "; - if (useBrackets) { + public void deParse(ExpressionList expressionList) { + // @todo: remove this NameExpressionList related part + String comma = expressionList instanceof NamedExpressionList + ? " " + : ", "; + // @todo: remove this NameExpressionList related part + List names = expressionList instanceof NamedExpressionList + ? ((NamedExpressionList) expressionList).getNames() + : Collections.nCopies(expressionList.size(), ""); + + if (expressionList != null) { + if (expressionList instanceof ParenthesedExpressionList) { buffer.append("("); } - int i=0; - int size = expressions.size() - 1; - for (Expression expression: expressions) { - expression.accept(expressionVisitor); - if (i 0) { buffer.append(comma); } + + // @todo: remove this NameExpressionList related part + String name = names.get(i); + if (!name.equals("")) { + buffer.append(name); + buffer.append(" "); + } + expression.accept(expressionVisitor); i++; } - if (useBrackets) { + if (expressionList instanceof ParenthesedExpressionList) { buffer.append(")"); } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/GroupByDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/GroupByDeParser.java index 839ae1adb..3c5cedf10 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/GroupByDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/GroupByDeParser.java @@ -9,25 +9,21 @@ */ package net.sf.jsqlparser.util.deparser; -import java.util.Iterator; -import java.util.List; - -import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.statement.select.GroupByElement; public class GroupByDeParser extends AbstractDeParser { - private ExpressionVisitor expressionVisitor; + private ExpressionListDeParser expressionListDeParser; GroupByDeParser() { - super(new StringBuilder()); + this(null, new StringBuilder()); } public GroupByDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { super(buffer); - this.expressionVisitor = expressionVisitor; + this.expressionListDeParser = new ExpressionListDeParser(expressionVisitor, buffer); this.buffer = buffer; } @@ -35,46 +31,19 @@ public GroupByDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"}) public void deParse(GroupByElement groupBy) { buffer.append("GROUP BY "); - if (groupBy.isUsingBrackets()) { - buffer.append("( "); - } - List expressions = groupBy.getGroupByExpressionList().getExpressions(); - if (expressions != null) { - for (Iterator iter = expressions.iterator(); iter.hasNext();) { - iter.next().accept(expressionVisitor); - if (iter.hasNext()) { - buffer.append(", "); - } - } - } - if (groupBy.isUsingBrackets()) { - buffer.append(" )"); - } + expressionListDeParser.deParse(groupBy.getGroupByExpressionList()); + + int i = 0; if (!groupBy.getGroupingSets().isEmpty()) { if (buffer.charAt(buffer.length() - 1) != ' ') { buffer.append(' '); } buffer.append("GROUPING SETS ("); - boolean first = true; - for (Object o : groupBy.getGroupingSets()) { - if (first) { - first = false; - } else { - buffer.append(", "); - } - if (o instanceof Expression) { - buffer.append(o.toString()); - } else if (o instanceof ExpressionList) { - ExpressionList list = (ExpressionList) o; - buffer.append(list.getExpressions() == null ? "()" : list.toString()); - } + for (ExpressionList expressionList : groupBy.getGroupingSets()) { + buffer.append(i++ > 0 ? ", " : ""); + expressionListDeParser.deParse(expressionList); } buffer.append(")"); } } - - void setExpressionVisitor(ExpressionVisitor expressionVisitor) { - this.expressionVisitor = expressionVisitor; - } - } 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 45cd0999b..a0614540e 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java @@ -9,24 +9,16 @@ */ package net.sf.jsqlparser.util.deparser; -import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor; -import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; -import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.statement.insert.Insert; -import net.sf.jsqlparser.statement.select.ParenthesedSelect; -import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.select.SelectVisitor; import net.sf.jsqlparser.statement.select.WithItem; import java.util.Iterator; -import java.util.List; -public class InsertDeParser extends AbstractDeParser implements ItemsListVisitor { +public class InsertDeParser extends AbstractDeParser { private ExpressionVisitor expressionVisitor; private SelectVisitor selectVisitor; @@ -91,34 +83,14 @@ public void deParse(Insert insert) { select.accept(selectVisitor); } - if (insert.isUseSet()) { + if (insert.getSetUpdateSets() != null) { buffer.append(" SET "); - for (int i = 0; i < insert.getSetColumns().size(); i++) { - Column column = insert.getSetColumns().get(i); - column.accept(expressionVisitor); - - buffer.append(" = "); - - Expression expression = insert.getSetExpressionList().get(i); - expression.accept(expressionVisitor); - if (i < insert.getSetColumns().size() - 1) { - buffer.append(", "); - } - } + deparseUpdateSets(insert.getSetUpdateSets(), buffer, expressionVisitor); } - if (insert.isUseDuplicate()) { + if (insert.getDuplicateUpdateSets() != null) { buffer.append(" ON DUPLICATE KEY UPDATE "); - for (int i = 0; i < insert.getDuplicateUpdateColumns().size(); i++) { - Column column = insert.getDuplicateUpdateColumns().get(i); - buffer.append(column.getFullyQualifiedName()).append(" = "); - - Expression expression = insert.getDuplicateUpdateExpressionList().get(i); - expression.accept(expressionVisitor); - if (i < insert.getDuplicateUpdateColumns().size() - 1) { - buffer.append(", "); - } - } + deparseUpdateSets(insert.getDuplicateUpdateSets(), buffer, expressionVisitor); } // @todo: Accept some Visitors for the involved Expressions @@ -131,43 +103,11 @@ public void deParse(Insert insert) { insert.getConflictAction().appendTo(buffer); } - if (insert.getReturningExpressionList() != null) { - buffer.append(" RETURNING ").append( - PlainSelect.getStringList(insert.getReturningExpressionList(), true, false)); + if (insert.getReturningClause() != null) { + insert.getReturningClause().appendTo(buffer); } } - @Override - public void visit(ExpressionList expressionList) { - new ExpressionListDeParser(expressionVisitor, buffer, expressionList.isUsingBrackets(), - true).deParse(expressionList.getExpressions()); - } - - @Override - public void visit(NamedExpressionList NamedExpressionList) { - // not used in a top-level insert statement - } - - @Override - public void visit(MultiExpressionList multiExprList) { - List expressionLists = multiExprList.getExpressionLists(); - int n = expressionLists.size() - 1; - int i = 0; - for (ExpressionList expressionList : expressionLists) { - new ExpressionListDeParser(expressionVisitor, buffer, expressionList.isUsingBrackets(), - true).deParse(expressionList.getExpressions()); - if (i < n) { - buffer.append(", "); - } - i++; - } - } - - @Override - public void visit(ParenthesedSelect selectBody) { - selectBody.accept(selectVisitor); - } - public ExpressionVisitor getExpressionVisitor() { return expressionVisitor; } @@ -183,6 +123,4 @@ public void setExpressionVisitor(ExpressionVisitor visitor) { public void setSelectVisitor(SelectVisitor visitor) { selectVisitor = visitor; } - - } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/LimitDeparser.java b/src/main/java/net/sf/jsqlparser/util/deparser/LimitDeparser.java index 6852f235b..88aec177d 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/LimitDeparser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/LimitDeparser.java @@ -9,12 +9,15 @@ */ package net.sf.jsqlparser.util.deparser; +import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.statement.select.Limit; public class LimitDeparser extends AbstractDeParser { + private ExpressionVisitor expressionVisitor; - public LimitDeparser(StringBuilder buffer) { + public LimitDeparser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { super(buffer); + this.expressionVisitor = expressionVisitor; } @Override @@ -27,13 +30,27 @@ public void deParse(Limit limit) { buffer.append("ALL"); } else { if (null != limit.getOffset()) { - buffer.append(limit.getOffset()).append(", "); + limit.getOffset().accept(expressionVisitor); + buffer.append(", "); } if (null != limit.getRowCount()) { - buffer.append(limit.getRowCount()); + limit.getRowCount().accept(expressionVisitor); } } } + + if (limit.getByExpressions() != null) { + buffer.append(" BY "); + limit.getByExpressions().accept(expressionVisitor); + } + } + + public ExpressionVisitor getExpressionVisitor() { + return expressionVisitor; + } + + public void setExpressionVisitor(ExpressionVisitor expressionVisitor) { + this.expressionVisitor = expressionVisitor; } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ReplaceDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ReplaceDeParser.java deleted file mode 100644 index 29647f160..000000000 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ReplaceDeParser.java +++ /dev/null @@ -1,144 +0,0 @@ -/*- - * #%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.util.deparser; - -import net.sf.jsqlparser.expression.Expression; -import net.sf.jsqlparser.expression.ExpressionVisitor; -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor; -import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; -import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList; -import net.sf.jsqlparser.schema.Column; -import net.sf.jsqlparser.statement.replace.Replace; -import net.sf.jsqlparser.statement.select.ParenthesedSelect; -import net.sf.jsqlparser.statement.select.SelectVisitor; - -import java.util.Iterator; - -public class ReplaceDeParser extends AbstractDeParser implements ItemsListVisitor { - - private ExpressionVisitor expressionVisitor; - private SelectVisitor selectVisitor; - - public ReplaceDeParser() { - super(new StringBuilder()); - } - - public ReplaceDeParser(ExpressionVisitor expressionVisitor, SelectVisitor selectVisitor, - StringBuilder buffer) { - super(buffer); - this.expressionVisitor = expressionVisitor; - this.selectVisitor = selectVisitor; - } - - @Override - public void deParse(Replace replace) { - buffer.append("REPLACE "); - if (replace.isUseIntoTables()) { - buffer.append("INTO "); - } - buffer.append(replace.getTable().getFullyQualifiedName()); - if (replace.getItemsList() != null) { - if (replace.getColumns() != null) { - buffer.append(" ("); - for (int i = 0; i < replace.getColumns().size(); i++) { - Column column = replace.getColumns().get(i); - buffer.append(column.getFullyQualifiedName()); - if (i < replace.getColumns().size() - 1) { - buffer.append(", "); - } - } - buffer.append(") "); - } else { - buffer.append(" "); - } - - } else { - buffer.append(" SET "); - for (int i = 0; i < replace.getColumns().size(); i++) { - Column column = replace.getColumns().get(i); - buffer.append(column.getFullyQualifiedName()).append("="); - - Expression expression = replace.getExpressions().get(i); - expression.accept(expressionVisitor); - if (i < replace.getColumns().size() - 1) { - buffer.append(", "); - } - - } - } - - if (replace.getItemsList() != null) { - // REPLACE mytab SELECT * FROM mytab2 - // or VALUES ('as', ?, 565) - replace.getItemsList().accept(this); - } - } - - @Override - public void visit(ExpressionList expressionList) { - buffer.append("VALUES ("); - for (Iterator iter = expressionList.getExpressions().iterator(); iter - .hasNext();) { - Expression expression = iter.next(); - expression.accept(expressionVisitor); - if (iter.hasNext()) { - buffer.append(", "); - } - } - buffer.append(")"); - } - - @Override - public void visit(NamedExpressionList namedExpressionList) { - // NamedExpressionList not use by top-level Replace - } - - @Override - public void visit(ParenthesedSelect selectBody) { - selectBody.accept(selectVisitor); - } - - public ExpressionVisitor getExpressionVisitor() { - return expressionVisitor; - } - - public SelectVisitor getSelectVisitor() { - return selectVisitor; - } - - public void setExpressionVisitor(ExpressionVisitor visitor) { - expressionVisitor = visitor; - } - - public void setSelectVisitor(SelectVisitor visitor) { - selectVisitor = visitor; - } - - @Override - public void visit(MultiExpressionList multiExprList) { - buffer.append("VALUES "); - for (Iterator it = multiExprList.getExprList().iterator(); it.hasNext();) { - buffer.append("("); - for (Iterator iter = it.next().getExpressions().iterator(); iter - .hasNext();) { - Expression expression = iter.next(); - expression.accept(expressionVisitor); - if (iter.hasNext()) { - buffer.append(", "); - } - } - buffer.append(")"); - if (it.hasNext()) { - buffer.append(", "); - } - } - } -} 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 064ebe5c3..09f46dfdc 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java @@ -17,20 +17,15 @@ import net.sf.jsqlparser.expression.OracleHint; import net.sf.jsqlparser.expression.SQLServerHints; import net.sf.jsqlparser.expression.WindowDefinition; -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor; -import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; -import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; -import net.sf.jsqlparser.statement.select.AllColumns; -import net.sf.jsqlparser.statement.select.AllTableColumns; import net.sf.jsqlparser.statement.select.Fetch; import net.sf.jsqlparser.statement.select.First; import net.sf.jsqlparser.statement.select.FromItem; import net.sf.jsqlparser.statement.select.FromItemVisitor; import net.sf.jsqlparser.statement.select.Join; import net.sf.jsqlparser.statement.select.LateralSubSelect; +import net.sf.jsqlparser.statement.select.LateralView; import net.sf.jsqlparser.statement.select.Offset; import net.sf.jsqlparser.statement.select.OptimizeFor; import net.sf.jsqlparser.statement.select.ParenthesedFromItem; @@ -39,7 +34,6 @@ import net.sf.jsqlparser.statement.select.PivotVisitor; import net.sf.jsqlparser.statement.select.PivotXml; import net.sf.jsqlparser.statement.select.PlainSelect; -import net.sf.jsqlparser.statement.select.SelectExpressionItem; import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.SelectItemVisitor; import net.sf.jsqlparser.statement.select.SelectVisitor; @@ -48,8 +42,8 @@ import net.sf.jsqlparser.statement.select.TableFunction; import net.sf.jsqlparser.statement.select.Top; import net.sf.jsqlparser.statement.select.UnPivot; -import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.statement.select.Values; +import net.sf.jsqlparser.statement.select.WithItem; import java.util.Iterator; import java.util.List; @@ -58,7 +52,7 @@ @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"}) public class SelectDeParser extends AbstractDeParser implements SelectVisitor, - SelectItemVisitor, FromItemVisitor, PivotVisitor, ItemsListVisitor { + SelectItemVisitor, FromItemVisitor, PivotVisitor { private ExpressionVisitor expressionVisitor; @@ -80,8 +74,8 @@ public void visit(ParenthesedSelect selectBody) { List withItemsList = selectBody.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { buffer.append("WITH "); - for (Iterator iter = withItemsList.iterator(); iter.hasNext();) { - iter.next().accept((SelectVisitor) this); + for (WithItem withItem : withItemsList) { + withItem.accept((SelectVisitor) this); buffer.append(" "); } } @@ -109,7 +103,7 @@ public void visit(ParenthesedSelect selectBody) { } if (selectBody.getLimit() != null) { - new LimitDeparser(buffer).deParse(selectBody.getLimit()); + new LimitDeparser(expressionVisitor, buffer).deParse(selectBody.getLimit()); } if (selectBody.getOffset() != null) { visit(selectBody.getOffset()); @@ -167,9 +161,9 @@ public void visit(PlainSelect plainSelect) { } if (plainSelect.getDistinct().getOnSelectItems() != null) { buffer.append("ON ("); - for (Iterator iter = + for (Iterator> iter = plainSelect.getDistinct().getOnSelectItems().iterator(); iter.hasNext();) { - SelectItem selectItem = iter.next(); + SelectItem selectItem = iter.next(); selectItem.accept(this); if (iter.hasNext()) { buffer.append(", "); @@ -193,11 +187,14 @@ public void visit(PlainSelect plainSelect) { buffer.append("SQL_CALC_FOUND_ROWS").append(" "); } - for (Iterator iter = plainSelect.getSelectItems().iterator(); iter.hasNext();) { - SelectItem selectItem = iter.next(); - selectItem.accept(this); - if (iter.hasNext()) { - buffer.append(", "); + final List> selectItems = plainSelect.getSelectItems(); + if (selectItems != null) { + for (Iterator> iter = selectItems.iterator(); iter.hasNext();) { + SelectItem selectItem = iter.next(); + selectItem.accept(this); + if (iter.hasNext()) { + buffer.append(", "); + } } } @@ -216,12 +213,22 @@ public void visit(PlainSelect plainSelect) { plainSelect.getFromItem().accept(this); } + if (plainSelect.getLateralViews() != null) { + for (LateralView lateralView : plainSelect.getLateralViews()) { + deparseLateralView(lateralView); + } + } + if (plainSelect.getJoins() != null) { for (Join join : plainSelect.getJoins()) { deparseJoin(join); } } + if (plainSelect.isUsingFinal()) { + buffer.append(" FINAL"); + } + if (plainSelect.getKsqlWindow() != null) { buffer.append(" WINDOW "); buffer.append(plainSelect.getKsqlWindow().toString()); @@ -272,8 +279,11 @@ public void visit(PlainSelect plainSelect) { if (plainSelect.isEmitChanges()) { buffer.append(" EMIT CHANGES"); } + if (plainSelect.getLimitBy() != null) { + new LimitDeparser(expressionVisitor, buffer).deParse(plainSelect.getLimitBy()); + } if (plainSelect.getLimit() != null) { - new LimitDeparser(buffer).deParse(plainSelect.getLimit()); + new LimitDeparser(expressionVisitor, buffer).deParse(plainSelect.getLimit()); } if (plainSelect.getOffset() != null) { visit(plainSelect.getOffset()); @@ -294,12 +304,7 @@ public void visit(PlainSelect plainSelect) { } @Override - public void visit(AllTableColumns allTableColumns) { - buffer.append(allTableColumns.getTable().getFullyQualifiedName()).append(".*"); - } - - @Override - public void visit(SelectExpressionItem selectExpressionItem) { + public void visit(SelectItem selectExpressionItem) { selectExpressionItem.getExpression().accept(expressionVisitor); if (selectExpressionItem.getAlias() != null) { buffer.append(selectExpressionItem.getAlias().toString()); @@ -334,13 +339,16 @@ public void visit(Table tableName) { @Override public void visit(Pivot pivot) { - List forColumns = pivot.getForColumns(); - buffer.append(" PIVOT (").append(PlainSelect.getStringList(pivot.getFunctionItems())) - .append(" FOR ") - .append(PlainSelect.getStringList(forColumns, true, - forColumns != null && forColumns.size() > 1)) - .append(" IN ").append(PlainSelect.getStringList(pivot.getInItems(), true, true)) - .append(")"); + // @todo: implement this as Visitor + buffer.append(" PIVOT (").append(PlainSelect.getStringList(pivot.getFunctionItems())); + + buffer.append(" FOR "); + pivot.getForColumns().accept(expressionVisitor); + + // @todo: implement this as Visitor + buffer.append(" IN ").append(PlainSelect.getStringList(pivot.getInItems(), true, true)); + + buffer.append(")"); if (pivot.getAlias() != null) { buffer.append(pivot.getAlias().toString()); } @@ -485,6 +493,23 @@ public void deparseJoin(Join join) { } + public void deparseLateralView(LateralView lateralView) { + buffer.append(" LATERAL VIEW"); + + if (lateralView.isUsingOuter()) { + buffer.append(" OUTER"); + } + + buffer.append(" "); + lateralView.getGeneratorFunction().accept(expressionVisitor); + + if (lateralView.getTableAlias() != null) { + buffer.append(" ").append(lateralView.getTableAlias()); + } + + buffer.append(" ").append(lateralView.getColumnAlias()); + } + @Override public void visit(SetOperationList list) { List withItemsList = list.getWithItemsList(); @@ -510,7 +535,7 @@ public void visit(SetOperationList list) { } if (list.getLimit() != null) { - new LimitDeparser(buffer).deParse(list.getLimit()); + new LimitDeparser(expressionVisitor, buffer).deParse(list.getLimit()); } if (list.getOffset() != null) { visit(list.getOffset()); @@ -543,11 +568,6 @@ public void visit(LateralSubSelect lateralSubSelect) { visit((ParenthesedSelect) lateralSubSelect); } - @Override - public void visit(AllColumns allColumns) { - buffer.append('*'); - } - @Override public void visit(TableFunction tableFunction) { buffer.append(tableFunction.toString()); @@ -585,7 +605,7 @@ public void visit(ParenthesedFromItem fromItem) { @Override public void visit(Values values) { - new ValuesStatementDeParser(this, buffer).deParse(values); + new ValuesStatementDeParser(expressionVisitor, buffer).deParse(values); } private void deparseOptimizeFor(OptimizeFor optimizeFor) { @@ -599,45 +619,4 @@ void deParse(PlainSelect statement) { statement.accept((SelectVisitor) this); } - @Override - public void visit(ExpressionList expressionList) { - new ExpressionListDeParser(expressionVisitor, buffer, expressionList.isUsingBrackets(), - true).deParse(expressionList.getExpressions()); - } - - @Override - public void visit(NamedExpressionList namedExpressionList) { - buffer.append(namedExpressionList.toString()); - - buffer.append("("); - List expressions = namedExpressionList.getExpressions(); - List names = namedExpressionList.getNames(); - for (int i = 0; i < expressions.size(); i++) { - Expression expression = expressions.get(i); - String name = names.get(i); - if (i > 0) { - buffer.append(" "); - } - if (!name.equals("")) { - buffer.append(name).append(" "); - } - expression.accept(expressionVisitor); - } - buffer.append(")"); - } - - @Override - public void visit(MultiExpressionList multiExprList) { - List expressionLists = multiExprList.getExpressionLists(); - int n = expressionLists.size() - 1; - int i = 0; - for (ExpressionList expressionList : expressionLists) { - new ExpressionListDeParser(expressionVisitor, buffer, expressionList.isUsingBrackets(), - true).deParse(expressionList.getExpressions()); - if (i < n) { - buffer.append(", "); - } - i++; - } - } } 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 eaeaf0a30..e5833c433 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java @@ -50,7 +50,6 @@ import net.sf.jsqlparser.statement.merge.Merge; import net.sf.jsqlparser.statement.merge.MergeInsert; import net.sf.jsqlparser.statement.merge.MergeUpdate; -import net.sf.jsqlparser.statement.replace.Replace; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.statement.show.ShowIndexStatement; @@ -76,8 +75,15 @@ public StatementDeParser(StringBuilder buffer) { public StatementDeParser(ExpressionDeParser expressionDeParser, SelectDeParser selectDeParser, StringBuilder buffer) { super(buffer); + this.expressionDeParser = expressionDeParser; this.selectDeParser = selectDeParser; + + this.selectDeParser.setBuffer(buffer); + this.selectDeParser.setExpressionVisitor(expressionDeParser); + + this.expressionDeParser.setSelectVisitor(selectDeParser); + this.expressionDeParser.setBuffer(buffer); } @Override @@ -106,10 +112,6 @@ public void visit(AlterView alterView) { @Override public void visit(Delete delete) { - selectDeParser.setBuffer(buffer); - expressionDeParser.setSelectVisitor(selectDeParser); - expressionDeParser.setBuffer(buffer); - selectDeParser.setExpressionVisitor(expressionDeParser); DeleteDeParser deleteDeParser = new DeleteDeParser(expressionDeParser, buffer); deleteDeParser.deParse(delete); } @@ -122,32 +124,13 @@ public void visit(Drop drop) { @Override public void visit(Insert insert) { - selectDeParser.setBuffer(buffer); - expressionDeParser.setSelectVisitor(selectDeParser); - expressionDeParser.setBuffer(buffer); - selectDeParser.setExpressionVisitor(expressionDeParser); InsertDeParser insertDeParser = new InsertDeParser(expressionDeParser, selectDeParser, buffer); insertDeParser.deParse(insert); } - @Override - public void visit(Replace replace) { - selectDeParser.setBuffer(buffer); - expressionDeParser.setSelectVisitor(selectDeParser); - expressionDeParser.setBuffer(buffer); - selectDeParser.setExpressionVisitor(expressionDeParser); - ReplaceDeParser replaceDeParser = - new ReplaceDeParser(expressionDeParser, selectDeParser, buffer); - replaceDeParser.deParse(replace); - } - @Override public void visit(Select select) { - selectDeParser.setBuffer(buffer); - expressionDeParser.setSelectVisitor(selectDeParser); - expressionDeParser.setBuffer(buffer); - selectDeParser.setExpressionVisitor(expressionDeParser); select.accept(selectDeParser); } @@ -171,11 +154,7 @@ public void visit(Truncate truncate) { @Override public void visit(Update update) { - selectDeParser.setBuffer(buffer); - expressionDeParser.setSelectVisitor(selectDeParser); - expressionDeParser.setBuffer(buffer); UpdateDeParser updateDeParser = new UpdateDeParser(expressionDeParser, buffer); - selectDeParser.setExpressionVisitor(expressionDeParser); updateDeParser.deParse(update); } @@ -198,80 +177,86 @@ public void visit(Statements stmts) { @Override public void visit(Execute execute) { - selectDeParser.setBuffer(buffer); - expressionDeParser.setSelectVisitor(selectDeParser); - expressionDeParser.setBuffer(buffer); ExecuteDeParser executeDeParser = new ExecuteDeParser(expressionDeParser, buffer); - selectDeParser.setExpressionVisitor(expressionDeParser); executeDeParser.deParse(execute); } @Override public void visit(SetStatement set) { - selectDeParser.setBuffer(buffer); - expressionDeParser.setSelectVisitor(selectDeParser); - expressionDeParser.setBuffer(buffer); SetStatementDeParser setStatementDeparser = new SetStatementDeParser(expressionDeParser, buffer); - selectDeParser.setExpressionVisitor(expressionDeParser); setStatementDeparser.deParse(set); } @Override public void visit(ResetStatement reset) { - selectDeParser.setBuffer(buffer); - expressionDeParser.setSelectVisitor(selectDeParser); - expressionDeParser.setBuffer(buffer); ResetStatementDeParser setStatementDeparser = new ResetStatementDeParser(expressionDeParser, buffer); - selectDeParser.setExpressionVisitor(expressionDeParser); setStatementDeparser.deParse(reset); } @SuppressWarnings({"PMD.CyclomaticComplexity"}) @Override public void visit(Merge merge) { - selectDeParser.setBuffer(buffer); - expressionDeParser.setSelectVisitor(selectDeParser); - expressionDeParser.setBuffer(buffer); - List withItemsList = merge.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { buffer.append("WITH "); for (Iterator iter = withItemsList.iterator(); iter.hasNext();) { - WithItem withItem = iter.next(); - buffer.append(withItem); + iter.next().accept(expressionDeParser); if (iter.hasNext()) { buffer.append(","); } buffer.append(" "); } } + buffer.append("MERGE INTO "); - selectDeParser.visit(merge.getTable()); + merge.getTable().accept(selectDeParser); + buffer.append(" USING "); + merge.getFromItem().accept(selectDeParser); - // @todo - // selectDeParser.visit(merge.getFromItem()); - buffer.append(merge.getFromItem()); buffer.append(" ON ("); - // @todo - // expressionDeParser.visit(merge.getOnCondition()); - buffer.append(merge.getOnCondition()); + merge.getOnCondition().accept(expressionDeParser); buffer.append(")"); MergeInsert mergeInsert = merge.getMergeInsert(); MergeUpdate mergeUpdate = merge.getMergeUpdate(); if (merge.isInsertFirst() && mergeInsert != null) { - buffer.append(mergeInsert); + deparseMergeInsert(mergeInsert); } if (mergeUpdate != null) { - buffer.append(mergeUpdate); + buffer.append(" WHEN MATCHED THEN UPDATE SET "); + deparseUpdateSets(mergeUpdate.getUpdateSets(), buffer, expressionDeParser); + + if (mergeUpdate.getWhereCondition() != null) { + buffer.append(" WHERE "); + mergeUpdate.getWhereCondition().accept(expressionDeParser); + } + + if (mergeUpdate.getDeleteWhereCondition() != null) { + buffer.append(" DELETE WHERE "); + mergeUpdate.getDeleteWhereCondition().accept(expressionDeParser); + } } if (!merge.isInsertFirst() && mergeInsert != null) { - buffer.append(mergeInsert); + deparseMergeInsert(mergeInsert); + } + } + + private void deparseMergeInsert(MergeInsert mergeInsert) { + buffer.append(" WHEN NOT MATCHED THEN INSERT "); + if (mergeInsert.getColumns() != null) { + mergeInsert.getColumns().accept(expressionDeParser); + } + buffer.append(" VALUES "); + mergeInsert.getValues().accept(expressionDeParser); + + if (mergeInsert.getWhereCondition() != null) { + buffer.append(" WHERE "); + mergeInsert.getWhereCondition().accept(expressionDeParser); } } @@ -292,10 +277,6 @@ public void visit(Commit commit) { @Override public void visit(Upsert upsert) { - selectDeParser.setBuffer(buffer); - expressionDeParser.setSelectVisitor(selectDeParser); - expressionDeParser.setBuffer(buffer); - selectDeParser.setExpressionVisitor(expressionDeParser); UpsertDeParser upsertDeParser = new UpsertDeParser(expressionDeParser, selectDeParser, buffer); upsertDeParser.deParse(upsert); @@ -365,7 +346,6 @@ public void visit(ShowStatement show) { @Override public void visit(DeclareStatement declare) { - expressionDeParser.setBuffer(buffer); new DeclareStatementDeParser(expressionDeParser, buffer).deParse(declare); } 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 da32c8f66..4f8affbeb 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java @@ -9,17 +9,15 @@ */ package net.sf.jsqlparser.util.deparser; -import java.util.Iterator; - import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.expression.ExpressionVisitorAdapter; import net.sf.jsqlparser.statement.select.Join; import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.OrderByVisitor; -import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.statement.update.Update; -import net.sf.jsqlparser.statement.update.UpdateSet; + +import java.util.Iterator; public class UpdateDeParser extends AbstractDeParser implements OrderByVisitor { @@ -35,9 +33,10 @@ public UpdateDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) } @Override - @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity", "PMD.ExcessiveMethodLength"}) + @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity", + "PMD.ExcessiveMethodLength"}) public void deParse(Update update) { - if (update.getWithItemsList() != null && !update.getWithItemsList().isEmpty()) { + if (update.getWithItemsList() != null && !update.getWithItemsList().isEmpty()) { buffer.append("WITH "); for (Iterator iter = update.getWithItemsList().iterator(); iter.hasNext();) { WithItem withItem = iter.next(); @@ -67,44 +66,9 @@ public void deParse(Update update) { } buffer.append(" SET "); - int j=0; - for (UpdateSet updateSet:update.getUpdateSets()) { - if (j > 0) { - buffer.append(", "); - } - - if (updateSet.isUsingBracketsForColumns()) { - buffer.append("("); - } - for (int i = 0; i < updateSet.getColumns().size(); i++) { - if (i > 0) { - buffer.append(", "); - } - updateSet.getColumns().get(i).accept(expressionVisitor); - } - 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++; - } + deparseUpdateSets(update.getUpdateSets(), buffer, expressionVisitor); - if (update.getOutputClause()!=null) { + if (update.getOutputClause() != null) { update.getOutputClause().appendTo(buffer); } @@ -129,12 +93,11 @@ public void deParse(Update update) { new OrderByDeParser(expressionVisitor, buffer).deParse(update.getOrderByElements()); } if (update.getLimit() != null) { - new LimitDeparser(buffer).deParse(update.getLimit()); + new LimitDeparser(expressionVisitor, buffer).deParse(update.getLimit()); } - if (update.getReturningExpressionList() != null) { - buffer.append(" RETURNING ").append(PlainSelect. - getStringList(update.getReturningExpressionList(), true, false)); + if (update.getReturningClause() != null) { + update.getReturningClause().appendTo(buffer); } } @@ -156,7 +119,8 @@ public void visit(OrderByElement orderBy) { } if (orderBy.getNullOrdering() != null) { buffer.append(' '); - buffer.append(orderBy.getNullOrdering() == OrderByElement.NullOrdering.NULLS_FIRST ? "NULLS FIRST" + buffer.append(orderBy.getNullOrdering() == OrderByElement.NullOrdering.NULLS_FIRST + ? "NULLS FIRST" : "NULLS LAST"); } } 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 0ebaf8aec..407a4c6e7 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/UpsertDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/UpsertDeParser.java @@ -9,32 +9,23 @@ */ package net.sf.jsqlparser.util.deparser; -import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor; -import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; -import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList; -import net.sf.jsqlparser.schema.Column; -import net.sf.jsqlparser.statement.select.ParenthesedSelect; import net.sf.jsqlparser.statement.select.SelectVisitor; import net.sf.jsqlparser.statement.upsert.Upsert; -import net.sf.jsqlparser.statement.upsert.UpsertType; - -import java.util.Iterator; -import java.util.List; @SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) -public class UpsertDeParser extends AbstractDeParser implements ItemsListVisitor { +public class UpsertDeParser extends AbstractDeParser { - private ExpressionVisitor expressionVisitor; - private SelectVisitor selectVisitor; + private ExpressionDeParser expressionVisitor; + private SelectDeParser selectVisitor; - public UpsertDeParser(ExpressionVisitor expressionVisitor, SelectVisitor selectVisitor, + public UpsertDeParser(ExpressionDeParser expressionVisitor, SelectDeParser selectVisitor, StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; + this.expressionVisitor.setSelectVisitor(selectVisitor); this.selectVisitor = selectVisitor; + this.selectVisitor.setExpressionVisitor(expressionVisitor); } @Override @@ -70,111 +61,30 @@ public void deParse(Upsert upsert) { } buffer.append(upsert.getTable().getFullyQualifiedName()); - if (upsert.getUpsertType() == UpsertType.REPLACE_SET) { - appendReplaceSetClause(upsert); + if (upsert.getUpdateSets() != null) { + buffer.append(" SET "); + deparseUpdateSets(upsert.getUpdateSets(), buffer, expressionVisitor); } else { if (upsert.getColumns() != null) { - appendColumns(upsert); + upsert.getColumns().accept(expressionVisitor); } - if (upsert.getItemsList() != null) { - upsert.getItemsList().accept(this); + if (upsert.getExpressions() != null) { + upsert.getExpressions().accept(expressionVisitor); } if (upsert.getSelect() != null) { - appendSelect(upsert); - } - - if (upsert.isUseDuplicate()) { - appendDuplicate(upsert); - } - } - } - - private void appendReplaceSetClause(Upsert upsert) { - buffer.append(" SET "); - // each element from expressions match up with a column from columns. - List expressions = upsert.getSetExpressions(); - for (int i = 0, s = upsert.getColumns().size(); i < s; i++) { - buffer.append(upsert.getColumns().get(i)).append("=").append(expressions.get(i)); - buffer.append(i < s - 1 ? ", " : ""); - } - } - - private void appendColumns(Upsert upsert) { - buffer.append(" ("); - for (Iterator iter = upsert.getColumns().iterator(); iter.hasNext();) { - Column column = iter.next(); - buffer.append(column.getColumnName()); - if (iter.hasNext()) { - buffer.append(", "); + buffer.append(" "); + upsert.getSelect().accept(selectVisitor); } - } - buffer.append(")"); - } - private void appendSelect(Upsert upsert) { - buffer.append(" "); - upsert.getSelect().accept(selectVisitor); - } - - private void appendDuplicate(Upsert upsert) { - buffer.append(" ON DUPLICATE KEY UPDATE "); - for (int i = 0; i < upsert.getDuplicateUpdateColumns().size(); i++) { - Column column = upsert.getDuplicateUpdateColumns().get(i); - buffer.append(column.getFullyQualifiedName()).append(" = "); - - Expression expression = upsert.getDuplicateUpdateExpressionList().get(i); - expression.accept(expressionVisitor); - if (i < upsert.getDuplicateUpdateColumns().size() - 1) { - buffer.append(", "); + if (upsert.getDuplicateUpdateSets() != null) { + buffer.append(" ON DUPLICATE KEY UPDATE "); + deparseUpdateSets(upsert.getDuplicateUpdateSets(), buffer, expressionVisitor); } } } - @Override - public void visit(ExpressionList expressionList) { - buffer.append(" VALUES ("); - for (Iterator iter = expressionList.getExpressions().iterator(); iter - .hasNext();) { - Expression expression = iter.next(); - expression.accept(expressionVisitor); - if (iter.hasNext()) { - buffer.append(", "); - } - } - buffer.append(")"); - } - - // not used by top-level upsert - @Override - public void visit(NamedExpressionList namedExpressionList) {} - - @Override - public void visit(MultiExpressionList multiExprList) { - buffer.append(" VALUES "); - for (Iterator it = multiExprList.getExprList().iterator(); it.hasNext();) { - buffer.append("("); - for (Iterator iter = it.next().getExpressions().iterator(); iter - .hasNext();) { - Expression expression = iter.next(); - expression.accept(expressionVisitor); - if (iter.hasNext()) { - buffer.append(", "); - } - } - buffer.append(")"); - if (it.hasNext()) { - buffer.append(", "); - } - } - } - - @Override - public void visit(ParenthesedSelect selectBody) { - selectBody.getSelect().accept(selectVisitor); - } - public ExpressionVisitor getExpressionVisitor() { return expressionVisitor; } @@ -183,11 +93,11 @@ public SelectVisitor getSelectVisitor() { return selectVisitor; } - public void setExpressionVisitor(ExpressionVisitor visitor) { + public void setExpressionVisitor(ExpressionDeParser visitor) { expressionVisitor = visitor; } - public void setSelectVisitor(SelectVisitor visitor) { + public void setSelectVisitor(SelectDeParser visitor) { selectVisitor = visitor; } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ValuesStatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ValuesStatementDeParser.java index 8ec63f6dd..233ec71c3 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ValuesStatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ValuesStatementDeParser.java @@ -9,14 +9,14 @@ */ package net.sf.jsqlparser.util.deparser; -import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor; +import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.statement.select.Values; public class ValuesStatementDeParser extends AbstractDeParser { - private final ItemsListVisitor expressionVisitor; + private final ExpressionVisitor expressionVisitor; - public ValuesStatementDeParser(ItemsListVisitor expressionVisitor, StringBuilder buffer) { + public ValuesStatementDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/ParseCapability.java b/src/main/java/net/sf/jsqlparser/util/validation/ParseCapability.java index 606c19126..b0cf02ff0 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/ParseCapability.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/ParseCapability.java @@ -9,14 +9,16 @@ */ package net.sf.jsqlparser.util.validation; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.function.Consumer; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.statement.Statements; /** - * package - private class for {@link Validation} to parse the statements - * within it's own {@link ValidationCapability} + * package - private class for {@link Validation} to parse the statements within it's own + * {@link ValidationCapability} * * @author gitmotte */ @@ -36,8 +38,7 @@ public String getStatements() { } /** - * @return null on parse error, otherwise the {@link Statements} - * parsed. + * @return null on parse error, otherwise the {@link Statements} parsed. */ public Statements getParsedStatements() { return parsedStatement; @@ -45,11 +46,17 @@ public Statements getParsedStatements() { @Override public void validate(ValidationContext context, Consumer errorConsumer) { + ExecutorService executorService = Executors.newSingleThreadExecutor(); try { this.parsedStatement = CCJSqlParserUtil.parseStatements( - CCJSqlParserUtil.newParser(statements).withConfiguration(context.getConfiguration())); + CCJSqlParserUtil.newParser(statements) + .withConfiguration(context.getConfiguration()), + executorService); } catch (JSQLParserException e) { - errorConsumer.accept(new ParseException("Cannot parse statement: " + e.getMessage(), e)); + errorConsumer + .accept(new ParseException("Cannot parse statement: " + e.getMessage(), e)); + } finally { + executorService.shutdown(); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/AbstractValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/AbstractValidator.java index b212cf84b..5eefdd1e4 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/AbstractValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/AbstractValidator.java @@ -10,9 +10,6 @@ package net.sf.jsqlparser.util.validation.validator; import net.sf.jsqlparser.expression.Expression; -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.expression.operators.relational.ItemsList; -import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; import net.sf.jsqlparser.parser.feature.Feature; import net.sf.jsqlparser.statement.select.FromItem; import net.sf.jsqlparser.statement.select.OrderByElement; @@ -134,17 +131,6 @@ protected > void validateOptionalList(List elementL } } - /** - * a multi-expression in clause: {@code ((a, b), (c, d))} - */ - protected void validateOptionalMultiExpressionList(MultiExpressionList multiExprList) { - if (multiExprList != null) { - ExpressionValidator v = getValidator(ExpressionValidator.class); - multiExprList.getExpressionLists().stream().map(ExpressionList::getExpressions) - .flatMap(List::stream).forEach(e -> e.accept(v)); - } - } - protected void validateOptionalExpression(Expression expression) { validateOptional(expression, e -> e.accept(getValidator(ExpressionValidator.class))); } @@ -180,10 +166,6 @@ protected void validateOptionalFromItem(FromItem fromItem, SelectValidator v) { validateOptional(fromItem, i -> i.accept(v)); } - protected void validateOptionalItemsList(ItemsList itemsList) { - validateOptional(itemsList, i -> i.accept(getValidator(ItemsListValidator.class))); - } - /** * Iterates through all {@link ValidationCapability} and validates the feature with * {@link #validateFeature(ValidationCapability, Feature)} diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/DeleteValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/DeleteValidator.java index 564278dfe..3de5343c4 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/DeleteValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/DeleteValidator.java @@ -28,7 +28,8 @@ public void validate(Delete delete) { validateOptionalFeature(c, delete.getJoins(), Feature.deleteJoin); validateOptionalFeature(c, delete.getLimit(), Feature.deleteLimit); validateOptionalFeature(c, delete.getOrderByElements(), Feature.deleteOrderBy); - validateOptionalFeature(c, delete.getReturningExpressionList(), Feature.deleteReturningExpressionList); + validateOptionalFeature(c, delete.getReturningClause(), + Feature.deleteReturningExpressionList); } SelectValidator v = getValidator(SelectValidator.class); @@ -47,8 +48,8 @@ public void validate(Delete delete) { getValidator(LimitValidator.class).validate(delete.getLimit()); } - if (isNotEmpty(delete.getReturningExpressionList())) { - delete.getReturningExpressionList().forEach(c -> c .accept(v)); + if (delete.getReturningClause() != null) { + delete.getReturningClause().forEach(c -> c.accept(v)); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/ExecuteValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/ExecuteValidator.java index 128b1c56c..3c91b9128 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/ExecuteValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/ExecuteValidator.java @@ -25,13 +25,14 @@ public class ExecuteValidator extends AbstractValidator { public void validate(Execute execute) { for (ValidationCapability c : getCapabilities()) { validateFeature(c, Feature.execute); - validateFeature(c, ExecType.EXECUTE.equals(execute.getExecType()), Feature.executeExecute); + validateFeature(c, ExecType.EXECUTE.equals(execute.getExecType()), + Feature.executeExecute); validateFeature(c, ExecType.EXEC.equals(execute.getExecType()), Feature.executeExec); validateFeature(c, ExecType.CALL.equals(execute.getExecType()), Feature.executeCall); validateName(NamedObject.procedure, execute.getName()); } - validateOptionalItemsList(execute.getExprList()); + validateOptionalExpression(execute.getExprList()); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java index cd540d073..fb03eeba3 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java @@ -9,7 +9,60 @@ */ package net.sf.jsqlparser.util.validation.validator; -import net.sf.jsqlparser.expression.*; +import net.sf.jsqlparser.expression.AllValue; +import net.sf.jsqlparser.expression.AnalyticExpression; +import net.sf.jsqlparser.expression.AnyComparisonExpression; +import net.sf.jsqlparser.expression.ArrayConstructor; +import net.sf.jsqlparser.expression.ArrayExpression; +import net.sf.jsqlparser.expression.BinaryExpression; +import net.sf.jsqlparser.expression.CaseExpression; +import net.sf.jsqlparser.expression.CastExpression; +import net.sf.jsqlparser.expression.CollateExpression; +import net.sf.jsqlparser.expression.ConnectByRootOperator; +import net.sf.jsqlparser.expression.DateTimeLiteralExpression; +import net.sf.jsqlparser.expression.DateValue; +import net.sf.jsqlparser.expression.DoubleValue; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.ExpressionVisitor; +import net.sf.jsqlparser.expression.ExtractExpression; +import net.sf.jsqlparser.expression.Function; +import net.sf.jsqlparser.expression.HexValue; +import net.sf.jsqlparser.expression.IntervalExpression; +import net.sf.jsqlparser.expression.JdbcNamedParameter; +import net.sf.jsqlparser.expression.JdbcParameter; +import net.sf.jsqlparser.expression.JsonAggregateFunction; +import net.sf.jsqlparser.expression.JsonExpression; +import net.sf.jsqlparser.expression.JsonFunction; +import net.sf.jsqlparser.expression.KeepExpression; +import net.sf.jsqlparser.expression.LongValue; +import net.sf.jsqlparser.expression.MySQLGroupConcat; +import net.sf.jsqlparser.expression.NextValExpression; +import net.sf.jsqlparser.expression.NotExpression; +import net.sf.jsqlparser.expression.NullValue; +import net.sf.jsqlparser.expression.NumericBind; +import net.sf.jsqlparser.expression.OracleHierarchicalExpression; +import net.sf.jsqlparser.expression.OracleHint; +import net.sf.jsqlparser.expression.OracleNamedFunctionParameter; +import net.sf.jsqlparser.expression.OverlapsCondition; +import net.sf.jsqlparser.expression.Parenthesis; +import net.sf.jsqlparser.expression.RangeExpression; +import net.sf.jsqlparser.expression.RowConstructor; +import net.sf.jsqlparser.expression.RowGetExpression; +import net.sf.jsqlparser.expression.SignedExpression; +import net.sf.jsqlparser.expression.StringValue; +import net.sf.jsqlparser.expression.TimeKeyExpression; +import net.sf.jsqlparser.expression.TimeValue; +import net.sf.jsqlparser.expression.TimestampValue; +import net.sf.jsqlparser.expression.TimezoneExpression; +import net.sf.jsqlparser.expression.TranscodingFunction; +import net.sf.jsqlparser.expression.TrimFunction; +import net.sf.jsqlparser.expression.UserVariable; +import net.sf.jsqlparser.expression.VariableAssignment; +import net.sf.jsqlparser.expression.WhenClause; +import net.sf.jsqlparser.expression.WindowElement; +import net.sf.jsqlparser.expression.WindowOffset; +import net.sf.jsqlparser.expression.WindowRange; +import net.sf.jsqlparser.expression.XMLSerializeExpr; import net.sf.jsqlparser.expression.operators.arithmetic.Addition; import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd; import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift; @@ -35,10 +88,12 @@ import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals; import net.sf.jsqlparser.expression.operators.relational.InExpression; import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression; +import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression; import net.sf.jsqlparser.expression.operators.relational.IsNullExpression; import net.sf.jsqlparser.expression.operators.relational.JsonOperator; import net.sf.jsqlparser.expression.operators.relational.LikeExpression; import net.sf.jsqlparser.expression.operators.relational.Matches; +import net.sf.jsqlparser.expression.operators.relational.MemberOfExpression; import net.sf.jsqlparser.expression.operators.relational.MinorThan; import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals; import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo; @@ -46,11 +101,9 @@ import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator; import net.sf.jsqlparser.expression.operators.relational.RegExpMySQLOperator; import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression; -import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression; import net.sf.jsqlparser.expression.operators.relational.SupportsOldOracleJoinSyntax; import net.sf.jsqlparser.parser.feature.Feature; import net.sf.jsqlparser.schema.Column; -import net.sf.jsqlparser.statement.create.table.ColumnDefinition; import net.sf.jsqlparser.statement.select.AllColumns; import net.sf.jsqlparser.statement.select.AllTableColumns; import net.sf.jsqlparser.statement.select.ParenthesedSelect; @@ -164,7 +217,6 @@ public void visit(InExpression inExpression) { } } validateOptionalExpression(inExpression.getRightExpression(), this); - validateOptionalItemsList(inExpression.getRightItemsList()); } @Override @@ -204,6 +256,12 @@ public void visit(ExistsExpression existsExpression) { existsExpression.getRightExpression().accept(this); } + @Override + public void visit(MemberOfExpression memberOfExpression) { + memberOfExpression.getLeftExpression().accept(this); + memberOfExpression.getRightExpression().accept(this); + } + @Override public void visit(LongValue longValue) { // nothing to validate @@ -284,8 +342,8 @@ public void visit(Column tableColumn) { public void visit(Function function) { validateFeature(Feature.function); - validateOptionalItemsList(function.getNamedParameters()); - validateOptionalItemsList(function.getParameters()); + validateOptionalExpressionList(function.getNamedParameters()); + validateOptionalExpressionList(function.getParameters()); Object attribute = function.getAttribute(); if (attribute instanceof Expression) { @@ -334,7 +392,7 @@ public void visit(WhenClause whenClause) { @Override public void visit(AnyComparisonExpression anyComparisonExpression) { - anyComparisonExpression.getSubSelect().accept(this); + anyComparisonExpression.getSelect().accept(this); } @Override @@ -367,17 +425,6 @@ public void visit(CastExpression cast) { cast.getLeftExpression().accept(this); } - @Override - public void visit(TryCastExpression cast) { - cast.getLeftExpression().accept(this); - } - - @Override - public void visit(SafeCastExpression cast) { - cast.getLeftExpression().accept(this); - - } - @Override public void visit(Modulo modulo) { visitBinaryExpression(modulo, " % "); @@ -470,26 +517,22 @@ public void visit(MySQLGroupConcat groupConcat) { validateOptionalOrderByElements(groupConcat.getOrderByElements()); } - private void validateOptionalExpressionList(ExpressionList expressionList) { + private void validateOptionalExpressionList(ExpressionList expressionList) { if (expressionList != null) { - expressionList.accept(getValidator(ItemsListValidator.class)); + for (Expression expression : expressionList) { + expression.accept(this); + } } } @Override - public void visit(ValueListExpression valueList) { - validateOptionalExpressionList(valueList.getExpressionList()); + public void visit(ExpressionList expressionList) { + validateOptionalExpressionList(expressionList); } @Override public void visit(RowConstructor rowConstructor) { - if (rowConstructor.getColumnDefinitions().isEmpty()) { - validateOptionalExpressionList(rowConstructor.getExprList()); - } else { - for (ColumnDefinition columnDefinition : rowConstructor.getColumnDefinitions()) { - validateName(NamedObject.column, columnDefinition.getColumnName()); - } - } + validateOptionalExpressionList(rowConstructor); } @Override @@ -618,4 +661,25 @@ public void visit(GeometryDistance geometryDistance) { public void visit(Select selectBody) { } + + @Override + public void visit(TranscodingFunction transcodingFunction) { + transcodingFunction.getExpression().accept(this); + } + + @Override + public void visit(TrimFunction trimFunction) { + if (trimFunction.getExpression() != null) { + trimFunction.getExpression().accept(this); + } + if (trimFunction.getFromExpression() != null) { + trimFunction.getFromExpression().accept(this); + } + } + + @Override + public void visit(RangeExpression rangeExpression) { + rangeExpression.getStartExpression().accept(this); + rangeExpression.getEndExpression().accept(this); + } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/InsertValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/InsertValidator.java index 59fb966fe..be09f314c 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/InsertValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/InsertValidator.java @@ -11,6 +11,8 @@ import net.sf.jsqlparser.parser.feature.Feature; import net.sf.jsqlparser.statement.insert.Insert; +import net.sf.jsqlparser.statement.select.Values; +import net.sf.jsqlparser.statement.update.UpdateSet; import net.sf.jsqlparser.util.validation.ValidationCapability; /** @@ -23,44 +25,55 @@ public class InsertValidator extends AbstractValidator { public void validate(Insert insert) { for (ValidationCapability c : getCapabilities()) { validateFeature(c, Feature.insert); - validateOptionalFeature(c, insert.getItemsList(), Feature.insertValues); - validateOptionalFeature(c, insert.getModifierPriority(), Feature.insertModifierPriority); + + if (insert.getSelect() instanceof Values) { + validateOptionalFeature(c, insert.getSelect().as(Values.class), + Feature.insertValues); + } + + validateOptionalFeature(c, insert.getModifierPriority(), + Feature.insertModifierPriority); validateFeature(c, insert.isModifierIgnore(), Feature.insertModifierIgnore); validateOptionalFeature(c, insert.getSelect(), Feature.insertFromSelect); validateFeature(c, insert.isUseSet(), Feature.insertUseSet); validateFeature(c, insert.isUseDuplicate(), Feature.insertUseDuplicateKeyUpdate); - validateOptionalFeature(c, insert.getReturningExpressionList(), Feature.insertReturningExpressionList); + validateOptionalFeature(c, insert.getReturningClause(), + Feature.insertReturningExpressionList); } validateOptionalFromItem(insert.getTable()); validateOptionalExpressions(insert.getColumns()); - validateOptionalItemsList(insert.getItemsList()); - if (insert.getSelect() != null) { + if (insert.getSelect() instanceof Values) { insert.getSelect().accept(getValidator(StatementValidator.class)); + validateOptionalExpressions(insert.getValues().getExpressions()); } - if (insert.isUseSet()) { + if (insert.getSetUpdateSets() != null) { ExpressionValidator v = getValidator(ExpressionValidator.class); // TODO is this useful? // validateModelCondition (insert.getSetColumns().size() != // insert.getSetExpressionList().size(), "model-error"); - insert.getSetColumns().forEach(c -> c.accept(v)); - insert.getSetExpressionList().forEach(c -> c.accept(v)); + for (UpdateSet updateSet : insert.getSetUpdateSets()) { + updateSet.getColumns().forEach(c -> c.accept(v)); + updateSet.getValues().forEach(c -> c.accept(v)); + } } - if (insert.isUseDuplicate()) { + if (insert.getDuplicateUpdateSets() != null) { ExpressionValidator v = getValidator(ExpressionValidator.class); // TODO is this useful? - // validateModelCondition (insert.getDuplicateUpdateColumns().size() != - // insert.getDuplicateUpdateExpressionList().size(), "model-error"); - insert.getDuplicateUpdateColumns().forEach(c -> c.accept(v)); - insert.getDuplicateUpdateExpressionList().forEach(c -> c.accept(v)); + // validateModelCondition (insert.getSetColumns().size() != + // insert.getSetExpressionList().size(), "model-error"); + for (UpdateSet updateSet : insert.getDuplicateUpdateSets()) { + updateSet.getColumns().forEach(c -> c.accept(v)); + updateSet.getValues().forEach(c -> c.accept(v)); + } } - if (isNotEmpty(insert.getReturningExpressionList())) { + if (insert.getReturningClause() != null) { SelectValidator v = getValidator(SelectValidator.class); - insert.getReturningExpressionList().forEach(c -> c .accept(v)); + insert.getReturningClause().forEach(c -> c.accept(v)); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/ItemsListValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/ItemsListValidator.java deleted file mode 100644 index 22c5f2095..000000000 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/ItemsListValidator.java +++ /dev/null @@ -1,49 +0,0 @@ -/*- - * #%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.util.validation.validator; - -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.expression.operators.relational.ItemsList; -import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor; -import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; -import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList; -import net.sf.jsqlparser.statement.select.ParenthesedSelect; - -/** - * @author gitmotte - */ -public class ItemsListValidator extends AbstractValidator implements ItemsListVisitor { - - @Override - public void visit(ParenthesedSelect selectBody) { - validateOptionalFromItem(selectBody); - } - - @Override - public void visit(ExpressionList expressionList) { - validateOptionalExpressions(expressionList.getExpressions()); - } - - @Override - public void visit(NamedExpressionList namedExpressionList) { - validateOptionalExpressions(namedExpressionList.getExpressions()); - } - - @Override - public void visit(MultiExpressionList multiExprList) { - multiExprList.getExpressionLists().forEach(l -> l.accept(this)); - } - - @Override - public void validate(ItemsList statement) { - statement.accept(this); - } - -} diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/MergeValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/MergeValidator.java index f7b6e1e06..0b2dd5711 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/MergeValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/MergeValidator.java @@ -11,6 +11,7 @@ import net.sf.jsqlparser.parser.feature.Feature; import net.sf.jsqlparser.statement.merge.Merge; +import net.sf.jsqlparser.statement.update.UpdateSet; import net.sf.jsqlparser.util.validation.ValidationCapability; /** @@ -31,13 +32,14 @@ public void validate(Merge merge) { validateOptionalExpressions(merge.getMergeInsert().getValues()); } if (merge.getMergeUpdate() != null) { - validateOptionalExpressions(merge.getMergeUpdate().getColumns()); - validateOptionalExpressions(merge.getMergeUpdate().getValues()); + for (UpdateSet updateSet : merge.getMergeUpdate().getUpdateSets()) { + validateOptionalExpressions(updateSet.getColumns()); + validateOptionalExpressions(updateSet.getValues()); + } validateOptionalExpression(merge.getMergeUpdate().getDeleteWhereCondition()); validateOptionalExpression(merge.getMergeUpdate().getWhereCondition()); } - // validateOptionalFromItems(merge.getTable(), merge.getUsingTable(), - // merge.getUsingSelect()); + validateOptionalFromItems(merge.getFromItem()); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/SelectValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/SelectValidator.java index 4b611c350..31349aa4f 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/SelectValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/SelectValidator.java @@ -14,8 +14,6 @@ import net.sf.jsqlparser.expression.SQLServerHints; import net.sf.jsqlparser.parser.feature.Feature; import net.sf.jsqlparser.schema.Table; -import net.sf.jsqlparser.statement.select.AllColumns; -import net.sf.jsqlparser.statement.select.AllTableColumns; import net.sf.jsqlparser.statement.select.ExceptOp; import net.sf.jsqlparser.statement.select.Fetch; import net.sf.jsqlparser.statement.select.FromItemVisitor; @@ -30,7 +28,6 @@ import net.sf.jsqlparser.statement.select.PivotVisitor; import net.sf.jsqlparser.statement.select.PivotXml; import net.sf.jsqlparser.statement.select.PlainSelect; -import net.sf.jsqlparser.statement.select.SelectExpressionItem; import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.SelectItemVisitor; import net.sf.jsqlparser.statement.select.SelectVisitor; @@ -38,8 +35,8 @@ import net.sf.jsqlparser.statement.select.TableFunction; import net.sf.jsqlparser.statement.select.UnPivot; import net.sf.jsqlparser.statement.select.UnionOp; -import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.statement.select.Values; +import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.util.validation.ValidationCapability; import net.sf.jsqlparser.util.validation.ValidationUtil; import net.sf.jsqlparser.util.validation.metadata.NamedObject; @@ -133,18 +130,7 @@ public void visit(PlainSelect plainSelect) { } @Override - public void visit(AllTableColumns allTableColumns) { - // nothing to validate - allTableColumns.getTable() will be validated with from - // clause - } - - @Override - public void visit(AllColumns allColumns) { - // nothing to validate - } - - @Override - public void visit(SelectExpressionItem selectExpressionItem) { + public void visit(SelectItem selectExpressionItem) { selectExpressionItem.getExpression().accept(getValidator(ExpressionValidator.class)); } @@ -196,7 +182,7 @@ public void visit(PivotXml pivot) { validateOptionalExpressions(pivot.getForColumns()); if (isNotEmpty(pivot.getFunctionItems())) { ExpressionValidator v = getValidator(ExpressionValidator.class); - pivot.getFunctionItems().forEach(f -> f.getFunction().accept(v)); + pivot.getFunctionItems().forEach(f -> f.getExpression().accept(v)); } if (pivot.getInSelect() != null) { pivot.getInSelect().accept(this); @@ -342,5 +328,4 @@ public void visit(Values values) { public void validate(SelectItem statement) { statement.accept(this); } - } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/StatementValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/StatementValidator.java index 9364cfa17..4bc3744b7 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/StatementValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/StatementValidator.java @@ -51,7 +51,6 @@ import net.sf.jsqlparser.statement.grant.Grant; import net.sf.jsqlparser.statement.insert.Insert; import net.sf.jsqlparser.statement.merge.Merge; -import net.sf.jsqlparser.statement.replace.Replace; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.show.ShowIndexStatement; import net.sf.jsqlparser.statement.show.ShowTablesStatement; @@ -101,11 +100,6 @@ public void visit(Insert insert) { getValidator(InsertValidator.class).validate(insert); } - @Override - public void visit(Replace replace) { - getValidator(ReplaceValidator.class).validate(replace); - } - @Override public void visit(Select select) { validateFeature(Feature.select); diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/UpdateValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/UpdateValidator.java index 052dfd6d1..735725126 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/UpdateValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/UpdateValidator.java @@ -28,7 +28,7 @@ public void validate(Update update) { validateFeature(c, update.isUseSelect(), Feature.updateUseSelect); validateOptionalFeature(c, update.getOrderByElements(), Feature.updateOrderBy); validateOptionalFeature(c, update.getLimit(), Feature.updateLimit); - validateOptionalFeature(c, update.getReturningExpressionList(), + validateOptionalFeature(c, update.getReturningClause(), Feature.updateReturning); } @@ -59,9 +59,9 @@ public void validate(Update update) { getValidator(LimitValidator.class).validate(update.getLimit()); } - if (isNotEmpty(update.getReturningExpressionList())) { + if (update.getReturningClause() != null) { SelectValidator v = getValidator(SelectValidator.class); - update.getReturningExpressionList().forEach(c -> c.accept(v)); + update.getReturningClause().forEach(c -> c.accept(v)); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/UpsertValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/UpsertValidator.java index 3ec620f2c..21e9ebeeb 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/UpsertValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/UpsertValidator.java @@ -11,6 +11,7 @@ import net.sf.jsqlparser.parser.feature.Feature; import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.statement.update.UpdateSet; import net.sf.jsqlparser.statement.upsert.Upsert; import net.sf.jsqlparser.util.validation.ValidationCapability; @@ -26,11 +27,9 @@ public void validate(Upsert upsert) { } validateOptionalFromItem(upsert.getTable()); validateOptionalExpressions(upsert.getColumns()); - validateOptionalItemsList(upsert.getItemsList()); + validateOptionalExpressions(upsert.getExpressions()); validateOptionalSelect(upsert.getSelect()); - if (upsert.isUseDuplicate()) { - validateDuplicate(upsert); - } + validateDuplicate(upsert); } private void validateOptionalSelect(Select select) { @@ -41,8 +40,12 @@ private void validateOptionalSelect(Select select) { } private void validateDuplicate(Upsert upsert) { - validateOptionalExpressions(upsert.getDuplicateUpdateColumns()); - validateOptionalExpressions(upsert.getDuplicateUpdateExpressionList()); + if (upsert.getDuplicateUpdateSets() != null) { + for (UpdateSet updateSet : upsert.getDuplicateUpdateSets()) { + validateOptionalExpressions(updateSet.getColumns()); + validateOptionalExpressions(updateSet.getValues()); + } + } } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/ValuesStatementValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/ValuesStatementValidator.java index 72b51fc96..79643c889 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/ValuesStatementValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/ValuesStatementValidator.java @@ -20,6 +20,6 @@ public class ValuesStatementValidator extends AbstractValidator { @Override public void validate(Values values) { validateFeature(Feature.values); - validateOptionalItemsList(values.getExpressions()); + validateOptionalExpression(values.getExpressions()); } } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 472a0c2aa..a346a0604 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -57,7 +57,6 @@ import net.sf.jsqlparser.statement.create.view.*; import net.sf.jsqlparser.statement.delete.*; import net.sf.jsqlparser.statement.drop.*; import net.sf.jsqlparser.statement.insert.*; -import net.sf.jsqlparser.statement.replace.*; import net.sf.jsqlparser.statement.execute.*; import net.sf.jsqlparser.statement.select.*; import net.sf.jsqlparser.statement.show.*; @@ -181,6 +180,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -204,6 +204,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -224,6 +225,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -288,6 +290,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -295,7 +298,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | -| +| | | | @@ -389,7 +392,8 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | -| +| +| | | | @@ -399,6 +403,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | ("CURRENT" ( "_" | (" ")+ ) "DATE") ) ( "()" )?> | +| | | | @@ -549,7 +554,7 @@ TOKEN: input_stream.backup(image.length() - matchedToken.image.length() ); } } -| < S_QUOTED_IDENTIFIER: "\"" (~["\n","\r","\""])* "\"" | "$$" (~["\n","\r","\""])* "$$" | ("`" (~["\n","\r","`"])+ "`") | ( "[" (~["\n","\r","]"])* "]" ) > +| < S_QUOTED_IDENTIFIER: "\"" ( "\"\"" | ~["\n","\r","\""])* "\"" | "$$" (~["$"])* "$$" | ("`" (~["\n","\r","`"])+ "`") | ( "[" (~["\n","\r","]"])* "]" ) > { if ( !configuration.getAsBoolean(Feature.allowSquareBracketQuotation) && matchedToken.image.charAt(0) == '[' ) { matchedToken.image = "["; @@ -632,38 +637,12 @@ Statement SingleStatement() : | LOOKAHEAD(3) stm = Upsert() | - LOOKAHEAD(2) - stm = AlterTable() - | - LOOKAHEAD(2) - stm = AlterSession() - | - LOOKAHEAD(CreateFunctionStatement()) - stm = CreateFunctionStatement() - | - LOOKAHEAD(CreateIndex()) - stm = CreateIndex() - | - LOOKAHEAD(CreateSchema()) - stm = CreateSchema() - | - LOOKAHEAD(CreateSequence()) - stm = CreateSequence() - | - LOOKAHEAD(CreateSynonym()) - stm = CreateSynonym() + LOOKAHEAD(2) stm = Alter() | - LOOKAHEAD(CreateTable()) - stm = CreateTable() - | - LOOKAHEAD(CreateView()) - stm = CreateView() - | - LOOKAHEAD(AlterView()) - stm = AlterView() + // @todo: merge this into the ALTER TABLE statement + stm = RenameTableStatement() | - LOOKAHEAD(AlterSequence()) - stm = AlterSequence() + stm = Create() | stm = Drop() | @@ -675,19 +654,8 @@ Statement SingleStatement() : | stm = Set() | - stm = RenameTableStatement() - | stm = Reset() | - LOOKAHEAD(ShowColumns()) - stm = ShowColumns() - | - LOOKAHEAD(ShowIndex()) - stm = ShowIndex() - | - LOOKAHEAD(ShowTables()) - stm = ShowTables() - | stm = Show() | stm = Use() @@ -709,8 +677,6 @@ Statement SingleStatement() : stm = Grant() | stm = PurgeStatement() - | - stm = AlterSystemStatement() ) { return stm; } } catch (ParseException e) { @@ -734,13 +700,11 @@ Block Block() #Block : { ()* try { ( - ( - stm = SingleStatement() - | stm = Block() - ) - - { list.add(stm); } + stm = SingleStatement() + | stm = Block() ) + + { list.add(stm); } ( ( @@ -772,10 +736,8 @@ Block Block() #Block : { } } -Statements Statements() #Statements : { +Statements Statements() #Statements: { Statements stmts = new Statements(); - List list = new ArrayList(); - IfElseStatement ifElseStatement = null; Statement stm = null; Statement stm2 = null; @@ -793,7 +755,7 @@ Statements Statements() #Statements : { ( stm2 = SingleStatement() | stm2 = Block() ) { ifElseStatement.setElseStatement(stm2); } ] - { list.add( ifElseStatement ); } + { stmts.add( ifElseStatement ); } ) | ( @@ -801,10 +763,10 @@ Statements Statements() #Statements : { | stm = Block() [ LOOKAHEAD(2) ] - ) { list.add(stm); } + ) { stmts.add(stm); } | LOOKAHEAD( { getAsBoolean(Feature.allowUnsupportedStatements) } ) stm = UnsupportedStatement() - { if ( !((UnsupportedStatement) stm).isEmpty() ) list.add(stm); } + { if ( !((UnsupportedStatement) stm).isEmpty() ) stmts.add(stm); } ) ( @@ -821,7 +783,7 @@ Statements Statements() #Statements : { ( stm2 = SingleStatement() | stm2 = Block() ) { ifElseStatement.setElseStatement(stm2); } ] - { list.add( ifElseStatement ); } + { stmts.add( ifElseStatement ); } ) | ( @@ -829,12 +791,12 @@ Statements Statements() #Statements : { | stm = Block() [ LOOKAHEAD(2) ] - ) { list.add(stm); } + ) { stmts.add(stm); } | // For any reason, we can't LOOKAHEAD( { getAsBoolean(Feature.allowUnsupportedStatements) } ) here // As it will result in a Stack Overflow stm = UnsupportedStatement() - { if ( !((UnsupportedStatement) stm).isEmpty() ) list.add(stm); } + { if ( !((UnsupportedStatement) stm).isEmpty() ) stmts.add(stm); } ] )* @@ -847,7 +809,7 @@ Statements Statements() #Statements : { } } { - return stmts.withStatements(list); + return stmts; } } @@ -904,8 +866,9 @@ DeclareStatement Declare(): { SetStatement Set(): { + String namePart; Object name; - ArrayList expList; + ExpressionList expList; boolean useEqual = false; SetStatement set; Expression exp = null; @@ -914,35 +877,50 @@ SetStatement Set(): { } { + [LOOKAHEAD(3) (tk = | tk = ) {effectParameter = tk.image; } ] ( - - [LOOKAHEAD(3) (tk = | tk = ) {effectParameter = tk.image; } ] - ( LOOKAHEAD(2) - { name = "Time Zone"; useEqual=false; } - | (name = UserVariable() ["=" { useEqual=true; } ]) - | (name = RelObjectNameExt() ["=" { useEqual=true; } ]) + LOOKAHEAD(2) + { name = "Time Zone"; useEqual=false; } + | + ( + name = UserVariable() ["=" { useEqual=true; } ] + ) + | + ( + name = IdentifierChain() + ["=" { useEqual=true; } ] ) ) exp=Expression() - {expList = new ArrayList(); expList.add(exp); } + { + expList = new ExpressionList(); + expList.add(exp); + set = new SetStatement(name, expList) + .withUseEqual(useEqual) + .withEffectParameter(effectParameter); + } - { set = new SetStatement(name,expList).withUseEqual(useEqual).withEffectParameter(effectParameter); } ( { useEqual=false; } "," (LOOKAHEAD(3) ( - ( LOOKAHEAD(2) - { name = "Time Zone"; useEqual=false; } - | (name = RelObjectNameExt() ["=" { useEqual=true; } ]) - ) - exp=Expression() - {expList = new ArrayList(); - expList.add(exp); - set.add(name, expList, useEqual);} + ( LOOKAHEAD(2) + { name = "Time Zone"; useEqual=false; } + | + (name = RelObjectNameExt() ["=" { useEqual=true; } ]) + ) + exp=Expression() + { + expList = new ExpressionList(); + expList.add(exp); + set.add(name, expList, useEqual); + } ) - | exp=Expression() { expList.add(exp); } - ))* + | + exp=Expression() { expList.add(exp); } + ) + )* { return set; } } @@ -953,8 +931,7 @@ ResetStatement Reset(): { } { ( LOOKAHEAD(2) {name = "Time Zone"; } | name = RelObjectName() | all = {name = all.image; } ) - { reset = new ResetStatement(name); } - { return reset; } + { reset = new ResetStatement(name); return reset; } } RenameTableStatement RenameTableStatement(): { @@ -1154,11 +1131,40 @@ UseStatement Use(): { } } +Statement Show(): +{ + Statement statement; + List captureRest; +} +{ + + ( + LOOKAHEAD(2) statement = ShowColumns() + | + LOOKAHEAD(2) statement = ShowIndex() + | + LOOKAHEAD(2) statement = ShowTables() + | + // any of the RDBMS specific SHOW syntax + captureRest = captureRest() + { + if (captureRest.size()==1) { + statement = new ShowStatement(captureRest.get(0)); + } else { + statement = new UnsupportedStatement("SHOW", captureRest); + } + } + ) + { + return statement; + } +} + ShowColumnsStatement ShowColumns(): { String tableName; } { - tableName = RelObjectNameExt() + tableName = RelObjectNameExt() { return new ShowColumnsStatement(tableName); } @@ -1168,7 +1174,7 @@ ShowIndexStatement ShowIndex(): { String tableName; } { - tableName = RelObjectNameExt() + tableName = RelObjectNameExt() { return new ShowIndexStatement(tableName); } @@ -1184,7 +1190,6 @@ ShowTablesStatement ShowTables(): { Expression whereCondition = null; } { - [ { modifiers.add(ShowTablesStatement.Modifiers.EXTENDED); } ] [ { modifiers.add(ShowTablesStatement.Modifiers.FULL); } ] @@ -1207,25 +1212,41 @@ ShowTablesStatement ShowTables(): { } } -ShowStatement Show(): { - String name; -} -{ - name = RelObjectNameExt() +Values Values(): { + ExpressionList expressions; +} { + ( | ) + expressions = ExpressionList() + { - return new ShowStatement(name); + return new Values(expressions); } } -Values Values(): { - ItemsList itemsList; -} { - ( | ) +ReturningClause ReturningClause(): +{ + Token keyword; + List> selectItems; + Object dataItem; + List dataItems = null; +} +{ + ( keyword= | keyword="RETURN" ) + selectItems = SelectItemsList() + + [ + + ( dataItem = Table() | dataItem = UserVariable() ) + { dataItems = new ArrayList(); dataItems.add(dataItem); } - itemsList = SimpleExpressionList(false) + ( + "," + ( dataItem = Table() | dataItem = UserVariable() ) { dataItems.add(dataItem); } + )* + ] { - return new Values(itemsList); + return new ReturningClause(keyword.image, selectItems, dataItems); } } @@ -1235,18 +1256,14 @@ Update Update( List with ): Table table = null; List startJoins = null; - UpdateSet updateSet = null; - Column tableColumn = null; - ParenthesedSelect subSelect; - Expression valueExpression = null; - ExpressionList expressionList; + List updateSets; Expression where = null; FromItem fromItem = null; List joins = null; Limit limit = null; List orderByElements; boolean useColumnsBrackets = false; - List returning = null; + ReturningClause returningClause; Token tk = null; UpdateModifierPriority modifierPriority = null; boolean modifierIgnore = false; @@ -1258,49 +1275,7 @@ Update Update( List with ): [ LOOKAHEAD(2) { modifierPriority = UpdateModifierPriority.LOW_PRIORITY; }] [ LOOKAHEAD(2) { modifierIgnore = true; }] table=TableWithAlias() [ startJoins=JoinsList() ] - - ( - LOOKAHEAD(3) tableColumn=Column() "=" valueExpression=SimpleExpression() { update.addUpdateSet(tableColumn, valueExpression); } - ("," tableColumn=Column() "=" valueExpression=SimpleExpression() { update.addUpdateSet(tableColumn, 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) ")" ] - - "=" - - ( - LOOKAHEAD(3) subSelect=ParenthesedSelect() { updateSet.add(subSelect); } - | - 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) ")" ] - - "=" - - ( - LOOKAHEAD(3) subSelect=ParenthesedSelect() { updateSet.add(subSelect); } - | - LOOKAHEAD(3) "(" expressionList = ComplexExpressionList() { updateSet.setUsingBracketsForValues(true); updateSet.add(expressionList); } ")" - | - valueExpression = Expression() { updateSet.add(valueExpression); } - ) - ) * - ) - ) + updateSets = UpdateSets() { update.setUpdateSets(updateSets); } [ outputClause = OutputClause() {update.setOutputClause(outputClause); } ] @@ -1312,7 +1287,7 @@ Update Update( List with ): [ orderByElements = OrderByElements() { update.setOrderByElements(orderByElements); } ] [ limit = PlainLimit() { update.setLimit(limit); } ] - [ returning=SelectItemsList() ] + [ returningClause = ReturningClause() { update.setReturningClause(returningClause); } ] { return update.withWithItemsList(with) @@ -1321,8 +1296,60 @@ Update Update( List with ): .withFromItem(fromItem) .withJoins(joins) .withModifierPriority(modifierPriority) - .withModifierIgnore(modifierIgnore) - .withReturningExpressionList(returning); + .withModifierIgnore(modifierIgnore); + } +} + +List UpdateSets(): +{ + ArrayList updateSets = new ArrayList(); + UpdateSet updateSet; + Column tableColumn; + Expression valueExpression; + + ExpressionList columns; + ExpressionListvalues; +} +{ + ( + ( + tableColumn=Column() "=" valueExpression=Expression() + { updateSets.add( new UpdateSet (tableColumn, valueExpression)); } + ) + | + ( + { updateSet = new UpdateSet(); updateSets.add(updateSet); } + columns = ParenthesedExpressionList() { updateSet.setColumns(columns); } + "=" + ( + LOOKAHEAD(3) valueExpression = ParenthesedSelect() { updateSet.setValues( new ExpressionList(valueExpression)); } + | + values = ParenthesedExpressionList() { updateSet.setValues(values); } + ) + ) + ) + + ( + "," + ( + tableColumn=Column() "=" valueExpression=Expression() + { updateSets.add( new UpdateSet (tableColumn, valueExpression)); } + ) + | + ( + { updateSet = new UpdateSet(); updateSets.add(updateSet); } + columns = ParenthesedExpressionList() { updateSet.setColumns(columns); } + "=" + ( + LOOKAHEAD(3) valueExpression = ParenthesedSelect() { updateSet.setValues( new ExpressionList(valueExpression)); } + | + values = ParenthesedExpressionList() { updateSet.setValues(values); } + ) + ) + )* + + { + return updateSets; } } @@ -1331,72 +1358,55 @@ Insert Insert( List with ): Insert insert = new Insert(); Table table = null; Column tableColumn = null; - List columns = new ArrayList(); + ExpressionList columns = new ExpressionList(); Expression exp = null; - List returning = null; + ReturningClause returningClause; Select select = null; boolean useDuplicate = false; - List duplicateUpdateColumns = null; - List duplicateUpdateExpressionList = null; Token tk = null; InsertModifierPriority modifierPriority = null; boolean modifierIgnore = false; - boolean useSet = false; - List setColumns = new ArrayList(); - List setExpressionList = new ArrayList(); + + List updateSets; + List duplicateUpdateSets; + String name = null; boolean useAs = false; OutputClause outputClause = null; - UpdateSet updateSet = null; InsertConflictTarget conflictTarget = null; InsertConflictAction conflictAction = null; } -{ +{ { insert.setOracleHint(getOracleHint()); } - [LOOKAHEAD(2) (tk = | tk = | tk = ) - {if (tk!=null) - modifierPriority = InsertModifierPriority.valueOf(tk.image.toUpperCase()); - }] + + [ + LOOKAHEAD(2) (tk = | tk = | tk = ) + { + if (tk!=null) + modifierPriority = InsertModifierPriority.from(tk.image); + } + ] [ LOOKAHEAD(2) { modifierIgnore = true; }] [ LOOKAHEAD(2) ] table=Table() [ LOOKAHEAD(2) [ { useAs = true; } ] name=RelObjectNameWithoutValue() { table.setAlias(new Alias(name,useAs)); }] - [LOOKAHEAD(2) "(" tableColumn=Column() { columns.add(tableColumn); } ("," tableColumn=Column() { columns.add(tableColumn); } )* ")" ] + [LOOKAHEAD(2) "(" columns=ColumnList() ")" ] [ outputClause = OutputClause() { insert.setOutputClause(outputClause); } ] ( ( - { useSet = true; } - tableColumn=Column() "=" exp=SimpleExpression() - { - setColumns = new ArrayList(); - setExpressionList = new ArrayList(); - setColumns.add(tableColumn); - setExpressionList.add(exp); - } - ("," tableColumn=Column() "=" exp=SimpleExpression() - { setColumns.add(tableColumn); - setExpressionList.add(exp); } )* + updateSets = UpdateSets() { insert.withSetUpdateSets(updateSets); } ) | select = Select() ) [ LOOKAHEAD(2) - { useDuplicate = true; } - tableColumn=Column() "=" exp=SimpleExpression() - { - duplicateUpdateColumns = new ArrayList(); - duplicateUpdateExpressionList = new ArrayList(); - duplicateUpdateColumns.add(tableColumn); - duplicateUpdateExpressionList.add(exp); - } - ("," tableColumn=Column() "=" exp=SimpleExpression() - { duplicateUpdateColumns.add(tableColumn); - duplicateUpdateExpressionList.add(exp); } )*] + duplicateUpdateSets = UpdateSets() { insert.withDuplicateUpdateSets(duplicateUpdateSets); } + ] [ @@ -1404,24 +1414,17 @@ Insert Insert( List with ): conflictAction = InsertConflictAction() { insert.withConflictTarget(conflictTarget).setConflictAction(conflictAction); } ] - [ returning=SelectItemsList() ] + [ returningClause = ReturningClause() { insert.setReturningClause(returningClause); } ] { - if (!columns.isEmpty()) { + if (!columns.isEmpty()) { insert.setColumns(columns); } return insert.withWithItemsList(with) .withSelect(select) .withTable(table) - .withUseDuplicate(useDuplicate) - .withDuplicateUpdateColumns(duplicateUpdateColumns) - .withDuplicateUpdateExpressionList(duplicateUpdateExpressionList) - .withReturningExpressionList(returning) .withModifierPriority(modifierPriority) - .withModifierIgnore(modifierIgnore) - .withUseSet(useSet) - .withUseSetColumns(setColumns) - .withSetExpressionList(setExpressionList); + .withModifierIgnore(modifierIgnore); } } @@ -1459,14 +1462,8 @@ InsertConflictTarget InsertConflictTarget(): InsertConflictAction InsertConflictAction(): { InsertConflictAction conflictAction; - ArrayList updateSets = new ArrayList(); - UpdateSet updateSet = null; Expression whereExpression = null; - - Column tableColumn = null; - ParenthesedSelect subSelect; - Expression valueExpression = null; - ExpressionList expressionList; + List updateSets; } { ( @@ -1476,76 +1473,18 @@ InsertConflictAction InsertConflictAction(): | ( { conflictAction = new InsertConflictAction( ConflictActionType.DO_UPDATE ); } - ( - LOOKAHEAD(3) tableColumn=Column() - "=" valueExpression=SimpleExpression() { - updateSet = new UpdateSet(); - updateSet.add(tableColumn); - updateSet.add(valueExpression); - updateSets.add(updateSet); - } - ( - "," - tableColumn=Column() - "=" valueExpression=SimpleExpression() { - updateSet = new UpdateSet(); - updateSet.add(tableColumn); - updateSet.add(valueExpression); - updateSets.add(updateSet); - } - )* - | - ( - { updateSet = new UpdateSet(); updateSets.add(updateSet); } - - [ LOOKAHEAD(2) "(" { updateSet.setUsingBracketsForColumns(true); } ] - tableColumn=Column() { updateSet.add(tableColumn); } - ( LOOKAHEAD(2) "," tableColumn=Column() { updateSet.add(tableColumn); } )* - [ LOOKAHEAD(2) ")" ] - - "=" - - ( - LOOKAHEAD(3) subSelect=ParenthesedSelect() { updateSet.add(subSelect); } - | - LOOKAHEAD(3) "(" expressionList = ComplexExpressionList() { updateSet.setUsingBracketsForValues(true); updateSet.add(expressionList); } ")" - | - valueExpression = Expression() { updateSet.add(valueExpression); } - ) - - ( - "," { updateSet = new UpdateSet(); updateSets.add(updateSet); } - - [ LOOKAHEAD(2) "(" { updateSet.setUsingBracketsForColumns(true); } ] - tableColumn=Column() { updateSet.add(tableColumn); } - ( LOOKAHEAD(2) "," tableColumn=Column() { updateSet.add(tableColumn); } )* - [ LOOKAHEAD(2) ")" ] - - "=" - - ( - LOOKAHEAD(3) subSelect=ParenthesedSelect() { updateSet.add(subSelect); } - | - LOOKAHEAD(3) "(" expressionList = ComplexExpressionList() { updateSet.setUsingBracketsForValues(true); updateSet.add(expressionList); } ")" - | - valueExpression = Expression() { updateSet.add(valueExpression); } - ) - ) * - ) - ) - + updateSets = UpdateSets() { conflictAction.setUpdateSets(updateSets); } [ whereExpression = WhereClause() ] ) ) { return conflictAction - .withUpdateSets(updateSets) .withWhereExpression(whereExpression); } } OutputClause OutputClause(): { - List selectItemList = null; + List> selectItemList = null; UserVariable tableVariable = null; Table outputTable = null; List columnList = null; @@ -1573,18 +1512,11 @@ Upsert Upsert(): { Upsert upsert = new Upsert(); Table table = null; - Column tableColumn = null; - List columns = new ArrayList(); - List primaryExpList = new ArrayList(); - ItemsList itemsList = null; - Expression exp = null; - MultiExpressionList multiExpr = null; - List returning = null; + ExpressionList columns; + List updateSets; + Select select = null; - boolean useSelectBrackets = false; - boolean useDuplicate = false; - List duplicateUpdateColumns = null; - List duplicateUpdateExpressionList = null; + List duplicateUpdateSets; Token tk = null; } { @@ -1597,69 +1529,29 @@ Upsert Upsert(): { upsert.setUpsertType(UpsertType.INSERT_OR_REPLACE); } ) ) - [ LOOKAHEAD(2) { upsert.setUsingInto(true); } ] table=Table() - [ - LOOKAHEAD(2) "(" tableColumn=Column() { columns.add(tableColumn); } - ("," tableColumn=Column() { columns.add(tableColumn); } )* ")" - ] + [ LOOKAHEAD(2) { upsert.setUsingInto(true); } ] + + table=Table() { upsert.setTable(table); } + + [ LOOKAHEAD(2) columns = ParenthesedColumnList() { upsert.setColumns(columns); } ] ( ( - { upsert.setUpsertType(UpsertType.REPLACE_SET); } - tableColumn=Column() "=" exp=SimpleExpression() { columns.add(tableColumn); primaryExpList.add(exp); } - ("," tableColumn=Column() "=" exp=SimpleExpression() { columns.add(tableColumn); primaryExpList.add(exp); } )* - { - itemsList = new ExpressionList(primaryExpList); - } + + updateSets = UpdateSets() { upsert.setUpdateSets(updateSets); } ) | - LOOKAHEAD(2) [ | ] "(" exp=SimpleExpression() { primaryExpList.add(exp); } - - ( "," exp=SimpleExpression() { primaryExpList.add(exp); } )* ")" { itemsList = new ExpressionList(primaryExpList); } - - ("," "(" exp=SimpleExpression() - { - if (multiExpr==null) { - multiExpr=new MultiExpressionList(); - multiExpr.addExpressionList((ExpressionList)itemsList); - itemsList = multiExpr; - } - primaryExpList = new ArrayList(); - primaryExpList.add(exp); - } - ("," exp=SimpleExpression() { primaryExpList.add(exp); } )* ")" - { multiExpr.addExpressionList(primaryExpList); } - )* - | ( - { upsert.setUseValues(false); } - select = Select() + select = Select() { upsert.setSelect(select); } ) ) - [ - { useDuplicate = true; } - tableColumn=Column() "=" exp=SimpleExpression() - { - duplicateUpdateColumns = new ArrayList(); - duplicateUpdateExpressionList = new ArrayList(); - duplicateUpdateColumns.add(tableColumn); - duplicateUpdateExpressionList.add(exp); - } - ("," tableColumn=Column() "=" exp=SimpleExpression() - { duplicateUpdateColumns.add(tableColumn); - duplicateUpdateExpressionList.add(exp); } )*] + [ + + duplicateUpdateSets = UpdateSets() { upsert.setDuplicateUpdateSets(duplicateUpdateSets); } + ] { - if (columns.size() > 0) { - upsert.setColumns(columns); - } - return upsert.withItemsList(itemsList) - .withUseSelectBrackets(useSelectBrackets) - .withSelect(select) - .withTable(table) - .withUseDuplicate(useDuplicate) - .withDuplicateUpdateColumns(duplicateUpdateColumns) - .withDuplicateUpdateExpressionList(duplicateUpdateExpressionList); + return upsert; } } @@ -1680,8 +1572,8 @@ Delete Delete( List with ): boolean modifierIgnore = false; boolean modifierQuick = false; - List returning = null; - OutputClause outputClause = null; + ReturningClause returningClause; + OutputClause outputClause; } { { delete.setOracleHint(getOracleHint()); } @@ -1700,7 +1592,7 @@ Delete Delete( List with ): [orderByElements = OrderByElements() { delete.setOrderByElements(orderByElements); } ] [limit=PlainLimit() {delete.setLimit(limit); } ] - [ returning=SelectItemsList() ] + [ returningClause = ReturningClause() { delete.setReturningClause(returningClause); } ] { if (joins != null && joins.size() > 0) { delete.setJoins(joins); @@ -1712,8 +1604,7 @@ Delete Delete( List with ): .withUsingList(usingList) .withModifierPriority(modifierPriority) .withModifierIgnore(modifierIgnore) - .withModifierQuick(modifierQuick) - .withReturningExpressionList(returning); + .withModifierQuick(modifierQuick); } } @@ -1742,45 +1633,42 @@ Statement Merge( List with ) : { } MergeUpdate MergeUpdateClause() : { - MergeUpdate mu = new MergeUpdate(); - List columns = new ArrayList(); - List expList = new ArrayList(); - Column col; - Expression exp; + MergeUpdate mu; + List updateSets; Expression condition; } { - + - col = Column() "=" exp = SimpleExpression() - { columns.add(col); expList.add(exp); } - ("," col = Column() "=" exp = SimpleExpression() { columns.add(col); expList.add(exp); } )* - - { mu.withColumns(columns).withValues(expList); } + updateSets = UpdateSets() { mu = new MergeUpdate(updateSets); } - [ condition = Expression() { mu.setWhereCondition(condition); }] - [ condition = Expression() { mu.setDeleteWhereCondition(condition); } ] + [ condition = Expression() { mu.setWhereCondition(condition); }] + [ condition = Expression() { mu.setDeleteWhereCondition(condition); } ] - { return mu; } + { return mu; } } MergeInsert MergeInsertClause() : { MergeInsert mi = new MergeInsert(); - List columns = new ArrayList(); - List expList = new ArrayList(); - Column col; - Expression exp; + ExpressionList columns; + ExpressionList expList; Expression condition; } { - ["(" col=Column() { columns.add(col); } ("," col=Column() { columns.add(col); } )* ")"] - "(" exp=SimpleExpression() { expList.add(exp); } ("," exp=SimpleExpression() { expList.add(exp); } )* ")" + + [ "(" columns = ColumnList() ")" + { + mi.setColumns( new ParenthesedExpressionList(columns) ); + } + ] + "(" expList = SimpleExpressionList() ")" + { + mi.setValues( new ParenthesedExpressionList(expList) ); + } - { mi.withColumns(columns).withValues(expList); } - [ condition = Expression() { mi.setWhereCondition(condition); }] - + { return mi; } } @@ -1799,12 +1687,20 @@ List RelObjectNameList() : { Column Column() #Column : { List data = new ArrayList(); + ArrayConstructor arrayConstructor = null; } { data = RelObjectNameList() + // @todo: we better should return a SEQUENCE instead of a COLUMN + [ "." { data.add("nextval"); } ] + + [ LOOKAHEAD(2) arrayConstructor = ArrayConstructor(false) ] { Column col = new Column(data); + if (arrayConstructor!=null) { + col.setArrayConstructor(arrayConstructor); + } linkAST(col,jjtThis); return col; } @@ -1822,7 +1718,7 @@ String RelObjectNameWithoutValue() : { Token tk = null; } { ( tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BEGIN" | tk="BINARY" | tk="BIT" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONFLICT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATABASE" | tk="DDL" | tk="DECLARE" | tk="DEFAULT" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GLOBAL" | tk="GRANT" | tk="GUARD" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="ISNULL" | tk="JSON" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAXVALUE" | tk="MERGE" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRECISION" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="READ" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGISTER" | tk="RENAME" | tk="REPLACE" | tk="RESET" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RLIKE" | tk="ROLLBACK" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TO" | tk="TRUE" | tk="TRUNCATE" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLTEXT" | tk="YAML" | tk="YES" | tk="ZONE" ) + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BEGIN" | tk="BINARY" | tk="BIT" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONFLICT" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATABASE" | tk="DDL" | tk="DECLARE" | tk="DEFAULT" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GLOBAL" | tk="GRANT" | tk="GUARD" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="ISNULL" | tk="JSON" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAXVALUE" | tk="MEMBER" | tk="MERGE" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRECISION" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="READ" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGISTER" | tk="RENAME" | tk="REPLACE" | tk="RESET" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RLIKE" | tk="ROLLBACK" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLTEXT" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -1863,7 +1759,7 @@ String RelObjectNameExt(): { ( result=RelObjectName() | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk= | tk= | tk= + | tk= | tk= | tk= | tk= | tk= | tk= | tk= ) { return tk!=null ? tk.image : result; } } @@ -1914,10 +1810,9 @@ Select SelectWithWithItems( List withItems): Select select; } { - select = Select() { select.setWithItemsList( withItems ); } - { - return select; - } + select = Select() { select.setWithItemsList( withItems ); + return select; +} } Select Select() #Select: @@ -1940,7 +1835,7 @@ Select Select() #Select: | LOOKAHEAD(3) select = ParenthesedSelect() ) - [ select = SetOperationList(select) ] + [ LOOKAHEAD(2) select = SetOperationList(select) ] [ LOOKAHEAD( ) orderByElements = OrderByElements() { select.setOrderByElements(orderByElements); } ] @@ -1971,6 +1866,49 @@ ParenthesedSelect ParenthesedSelect() #ParenthesedSelect: } } +LateralView LateralView() #LateralView: +{ + boolean useOuter = false; + Function generatorFunction = null; + String tableName = null; + String columnName = null; + Alias tableAlias = null; + Alias columnAlias = null; +} +{ + [ { useOuter=true; } ] + generatorFunction = Function() + [ LOOKAHEAD(2) + tableName=RelObjectNameWithoutStart() + { + tableAlias = new Alias(tableName, false); + } + ] + columnName = RelObjectNameWithoutStart() + { + columnAlias = new Alias(columnName, true); + return new LateralView( + useOuter + , generatorFunction + , tableAlias + , columnAlias + ); + } +} + +List LateralViews(): +{ + ArrayList lateralViews = new ArrayList(); + LateralView lateralView = null; +} +{ + lateralView = LateralView() { lateralViews.add(lateralView); } + ( lateralView = LateralView() { lateralViews.add(lateralView); } )* + + { + return lateralViews; + } +} LateralSubSelect LateralSubSelect() #LateralSubSelect: { @@ -1988,14 +1926,16 @@ LateralSubSelect LateralSubSelect() #LateralSubSelect: PlainSelect PlainSelect() #PlainSelect: { PlainSelect plainSelect = new PlainSelect(); - List selectItems = null; + List> selectItems = null; FromItem fromItem = null; + List lateralViews = null; List joins = null; - List distinctOn = null; + List> distinctOn = null; Expression where = null; List orderByElements; GroupByElement groupBy = null; Expression having = null; + Limit limitBy = null; Limit limit = null; Offset offset = null; Fetch fetch = null; @@ -2049,14 +1989,20 @@ PlainSelect PlainSelect() #PlainSelect: selectItems=SelectItemsList() - [intoTables = IntoClause() { plainSelect.setIntoTables(intoTables); } ] + [ LOOKAHEAD(2) intoTables = IntoClause() { plainSelect.setIntoTables(intoTables); } ] [ LOOKAHEAD(2) fromItem=FromItem() - [ LOOKAHEAD(2) joins=JoinsList() ] + [ lateralViews=LateralViews() ] + [ LOOKAHEAD(2) joins=JoinsList() ] ] + // Clickhouse FINAL as shown at https://clickhouse.com/docs/en/operations/settings/settings#final + [ LOOKAHEAD(2) { plainSelect.setUsingFinal(true); } ] + [ LOOKAHEAD(2) ksqlWindow=KSQLWindowClause() { plainSelect.setKsqlWindow(ksqlWindow); } ] [ LOOKAHEAD(2) where=WhereClause() { plainSelect.setWhere(where); }] [ LOOKAHEAD(2) oracleHierarchicalQueryClause=OracleHierarchicalQueryClause() { plainSelect.setOracleHierarchical(oracleHierarchicalQueryClause); } ] + // Oracle supports "HAVING" before "GROUP BY", we will simply parse that but won't pay special attention to the order + [ LOOKAHEAD(2) having=Having() { plainSelect.setHaving(having); }] [ LOOKAHEAD(2) groupBy=GroupByColumnReferences() { plainSelect.setGroupByElement(groupBy); }] [ LOOKAHEAD(2) having=Having() { plainSelect.setHaving(having); }] [ LOOKAHEAD( ) orderByElements = OrderByElements() { plainSelect.setOracleSiblings(true); plainSelect.setOrderByElements(orderByElements); } ] @@ -2067,6 +2013,7 @@ PlainSelect PlainSelect() #PlainSelect: ] [ LOOKAHEAD( ) orderByElements = OrderByElements() { plainSelect.setOrderByElements(orderByElements); } ] [ LOOKAHEAD(2) { plainSelect.setEmitChanges(true); } ] + [ LOOKAHEAD(LimitBy()) limit = LimitBy() { plainSelect.setLimitBy(limit); } ] [ LOOKAHEAD() limit = LimitWithOffset() { plainSelect.setLimit(limit); } ] [ LOOKAHEAD() offset = Offset() { plainSelect.setOffset(offset); } ] [ LOOKAHEAD(, { limit==null }) limit = LimitWithOffset() { plainSelect.setLimit(limit); } ] @@ -2075,8 +2022,8 @@ PlainSelect PlainSelect() #PlainSelect: [ LOOKAHEAD(2) { plainSelect.setForUpdate(true); } [ LOOKAHEAD(2) updateTable = Table() { plainSelect.setForUpdateTable(updateTable); } ] [ LOOKAHEAD() wait = Wait() { plainSelect.setWait(wait); } ] - [ LOOKAHEAD(2) { plainSelect.setNoWait(true); } - | { plainSelect.setSkipLocked(true); } ] + [ LOOKAHEAD(2) ( { plainSelect.setNoWait(true); } + | { plainSelect.setSkipLocked(true); }) ] ] [ LOOKAHEAD() optimize = OptimizeFor() { plainSelect.setOptimizeFor(optimize); } ] @@ -2086,8 +2033,12 @@ PlainSelect PlainSelect() #PlainSelect: { plainSelect.setSelectItems(selectItems); plainSelect.setFromItem(fromItem); - if (joins != null && joins.size() > 0) - plainSelect.setJoins(joins); + if ( lateralViews!=null && lateralViews.size()>0 ) { + plainSelect.setLateralViews( lateralViews ); + } + if ( joins!=null && joins.size()>0 ) { + plainSelect.setJoins( joins ); + } linkAST(plainSelect,jjtThis); return plainSelect; } @@ -2100,7 +2051,6 @@ Select SetOperationList(Select select) #SetOperationList: { Offset offset = null; Fetch fetch = null; WithIsolation withIsolation = null; - //Select select = null; List(); List operations = new ArrayList(); } @@ -2182,7 +2132,7 @@ WithItem WithItem() #WithItem: { WithItem withItem = new WithItem(); String name; - List selectItems; + List> selectItems; Select select; } { @@ -2195,46 +2145,46 @@ WithItem WithItem() #WithItem: } } -List SelectItemsList(): +List> SelectItemsList(): { - List selectItemsList = new ArrayList(); + List> selectItemsList = new ArrayList>(); SelectItem selectItem = null; } { - selectItem=SelectItem() { selectItemsList.add(selectItem); } ( LOOKAHEAD(2) "," selectItem=SelectItem() { selectItemsList.add(selectItem); } )* + selectItem=SelectItem() { selectItemsList.add(selectItem); } + ( + LOOKAHEAD(2) "," selectItem=SelectItem() + { + selectItemsList.add(selectItem); + } + )* { return selectItemsList; } } -SelectExpressionItem SelectExpressionItem(): + +SelectItem SelectItem() #SelectItem: { - SelectExpressionItem selectExpressionItem = null; - Expression expression = null; + Expression expression; Alias alias = null; } { - ( + // @fixme: Oracle's SEQUENCE.nextval is parsed as COLUMN with a name part nextval + // @todo: parse a proper SEQUENCE instead of a COLUMN + ( + "*" { expression = new AllColumns(); } + | + LOOKAHEAD(AllTableColumns()) expression = AllTableColumns() + | LOOKAHEAD( Condition() ) expression = Condition() | LOOKAHEAD( 3 ) expression = ConcatExpression() | expression=Expression() - ) { selectExpressionItem = new SelectExpressionItem(); selectExpressionItem.setExpression(expression); } - [ LOOKAHEAD(2) alias=Alias() { selectExpressionItem.setAlias(alias); }] { return selectExpressionItem; } -} - - -SelectItem SelectItem() #SelectItem: -{ - SelectItem selectItem = null; -} -{ ("*" { selectItem = new AllColumns(); } - | - LOOKAHEAD(AllTableColumns()) selectItem=AllTableColumns() - | - selectItem=SelectExpressionItem() ) + [ LOOKAHEAD(2) alias=Alias() ] { + SelectItem selectItem = new SelectItem(expression, alias); linkAST(selectItem,jjtThis); return selectItem; } @@ -2321,37 +2271,35 @@ MySQLIndexHint MySQLIndexHint(): } } - FunctionItem FunctionItem(): +SelectItem FunctionItem(): { Alias alias = null; Function function; - FunctionItem functionItem; } { - function=Function() { functionItem = new FunctionItem(); functionItem.setFunction(function); } - [alias=Alias() { functionItem.setAlias(alias); }] - { return functionItem; } + function=Function() + [ alias=Alias() ] + { return new SelectItem(function, alias); } } -List PivotForColumns(): +ExpressionList PivotForColumns(): { - List columns = new ArrayList(); + ExpressionList columns; Column column; } { ( - ("(" column = Column() { columns.add(column); } - ("," column = Column() { columns.add(column); } )* - ")") - | column = Column() { columns.add(column); } + columns = ParenthesedColumnList() + | + column = Column() { columns = new ExpressionList(column); } ) { return columns; } } -List PivotFunctionItems(): +List> PivotFunctionItems(): { - List< FunctionItem> functionItems = new ArrayList< FunctionItem>(); - FunctionItem item; + List> functionItems = new ArrayList>(); + SelectItem item; } { item = FunctionItem() {functionItems.add(item);} @@ -2359,46 +2307,21 @@ List PivotFunctionItems(): { return functionItems; } } -List PivotSingleInItems(): +SelectItem ExpressionListItem(): { - List retval = new ArrayList(); - SelectExpressionItem item; + ExpressionList expressionList; + Alias alias = null; } { - item = PivotSelectExprItem() {retval.add(item);} - ("," item = PivotSelectExprItem() {retval.add(item);} )* - { return retval; } -} - -SelectExpressionItem PivotSelectExprItem(): -{ - SelectExpressionItem selectExpressionItem = null; - Expression expression = null; - Alias alias = null; -} -{ - expression=SimpleExpression() { selectExpressionItem = new SelectExpressionItem(); selectExpressionItem.setExpression(expression); } - [alias=Alias() { selectExpressionItem.setAlias(alias); }] { return selectExpressionItem; } -} - -ExpressionListItem ExpressionListItem(): -{ - ExpressionListItem expressionListItem = null; - ExpressionList expressionList = null; - Alias alias = null; -} -{ - "(" - expressionList=SimpleExpressionList(true) { expressionListItem = new ExpressionListItem(); expressionListItem.setExpressionList(expressionList); } - ")" - [alias=Alias() { expressionListItem.setAlias(alias); }] - { return expressionListItem; } + expressionList=ParenthesedExpressionList() + [ alias=Alias() ] + { return new SelectItem(expressionList, alias); } } -List PivotMultiInItems(): +List> PivotMultiInItems(): { - List retval = new ArrayList(); - ExpressionListItem item; + List> retval = new ArrayList>(); + SelectItem item; } { item = ExpressionListItem() {retval.add(item);} @@ -2409,17 +2332,17 @@ List PivotMultiInItems(): Pivot Pivot(): { Pivot retval = new Pivot(); - List functionItems; - List forColumns; - List singleInItems = null; - List multiInItems = null; + List> functionItems; + ExpressionList forColumns; + List> singleInItems = null; + List> multiInItems = null; Alias alias = null; } { "(" functionItems = PivotFunctionItems() forColumns = PivotForColumns() "(" - (LOOKAHEAD(3) singleInItems = PivotSingleInItems() + (LOOKAHEAD(3) singleInItems = SelectItemsList() | multiInItems = PivotMultiInItems() ) ")" ")" @@ -2437,10 +2360,10 @@ Pivot Pivot(): PivotXml PivotXml(): { PivotXml retval = new PivotXml(); - List functionItems; - List forColumns; - List singleInItems = null; - List multiInItems = null; + List> functionItems; + ExpressionList forColumns; + List> singleInItems = null; + List> multiInItems = null; Select inSelect = null; } { @@ -2450,7 +2373,7 @@ PivotXml PivotXml(): ( LOOKAHEAD(2) { retval.setInAny(true); } | LOOKAHEAD(1) inSelect = Select() | - LOOKAHEAD(2) singleInItems = PivotSingleInItems() | + LOOKAHEAD(2) singleInItems =SelectItemsList() | multiInItems = PivotMultiInItems() ) ")" @@ -2468,9 +2391,9 @@ PivotXml PivotXml(): UnPivot UnPivot(): { UnPivot retval = new UnPivot(); - List unpivotClause; - List unpivotForClause; - List unpivotInClause; + ExpressionList unpivotClause; + ExpressionList unpivotForClause; + List> unpivotInClause; Alias alias = null; } { @@ -2480,7 +2403,7 @@ UnPivot UnPivot(): "(" unpivotClause = PivotForColumns() unpivotForClause = PivotForColumns() "(" - unpivotInClause = PivotSingleInItems() + unpivotInClause = SelectItemsList() ")" ")" [ LOOKAHEAD(2) alias = Alias() ] @@ -2669,14 +2592,14 @@ KSQLJoinWindow JoinWindow(): { if (afterDurationToken == null) { retval.setDuration(Long.parseLong(beforeDurationToken.image)); - retval.setTimeUnit(KSQLJoinWindow.TimeUnit.valueOf(beforeTimeUnitToken.image)); + retval.setTimeUnit(KSQLWindow.TimeUnit.from(beforeTimeUnitToken.image)); retval.setBeforeAfterWindow(false); return retval; } retval.setBeforeDuration(Long.parseLong(beforeDurationToken.image)); - retval.setBeforeTimeUnit(KSQLJoinWindow.TimeUnit.valueOf(beforeTimeUnitToken.image)); + retval.setBeforeTimeUnit(KSQLWindow.TimeUnit.from(beforeTimeUnitToken.image)); retval.setAfterDuration(Long.parseLong(afterDurationToken.image)); - retval.setAfterTimeUnit(KSQLJoinWindow.TimeUnit.valueOf(afterTimeUnitToken.image)); + retval.setAfterTimeUnit(KSQLWindow.TimeUnit.from(afterTimeUnitToken.image)); retval.setBeforeAfterWindow(true); return retval; }) @@ -2716,10 +2639,10 @@ KSQLWindow KSQLWindowClause(): ) { retval.setSizeDuration(Long.parseLong(sizeDurationToken.image)); - retval.setSizeTimeUnit(KSQLWindow.TimeUnit.valueOf(sizeTimeUnitToken.image)); + retval.setSizeTimeUnit(KSQLWindow.TimeUnit.from(sizeTimeUnitToken.image)); if (advanceDurationToken != null) { retval.setAdvanceDuration(Long.parseLong(advanceDurationToken.image)); - retval.setAdvanceTimeUnit(KSQLWindow.TimeUnit.valueOf(advanceTimeUnitToken.image)); + retval.setAdvanceTimeUnit(KSQLWindow.TimeUnit.from(advanceTimeUnitToken.image)); } return retval; } @@ -2755,7 +2678,7 @@ OracleHierarchicalExpression OracleHierarchicalQueryClause(): result.setConnectExpression(expr); result.setConnectFirst(true); } - [ expr=AndExpression() {result.setStartExpression(expr);} ] + [ LOOKAHEAD(2) expr=AndExpression() {result.setStartExpression(expr);} ] ) ) { @@ -2769,60 +2692,49 @@ GroupByElement GroupByColumnReferences(): GroupByElement groupBy = new GroupByElement(); Expression expr; ExpressionList list; + Token token; } { - ( LOOKAHEAD(2) ( - "(" ")" { groupBy.withUsingBrackets(true); } - ( - LOOKAHEAD(2) ( - "(" - ( LOOKAHEAD(2) "(" ")" { groupBy.addGroupingSet(new ExpressionList()); } - | LOOKAHEAD(3) "(" list = SimpleExpressionList(true) ")" { groupBy.addGroupingSet(list); } - | expr = SimpleExpression() { groupBy.addGroupingSet(expr); } ) - - ( "," ( LOOKAHEAD(2) "(" ")" { groupBy.addGroupingSet(new ExpressionList()); } - | LOOKAHEAD(3) "(" list = SimpleExpressionList(true) ")" { groupBy.addGroupingSet(list); } - | expr = SimpleExpression() { groupBy.addGroupingSet(expr); } ) )* - ")" - ) - )? - ) - | - LOOKAHEAD(2) ( + ( + LOOKAHEAD(2) ( "(" - ( LOOKAHEAD(2) "(" ")" { groupBy.addGroupingSet(new ExpressionList()); } - | LOOKAHEAD(3) "(" list = SimpleExpressionList(true) ")" { groupBy.addGroupingSet(list); } - | expr = SimpleExpression() { groupBy.addGroupingSet(expr); } ) - - ( "," ( LOOKAHEAD(2) "(" ")" { groupBy.addGroupingSet(new ExpressionList()); } - | LOOKAHEAD(3) "(" list = SimpleExpressionList(true) ")" { groupBy.addGroupingSet(list); } - | expr = SimpleExpression() { groupBy.addGroupingSet(expr); } ) )* + list = GroupingSet() { groupBy.addGroupingSet(list); } + ( LOOKAHEAD(2) "," list = GroupingSet() { groupBy.addGroupingSet(list); })* ")" - ) - | - LOOKAHEAD(2) ( - list = ComplexExpressionList() { groupBy.setGroupByExpressionList(list.withUsingBrackets(false)); } + ) + | + ( + list = ExpressionList() { groupBy.setGroupByExpressions(list); } ( - LOOKAHEAD(2) ( - "(" - ( LOOKAHEAD(2) "(" ")" { groupBy.addGroupingSet(new ExpressionList()); } - | LOOKAHEAD(3) "(" list = SimpleExpressionList(true) ")" { groupBy.addGroupingSet(list); } - | expr = SimpleExpression() { groupBy.addGroupingSet(expr); } ) - - ( "," ( LOOKAHEAD(2) "(" ")" { groupBy.addGroupingSet(new ExpressionList()); } - | LOOKAHEAD(3) "(" list = SimpleExpressionList(true) ")" { groupBy.addGroupingSet(list); } - | expr = SimpleExpression() { groupBy.addGroupingSet(expr); } ) )* + LOOKAHEAD(2) "(" + list = GroupingSet() { groupBy.addGroupingSet(list); } + ( LOOKAHEAD(2) "," list = GroupingSet() { groupBy.addGroupingSet(list); })* ")" - ) )? - ) + ) ) { return groupBy; } } +ExpressionList GroupingSet(): +{ + ExpressionList list; + Expression expression; +} +{ + ( + LOOKAHEAD(2) list = ParenthesedExpressionList() + | + expression = SimpleExpression() { list = new ExpressionList(expression); } + ) + { + return list; + } +} + Expression Having(): { Expression having = null; @@ -2856,10 +2768,11 @@ OrderByElement OrderByElement(): columnReference = Expression() [ LOOKAHEAD(2) ( | ( { orderByElement.setAsc(false); } )) { orderByElement.setAscDescPresent(true); } ] [ LOOKAHEAD(2) - [ + [ LOOKAHEAD(2) ( { orderByElement.setNullOrdering(OrderByElement.NullOrdering.NULLS_FIRST); } | { orderByElement.setNullOrdering(OrderByElement.NullOrdering.NULLS_LAST); } + ) ] ] { @@ -2923,7 +2836,7 @@ Limit PlainLimit() #PlainLimit: ( ( - LOOKAHEAD(3) "(" rowCountExpression = ParenthesedSelect() ")" + LOOKAHEAD(3) rowCountExpression = ParenthesedSelect() | rowCountExpression = Expression() ) { limit.setRowCount(rowCountExpression); } @@ -2934,6 +2847,23 @@ Limit PlainLimit() #PlainLimit: } } +/** + * Clickhouse LIMIT BY + * @see SELECT Query + */ +Limit LimitBy(): +{ + Limit limit; + ExpressionList byExpressions; +} +{ + limit = LimitWithOffset() + byExpressions = ExpressionList() { limit.setByExpressions(byExpressions); } + { + return limit; + } +} + Offset Offset(): { Offset offset = new Offset(); @@ -3150,7 +3080,7 @@ Expression AndExpression() : } { ( - LOOKAHEAD(Condition()) + LOOKAHEAD(Condition(), {!interrupted}) left=Condition() | [ { not=true; } | "!" { not=true; exclamationMarkNot=true; } ] @@ -3162,7 +3092,7 @@ Expression AndExpression() : { boolean useOperator = false; } ( | {useOperator=true;} ) ( - LOOKAHEAD(Condition()) + LOOKAHEAD(Condition(), {!interrupted}) right=Condition() | [ { not=true; } | "!" { not=true; exclamationMarkNot=true; } ] @@ -3203,9 +3133,9 @@ Expression OverlapsCondition():{ { //As per the sql2003 standard, we need at least two items in the list if there is not explicit ROW prefix //More than two expression are allowed per the sql2003 grammar. - "(" left = SimpleExpressionListAtLeastTwoItems() ")" + left = ParenthesedExpressionList() - "(" right = SimpleExpressionListAtLeastTwoItems() ")" + right = ParenthesedExpressionList() {return new OverlapsCondition(left, right);} } @@ -3285,46 +3215,58 @@ Expression SQLCondition(): { ( result=ExistsExpression() - | LOOKAHEAD(InExpression()) result=InExpression() - | LOOKAHEAD(OverlapsCondition()) result=OverlapsCondition() + | LOOKAHEAD(InExpression() , {!interrupted}) result=InExpression() + | LOOKAHEAD(OverlapsCondition(), {!interrupted}) result=OverlapsCondition() | left = SimpleExpression() { result = left; } - [ LOOKAHEAD(2) ((LOOKAHEAD(2) result=Between(left) - | LOOKAHEAD(IsNullExpression()) result=IsNullExpression(left) - | LOOKAHEAD(IsBooleanExpression()) result=IsBooleanExpression(left) - | LOOKAHEAD(2) result=LikeExpression(left) - | LOOKAHEAD(IsDistinctExpression()) result=IsDistinctExpression(left) - | result=SimilarToExpression(left) - )) ] + [ + LOOKAHEAD(2) ( + ( + LOOKAHEAD(2) result=Between(left) + | + result = MemberOfExpression(left) + | + LOOKAHEAD(IsNullExpression()) result=IsNullExpression(left) + | + LOOKAHEAD(IsBooleanExpression()) result=IsBooleanExpression(left) + | + LOOKAHEAD(2) result=LikeExpression(left) + | + LOOKAHEAD(IsDistinctExpression()) result=IsDistinctExpression(left) + | + result=SimilarToExpression(left) + ) + ) + ] ) { return result; } } Expression InExpression() #InExpression : { - InExpression result = new InExpression(); - ItemsList leftItemsList = null; - ExpressionList rightItemsList = null; - Expression leftExpression = null; - Expression rightExpression = null; Token token; - MultiExpressionList multiExpressionList = null; - ExpressionList expressionList = null; + int oldOracleJoin = 0; + boolean usesNot = false; + Expression leftExpression; + Expression rightExpression; } { - leftExpression=SimpleExpression() { result.setLeftExpression(leftExpression); } - [ "(" "+" ")" { result.setOldOracleJoinSyntax(EqualsTo.ORACLE_JOIN_RIGHT); } ] + leftExpression=SimpleExpression() + [ "(" "+" ")" { oldOracleJoin=EqualsTo.ORACLE_JOIN_RIGHT; } ] - [ { result.setNot(true); } ] + [ { usesNot=true; } ] ( - 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(3) rightExpression = ParenthesedSelect() { result.setRightExpression( rightExpression ); } - | LOOKAHEAD(2) rightExpression = SimpleExpression() { result.setRightExpression(rightExpression); } + LOOKAHEAD(2) token= { rightExpression = new StringValue(token.image); } + | LOOKAHEAD(3) rightExpression = Function() + | LOOKAHEAD(ParenthesedSelect(), {!interrupted}) rightExpression = ParenthesedSelect() + | LOOKAHEAD(3) rightExpression = ParenthesedExpressionList() + | rightExpression = SimpleExpression() ) { - linkAST(result,jjtThis); - return result; + InExpression inExpression = new InExpression(leftExpression, rightExpression) + .withOldOracleJoinSyntax(oldOracleJoin) + .withNot(usesNot); + linkAST(inExpression,jjtThis); + return inExpression; } } @@ -3445,79 +3387,141 @@ Expression ExistsExpression(): } } -ExpressionList SimpleExpressionList(boolean outerBrackets) #ExpressionList: +Expression MemberOfExpression(Expression leftExpression): { - ExpressionList retval = new ExpressionList().withBrackets(outerBrackets); - List expressions = new ArrayList(); - Expression expr = null; + MemberOfExpression result; + Expression rightExpression = null; } { - expr=SimpleExpression() { expressions.add(expr); } - ( LOOKAHEAD(2, {!interrupted} ) "," expr=SimpleExpression() { expressions.add(expr); } )* + rightExpression=Expression() { - retval.setExpressions(expressions); - return retval; + return new MemberOfExpression(leftExpression, rightExpression ); } } -ExpressionList ComplexExpressionList() #ExpressionList: +ExpressionList ExpressionList() #ExpressionList: { - ExpressionList retval = new ExpressionList(); - List expressions = new ArrayList(); - Expression expr = null; + ExpressionList expressionList; } { - ( - LOOKAHEAD(2) expr=OracleNamedFunctionParameter() - | expr=Expression() - ) { expressions.add(expr); } + ( + LOOKAHEAD(3, { getAsBoolean(Feature.allowComplexParsing) && !interrupted}) expressionList = ComplexExpressionList() + | + LOOKAHEAD(3) expressionList = SimpleExpressionList() + | + LOOKAHEAD(3) expressionList = ParenthesedExpressionList() + ) + { + // Avoid redundant ExpressionLists containing only one ParenthesedExpressionList + // return the Parenthesed Sub ExpressionList instead + // Same for ParenthesedExpressionList containing only 1 ExpressionList + + if ( expressionList.size() == 1 && expressionList.get(0) instanceof ExpressionList ) { + ExpressionList subList = (ExpressionList) expressionList.get(0); + if (expressionList instanceof ParenthesedExpressionList) { + if (subList instanceof ParenthesedExpressionList) { + return expressionList; + } else { + return new ParenthesedExpressionList(subList); + } + } else { + if (subList instanceof ParenthesedExpressionList) { + return new ParenthesedExpressionList(subList); + } else { + return subList; + } + } + } + return expressionList; + } +} +ParenthesedExpressionList ParenthesedExpressionList(): +{ + ExpressionList expressions=new ExpressionList(); +} +{ + "(" ( - LOOKAHEAD(2, {!interrupted}) "," - ( - LOOKAHEAD(2) expr=OracleNamedFunctionParameter() - | expr=Expression() - ) { expressions.add(expr); } - )* + LOOKAHEAD({ getAsBoolean(Feature.allowComplexParsing) && !interrupted}) expressions = ComplexExpressionList() + | + expressions = SimpleExpressionList() + )? + ")" + { + return new ParenthesedExpressionList(expressions); + } +} +ExpressionList SimpleExpressionList(): +{ + ExpressionList expressions = new ExpressionList(); + Expression expr; +} +{ + expr=SimpleExpression() { expressions.add(expr); } + ( LOOKAHEAD(2, {!interrupted} ) "," expr=SimpleExpression() { expressions.add(expr); } )* { - retval.setExpressions(expressions); - return retval; + return expressions; } } -// trim( [leading|trailing|both] expr from expr) -// The [leading|trailing|both] token has already been consumed -NamedExpressionList NamedExpressionList1(): + +ExpressionList ColumnList(): { - NamedExpressionList retval = new NamedExpressionList(); - List expressions = new ArrayList(); - List names = new ArrayList(); - Expression expr1 = null; - Expression expr2 = null; - String name = ""; - Token tk1 = null; - Token tk2 = null; + ExpressionList expressions = new ExpressionList(); + Column expr; +} +{ + expr=Column() { expressions.add(expr); } + ( LOOKAHEAD(2) "," expr=Column() { expressions.add(expr); } )* + { + return expressions; + } +} + +ParenthesedExpressionList ParenthesedColumnList(): +{ + ExpressionList expressions; +} +{ + "(" expressions = ColumnList() ")" + { + return new ParenthesedExpressionList(expressions); + } +} + +ExpressionList ComplexExpressionList(): +{ + ExpressionList expressions = new ExpressionList(); + Expression expr; } { ( - (tk1=|tk1=|tk1=) { names.add(tk1.image); } - expr1=SimpleExpression() - (tk2=|tk2=|tk2=) - expr2=SimpleExpression() - { expressions.add(expr1); names.add(tk2.image); expressions.add(expr2);} + LOOKAHEAD(2) expr=OracleNamedFunctionParameter() + | expr=Expression() ) + { + expressions.add(expr); + } + + ( + LOOKAHEAD(2, {!interrupted}) "," + ( + LOOKAHEAD(2) expr=OracleNamedFunctionParameter() + | expr=Expression() + ) { expressions.add(expr); } + )* { - retval.setNames(names); - retval.setExpressions(expressions); - return retval; + return expressions; } } +// @Todo: Refactor this with proper SQL:2016 functions according to https://manticore-projects.com/SQL2016Parser/syntax.html#character-value-function // substring(expr1 from expr2) // substring(expr1 from expr2 for expr3) -// trim(expr1 from expr2) +// trim(expr1 from expr2) <-- Superceded by TrimFunction() below // position(expr1 in expr2) // overlay(expr1 placing expr2 from expr3) // overlay(expr1 placing expr2 from expr3 for expr4) @@ -3562,21 +3566,6 @@ NamedExpressionList NamedExpressionListExprFirst(): } } - -ExpressionList SimpleExpressionListAtLeastTwoItems(): -{ - ExpressionList retval = new ExpressionList(); - List expressions = new ArrayList(); - Expression expr = null; -} -{ - expr=SimpleExpression() { expressions.add(expr); } ("," expr=SimpleExpression() { expressions.add(expr); })+ - { - retval.setExpressions(expressions); - return retval; - } -} - Expression ComparisonItem() : { Expression retval = null; @@ -3584,8 +3573,8 @@ Expression ComparisonItem() : { ( LOOKAHEAD(3) retval=AnyComparisonExpression() - | LOOKAHEAD(ValueListExpression()) retval=ValueListExpression() | LOOKAHEAD(3) retval=SimpleExpression() + | LOOKAHEAD(3) retval=ParenthesedExpressionList() | LOOKAHEAD(3) retval=RowConstructor() | retval=PrimaryExpression() ) @@ -3597,29 +3586,18 @@ Expression ComparisonItem() : Expression AnyComparisonExpression() : { - AnyComparisonExpression anyComparisonExpr = null; AnyType anyType; - ParenthesedSelect subSelect; - ItemsList simpleExpressionList; + Select select; } { - ( { anyType = AnyType.ANY; } | { anyType = AnyType.SOME; } | { anyType = AnyType.ALL; } ) - "(" - - // if the next block looks alike an ExpressionList without Brackets, then parse as List ( - LOOKAHEAD( SimpleExpressionList(false) ) - ( - - simpleExpressionList = SimpleExpressionList(false) { anyComparisonExpr=new AnyComparisonExpression(anyType, simpleExpressionList).withUseBracketsForValues(false); } - ) - // Otherwise parse it as a ParenthesedSelect - | subSelect = ParenthesedSelect() { anyComparisonExpr=new AnyComparisonExpression(anyType, subSelect).withUseBracketsForValues(false); } - + { anyType = AnyType.ANY; } + | { anyType = AnyType.SOME; } + | { anyType = AnyType.ALL; } ) - ")" + select = Select() { - return anyComparisonExpr; + return new AnyComparisonExpression(anyType, select); } } @@ -3630,11 +3608,14 @@ Expression SimpleExpression(): Token operation = null; } { - [ LOOKAHEAD(UserVariable() ("=" | ":=") ) - user = UserVariable() - ( operation = "=" | operation = ":=" ) - ] - retval=ConcatExpression() + + ( + [ LOOKAHEAD(UserVariable() ("=" | ":=") ) + user = UserVariable() + ( operation = "=" | operation = ":=" ) + ] + retval=ConcatExpression() + ) { if (user != null) { VariableAssignment assignment = new VariableAssignment(); @@ -3642,7 +3623,7 @@ Expression SimpleExpression(): assignment.setOperation(operation.image); assignment.setExpression(retval); return assignment; - } else + } else return retval; } } @@ -3679,7 +3660,7 @@ Expression BitwiseAndOr(): { leftExpression=AdditiveExpression() { result = leftExpression; } ( - ( + LOOKAHEAD(2) ( "|" { result = new BitwiseOr(); } | "&" { result = new BitwiseAnd(); } @@ -3865,11 +3846,7 @@ Expression PrimaryExpression() #PrimaryExpression: | LOOKAHEAD(2, {!interrupted}) retval=CastExpression() - | LOOKAHEAD(2, {!interrupted}) retval=TryCastExpression() - - | LOOKAHEAD(2, {!interrupted}) retval=SafeCastExpression() - - //| LOOKAHEAD(2) retval=RowConstructor() + | LOOKAHEAD(2, {!interrupted}) retval=CharacterPrimary() // support timestamp expressions | LOOKAHEAD(2, {!interrupted}) (token= | token=) { retval = new TimeKeyExpression(token.image); } @@ -3896,16 +3873,17 @@ Expression PrimaryExpression() #PrimaryExpression: | LOOKAHEAD( ParenthesedSelect() , {!interrupted} ) retval=ParenthesedSelect() - | ( - "(" ( LOOKAHEAD( { getAsBoolean(Feature.allowComplexParsing) && !interrupted } ) list = ComplexExpressionList() | list = SimpleExpressionList(true) ) ")" - { - if (list.getExpressions().size() == 1) { - retval = new Parenthesis(list.getExpressions().get(0)); - } else { - retval = new RowConstructor().withExprList(list); - } - } - ["." tmp=RelObjectNameExt() { retval = new RowGetExpression(retval, tmp); }] + | + ( + list=ParenthesedExpressionList() + { + if (list.size() == 1) { + retval = new Parenthesis( (Expression) list.getExpressions().get(0)); + } else { + retval = list; + } + } + ["." tmp=RelObjectNameExt() { retval = new RowGetExpression(retval, tmp); }] ) ) @@ -3923,7 +3901,7 @@ Expression PrimaryExpression() #PrimaryExpression: castExpr = new CastExpression(); castExpr.setUseCastKeyword(false); castExpr.setLeftExpression(retval); - castExpr.setType(type); + castExpr.setColDataType(type); retval=castExpr; } )* @@ -3932,16 +3910,14 @@ Expression PrimaryExpression() #PrimaryExpression: timezoneExpr = new TimezoneExpression(); timezoneExpr.addTimezoneExpression(timezoneRightExpr); - } )* + } + )* { if (timezoneExpr != null && !timezoneExpr.getTimezoneExpressions().isEmpty()) { timezoneExpr.setLeftExpression(retval); retval=timezoneExpr; } - } - - { if (sign != null) { retval = new SignedExpression(sign.image.charAt(0), retval); } @@ -3976,10 +3952,13 @@ NextValExpression NextValExpression() : { JdbcNamedParameter JdbcNamedParameter() : { JdbcNamedParameter parameter = new JdbcNamedParameter(); String name; + String namePart; } { - ":" (name=RelObjectNameExt2() { parameter.setName(name); }) + (":" | "&" { parameter.setParameterCharacter("&"); } ) + name=IdentifierChain() { + parameter.setName(name); return parameter; } } @@ -3991,7 +3970,7 @@ OracleNamedFunctionParameter OracleNamedFunctionParameter() : { { name=RelObjectNameExt2() - expression=Expression() + expression=Expression() { return new OracleNamedFunctionParameter(name, expression); } @@ -4004,8 +3983,7 @@ UserVariable UserVariable() : { } { ("@" | "@@" { var.setDoubleAdd(true);} ) - varName=RelObjectNameExt2() - ( "." var2=RelObjectNameExt2() { varName+="." + var2; } )* + varName=IdentifierChain() { var.setName(varName); return var; @@ -4028,26 +4006,59 @@ DateTimeLiteralExpression DateTimeLiteralExpression() : { DateTimeLiteralExpression expr = new DateTimeLiteralExpression(); Token t; } { - t= { expr.setType(DateTimeLiteralExpression.DateTime.valueOf(t.image.toUpperCase())); } + t= { expr.setType(DateTimeLiteralExpression.DateTime.from(t.image)); } t= { expr.setValue(t.image); return expr; } } +RangeExpression RangeExpression(Expression startExpression): +{ + Expression endExpression; +} +{ + ":" endExpression = Expression() + { + return new RangeExpression(startExpression, endExpression); + } +} + ArrayConstructor ArrayConstructor(boolean arrayKeyword) : { - ArrayList expList = new ArrayList(); + ExpressionList expList = new ExpressionList(); ArrayConstructor array = new ArrayConstructor(expList, arrayKeyword); - Expression exp = null; + Expression exp; } { "[" - [ (LOOKAHEAD(3) exp = SimpleExpression() | exp = ArrayConstructor(false)) - { expList.add(exp); } - ("," (exp = SimpleExpression() | exp = ArrayConstructor(false)) - { expList.add(exp); })* - ] + [ + ( + LOOKAHEAD(3) exp = Expression() [ exp=RangeExpression(exp) ] + | + exp = ArrayConstructor(false) + ) { expList.add(exp); } + + ( + "," + ( + LOOKAHEAD(3) exp = Expression() [ exp=RangeExpression(exp) ] + | + exp = ArrayConstructor(false) + ){ expList.add(exp); } + )* + ] "]" { return array; } } +Expression ParenthesedExpression(): +{ + Expression expression; +} +{ + "(" expression = PrimaryExpression() ")" + { + return new Parenthesis(expression); + } +} + JsonExpression JsonExpression() : { JsonExpression result = new JsonExpression(); Expression expr; @@ -4065,34 +4076,82 @@ JsonExpression JsonExpression() : { | expr=UserVariable() | - LOOKAHEAD(JsonFunction(), {!interrupted}) expr = JsonFunction() + LOOKAHEAD(JsonFunction(), {getAsBoolean(Feature.allowComplexParsing) && !interrupted}) expr = JsonFunction() | - LOOKAHEAD(JsonAggregateFunction(), {!interrupted}) expr = JsonAggregateFunction() + LOOKAHEAD(JsonAggregateFunction(), {getAsBoolean(Feature.allowComplexParsing) && !interrupted}) expr = JsonAggregateFunction() | - LOOKAHEAD(FullTextSearch(), {!interrupted}) expr = FullTextSearch() + LOOKAHEAD(FullTextSearch(), {getAsBoolean(Feature.allowComplexParsing) && !interrupted}) expr = FullTextSearch() | - LOOKAHEAD( 3 , {!interrupted && getAsBoolean(Feature.allowComplexParsing) } ) expr=SimpleFunction() + LOOKAHEAD( Function() , {getAsBoolean(Feature.allowComplexParsing) && !interrupted} ) expr=Function() | LOOKAHEAD( 2, {!interrupted} ) expr=Column() | token= { expr = new StringValue(token.image); } | - LOOKAHEAD( {!interrupted} ) "(" expr=ParenthesedSelect() ")" + LOOKAHEAD(ParenthesedExpression(), {getAsBoolean(Feature.allowComplexParsing)} ) expr = ParenthesedExpression() + | + LOOKAHEAD( 3, {getAsBoolean(Feature.allowComplexParsing) && !interrupted}) expr=ParenthesedSelect() ) - ( "::" type=ColDataType() { + ( + "::" type=ColDataType() + { castExpr = new CastExpression(); castExpr.setUseCastKeyword(false); castExpr.setLeftExpression(expr); - castExpr.setType(type); + castExpr.setColDataType(type); expr=castExpr; - } )* + } + )* + { + result.setExpression(expr); + } + ( - "->" (token= | token=) {result.addIdent(token.image,"->");} | - "->>" (token= | token=) {result.addIdent(token.image,"->>");} | - "#>" token= {result.addIdent(token.image,"#>");} | - "#>>" token= {result.addIdent(token.image,"#>>");} + LOOKAHEAD(2) ( + "->" (token= | token=) {result.addIdent(token.image,"->");} + | + "->>" (token= | token=) {result.addIdent(token.image,"->>");} + | + "#>" token= {result.addIdent(token.image,"#>");} + | + "#>>" token= {result.addIdent(token.image,"#>>");} + ) )+ + + // chaining JSON Expressions, e.g. + // '{"obj":{"field": "value"}}'::JSON -> 'obj'::TEXT ->> 'field'::TEXT + ( + LOOKAHEAD(2, {!interrupted} ) ( + LOOKAHEAD(2) ( + "::" type=ColDataType() + { + castExpr = new CastExpression(); + castExpr.setUseCastKeyword(false); + castExpr.setLeftExpression(result); + castExpr.setColDataType(type); + expr=castExpr; + } + ) + )+ + { + result = new JsonExpression(); + result.setExpression(expr); + } + + ( + LOOKAHEAD(2) ( + "->" (token= | token=) {result.addIdent(token.image,"->");} + | + "->>" (token= | token=) {result.addIdent(token.image,"->>");} + | + "#>" token= {result.addIdent(token.image,"#>");} + | + "#>>" token= {result.addIdent(token.image,"#>>");} + ) + )* + )* + { result.setExpression(expr); return result; @@ -4111,12 +4170,12 @@ JsonFunction JsonFunction() : { Expression expression = null; JsonFunctionExpression functionExpression; - + } { ( - ( - ( + ( + ( "(" { result.setType( JsonFunctionType.OBJECT ); } ( ( @@ -4179,18 +4238,18 @@ JsonFunction JsonFunction() : { ")" ) | - ( - { result.setType( JsonFunctionType.ARRAY ); } - "(" + ( + { 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 ); } ] @@ -4216,7 +4275,7 @@ JsonAggregateFunction JsonAggregateFunction() : { Token token; Expression expression; List expressionOrderByList = null; - + Expression filter; ExpressionList expressionList = null; List olist = null; @@ -4225,22 +4284,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 ); } ) ] @@ -4257,19 +4316,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 ); } ) ] @@ -4498,70 +4557,37 @@ ExtractExpression ExtractExpression() : CastExpression CastExpression(): { - CastExpression retval = new CastExpression(); - ColDataType type = null; - RowConstructor rowConstructor = null; - Expression expression = null; - boolean useCastKeyword; -} -{ - - "(" - expression=SimpleExpression() - { retval.setUseCastKeyword(true); } - ( - LOOKAHEAD(3) rowConstructor = RowConstructor() { retval.setRowConstructor(rowConstructor); } - | type=ColDataType() { retval.setType(type); } - ) - ")" - - { - retval.setLeftExpression(expression); - return retval; - } -} - -TryCastExpression TryCastExpression(): -{ - TryCastExpression retval = new TryCastExpression(); - ColDataType type = null; - RowConstructor rowConstructor = null; + Token keyword; + CastExpression retval; + ColumnDefinition columnDefinition; + ColDataType type; Expression expression = null; boolean useCastKeyword; } { - - "(" - expression=SimpleExpression() - { retval.setUseCastKeyword(true); } ( - LOOKAHEAD(3) rowConstructor = RowConstructor() { retval.setRowConstructor(rowConstructor); } - | type=ColDataType() { retval.setType(type); } + keyword= + | + keyword= + | + keyword= ) - ")" - { - retval.setLeftExpression(expression); - return retval; + retval = new CastExpression(keyword.image); } -} - -SafeCastExpression SafeCastExpression(): -{ - SafeCastExpression retval = new SafeCastExpression(); - ColDataType type = null; - RowConstructor rowConstructor = null; - Expression expression = null; - boolean useCastKeyword; -} -{ - "(" expression=SimpleExpression() { retval.setUseCastKeyword(true); } ( - LOOKAHEAD(3) rowConstructor = RowConstructor() { retval.setRowConstructor(rowConstructor); } - | type=ColDataType() { retval.setType(type); } + ( + + "(" + columnDefinition=ColumnDefinition() { retval.addColumnDefinition(columnDefinition); } + ( "," columnDefinition=ColumnDefinition() { retval.addColumnDefinition(columnDefinition); } )* + ")" + ) + | + type=ColDataType() { retval.setColDataType(type); } ) ")" @@ -4570,6 +4596,7 @@ SafeCastExpression SafeCastExpression(): return retval; } } + Expression CaseWhenExpression() #CaseWhenExpression: { CaseExpression caseExp = new CaseExpression(); @@ -4582,9 +4609,14 @@ Expression CaseWhenExpression() #CaseWhenExpression: { caseCounter++; } [ switchExp=Expression() ] ( clause=WhenThenSearchCondition() { whenClauses.add(clause); } )+ - [ (LOOKAHEAD( ["("] CaseWhenExpression() [")"] ( | | ) ) ["("] elseExp=CaseWhenExpression() [")" { ((CaseExpression) elseExp).setUsingBrackets(true); } ] - | elseExp=Expression() - ) + [ + + ( + LOOKAHEAD(3, {!interrupted}) "(" elseExp=CaseWhenExpression() ")" { elseExp = new Parenthesis( elseExp ); } + | LOOKAHEAD(3, {!interrupted}) elseExp=CaseWhenExpression() + | LOOKAHEAD(3, {getAsBoolean(Feature.allowComplexParsing) && !interrupted}) elseExp=Expression() + | elseExp=SimpleExpression() + ) ] { caseCounter--; } { @@ -4598,16 +4630,17 @@ Expression CaseWhenExpression() #CaseWhenExpression: WhenClause WhenThenSearchCondition(): { WhenClause whenThen = new WhenClause(); - Expression whenExp = null; - Expression thenExp = null; + Expression whenExp; + Expression thenExp; } { whenExp=Expression() - ( - LOOKAHEAD( ["("] CaseWhenExpression() [")"] ( | | ) ) ["("] thenExp=CaseWhenExpression() [")" { ((CaseExpression) thenExp).setUsingBrackets(true); }] - | - thenExp=Expression() - ) + + ( + LOOKAHEAD({getAsBoolean(Feature.allowComplexParsing) && !interrupted}) thenExp=Expression() + | + thenExp=SimpleExpression() + ) { whenThen.setWhenExpression(whenExp); whenThen.setThenExpression(thenExp); @@ -4616,26 +4649,18 @@ WhenClause WhenThenSearchCondition(): } RowConstructor RowConstructor(): { - RowConstructor rowConstructor = new RowConstructor(); - ColumnDefinition columnDefinition = null; + Token token; + ParenthesedExpressionList expressions; } { - [ { rowConstructor.setName("ROW");} ] - "(" - columnDefinition = ColumnDefinition() { rowConstructor.addColumnDefinition(columnDefinition); } - ( - "," - columnDefinition = ColumnDefinition() { rowConstructor.addColumnDefinition(columnDefinition); } - )* - ")" - - + token= + expressions = ParenthesedExpressionList() { - return rowConstructor; + return new RowConstructor(token.image, expressions); } } /** -TODO: VariableExpression should be a standalone class with more operations available. +TODO: VariableExpression should be a standalone class with more operations available. */ EqualsTo VariableExpression(): { Expression left; @@ -4651,6 +4676,7 @@ EqualsTo VariableExpression(): { } Execute Execute(): { + Token token; List funcName; ExpressionList expressionList = null; Execute execute = new Execute(); @@ -4665,39 +4691,30 @@ Execute Execute(): { funcName=RelObjectNameList() { execute.setName(funcName); } ( - LOOKAHEAD(3) ( expr = VariableExpression() { namedExprList = new ArrayList(); namedExprList.add( expr ); } - ( "," expr = VariableExpression() { namedExprList.add(expr); })* - { expressionList = new ExpressionList(namedExprList); } ) - | - LOOKAHEAD(3) expressionList=SimpleExpressionList(true) - | - ("(" expressionList=SimpleExpressionList(true) ")" { execute.setParenthesis(true); }) + expressionList=ExpressionList() { execute.setExprList(expressionList); } )? { - execute.setExprList(expressionList); return execute; } } FullTextSearch FullTextSearch() : { - Column col; Token searchModifier; Token againstValue; JdbcParameter jdbcParameter; JdbcNamedParameter jdbcNamedParameter; FullTextSearch fs = new FullTextSearch(); - List matchedColumns = new ArrayList(); - List expList = new ArrayList(); + ExpressionList matchedColumns; } { - "(" col=Column() { matchedColumns.add(col); } ("," col=Column() { matchedColumns.add(col); } )* ")" - "(" - ( - againstValue= { fs.setAgainstValue(new StringValue(againstValue.image)); } - | + "(" matchedColumns=ColumnList() ")" + "(" + ( + againstValue= { fs.setAgainstValue(new StringValue(againstValue.image)); } + | jdbcParameter=SimpleJdbcParameter() { fs.setAgainstValue( jdbcParameter ); } - | + | jdbcNamedParameter=SimpleJdbcNamedParameter() { fs.setAgainstValue( jdbcNamedParameter ); } ) [ @@ -4737,90 +4754,38 @@ Function SpecialStringFunctionWithNamedParameters() : Token funcName; NamedExpressionList namedExpressionList = null; ExpressionList expressionList = null; - List orderByList; -} -{ - funcName = - - "(" - ( - LOOKAHEAD(NamedExpressionList1()) namedExpressionList=NamedExpressionList1() - | - LOOKAHEAD(NamedExpressionListExprFirst(), { getAsBoolean(Feature.allowComplexParsing) }) namedExpressionList = NamedExpressionListExprFirst() - | - LOOKAHEAD(3, { getAsBoolean(Feature.allowComplexParsing) }) expressionList=ComplexExpressionList() {expressionList.setUsingBrackets(false);} - | - LOOKAHEAD(3) expressionList=SimpleExpressionList(false) - ) - ")" - - { - return new Function().withName(funcName.image).withNamedParameters(namedExpressionList).withParameters(expressionList); - } -} - -Function InternalFunction(Function retval) : -{ - List funcName; - Expression allColumnsExpression = null; - List expressions = new ArrayList(); - ExpressionList expressionList = null; - NamedExpressionList namedExpressionList = null; - KeepExpression keep = null; - Select expr = null; - Token tk1 = null; - Token tk2 = null; - Expression attributeExpression = null; - Column attributeColumn = null; - List orderByList; - boolean ignoreNulls = false; -} -{ - funcName = RelObjectNameList() - - "(" [ LOOKAHEAD(2) [ LOOKAHEAD(2)( { retval.setDistinct(true); } | { retval.setAllColumns(true); } | { retval.setUnique(true); }) ] - ( LOOKAHEAD(4) - "*" { allColumnsExpression = new AllColumns(); expressionList = new ExpressionList(allColumnsExpression).withUsingBrackets(false); } - | - LOOKAHEAD(AllTableColumns()) allColumnsExpression=AllTableColumns() { expressionList = new ExpressionList(allColumnsExpression).withUsingBrackets(false); } - | - LOOKAHEAD(3, { getAsBoolean(Feature.allowComplexParsing) }) (expressionList=ComplexExpressionList() {expressionList.setUsingBrackets(false);} [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ]) - | - LOOKAHEAD(3) (expressionList=SimpleExpressionList(false) [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ]) - | - expr = Select() { expressionList = new ExpressionList(expr).withUsingBrackets(false); } - - )] - [ {retval.setIgnoreNulls(true); }] - ")" + List orderByList; +} +{ + funcName = - [ "." ( - // tricky lookahead since we do need to support the following constructs - // schema.f1().f2() - Function with Function Column - // schema.f1().f2.f3 - Function with Attribute Column - LOOKAHEAD( Function() ) attributeExpression=Function() { retval.setAttribute(attributeExpression); } + "(" + ( + LOOKAHEAD(NamedExpressionListExprFirst(), { getAsBoolean(Feature.allowComplexParsing) }) namedExpressionList = NamedExpressionListExprFirst() | - attributeColumn=Column() { retval.setAttribute(attributeColumn); } - ) - ] - - [ LOOKAHEAD(2) keep = KeepExpression() ] + expressionList=ExpressionList() + ) + ")" { - retval.setParameters(expressionList); - retval.setName(funcName); - retval.setKeep(keep); - return retval; + return new Function() + .withName(funcName.image) + .withNamedParameters(namedExpressionList) + .withParameters(expressionList); } } -Function SimpleFunction() #SimpleFunction : +Function InternalFunction(Function retval) : { - Function retval = new Function(); List funcName; Expression allColumnsExpression = null; ExpressionList expressionList = null; KeepExpression keep = null; + Select expr = null; + Token tk1 = null; + Token tk2 = null; + Expression attributeExpression = null; + Column attributeColumn = null; List orderByList; boolean ignoreNulls = false; } @@ -4829,28 +4794,42 @@ Function SimpleFunction() #SimpleFunction : "(" [ - LOOKAHEAD(2) - [ - LOOKAHEAD(2)( { retval.setDistinct(true); } - | { retval.setAllColumns(true); } - | { retval.setUnique(true); }) + LOOKAHEAD(2) [ + LOOKAHEAD(2) ( + { retval.setDistinct(true); } + | { retval.setAllColumns(true); } + | { retval.setUnique(true); } + ) ] ( - LOOKAHEAD(4) "*" { allColumnsExpression = new AllColumns(); expressionList = new ExpressionList(allColumnsExpression).withUsingBrackets(false); } + "*" { expressionList = new ExpressionList(new AllColumns()); } + | + LOOKAHEAD( AllTableColumns() ) allColumnsExpression=AllTableColumns() { expressionList = new ExpressionList(allColumnsExpression); } | - LOOKAHEAD(AllTableColumns()) allColumnsExpression=AllTableColumns() { expressionList = new ExpressionList(allColumnsExpression).withUsingBrackets(false); } + LOOKAHEAD(3) expressionList=ExpressionList() [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ] | - (expressionList=SimpleExpressionList(false) [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ]) + expr = Select() { expressionList = new ExpressionList(expr); } ) ] - [ {retval.setIgnoreNulls(true); } ] + [ {retval.setIgnoreNulls(true); }] ")" + [ "." ( + // tricky lookahead since we do need to support the following constructs + // schema.f1().f2() - Function with Function Column + // schema.f1().f2.f3 - Function with Attribute Column + LOOKAHEAD( Function() ) attributeExpression=Function() { retval.setAttribute(attributeExpression); } + | + attributeColumn=Column() { retval.setAttribute(attributeColumn); } + ) + ] + [ LOOKAHEAD(2) keep = KeepExpression() ] { retval.setParameters(expressionList); retval.setName(funcName); + retval.setKeep(keep); return retval; } } @@ -4888,7 +4867,7 @@ MySQLGroupConcat MySQLGroupConcat():{ { "(" [ { retval.setDistinct(true); } ] - expressionList = SimpleExpressionList(true) + expressionList = ExpressionList() [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ] [ t= { retval.setSeparator(t.image); } ] ")" @@ -4898,19 +4877,6 @@ MySQLGroupConcat MySQLGroupConcat():{ } } -ValueListExpression ValueListExpression(): -{ - ValueListExpression retval = new ValueListExpression(); - ExpressionList expressionList = null; -} -{ - "(" expressionList = SimpleExpressionListAtLeastTwoItems() ")" - { - retval.setExpressionList(expressionList); - return retval; - } -} - TableFunction TableFunction(): { Alias alias = null; @@ -4919,7 +4885,7 @@ TableFunction TableFunction(): } { function=Function() { - functionItem = new TableFunction().withFunction(function); + functionItem = new TableFunction().withExpression(function); } [LOOKAHEAD(2) alias=Alias() { functionItem.setAlias(alias); }] { return functionItem; } @@ -4977,7 +4943,6 @@ CreateIndex CreateIndex(): List name; } { - [ parameter=CreateParameter() ] index = Index() { index.setType(parameter.isEmpty()?null:parameter.get(0)); } @@ -5036,7 +5001,7 @@ CreateSchema CreateSchema(): List statements = new ArrayList(); } { - + [ ( tk= | tk=) { schema.setSchemaName(tk.image); } ] [ (tk= | tk=) { schema.setAuthorization(tk.image); } @@ -5045,13 +5010,14 @@ CreateSchema CreateSchema(): [schemaPath=PathSpecification() { schema.setSchemaPath(schemaPath); }] ( - LOOKAHEAD(3) - table = CreateTable() + + + table = CreateTable(false) { table.getTable().setSchemaName(schema.getSchemaName()); schema.addStatement(table); } - | view = CreateView() + | view = CreateView(false) { view.getView().setSchemaName(schema.getSchemaName()); schema.addStatement(view); @@ -5076,7 +5042,7 @@ List PathSpecification(): } } -CreateTable CreateTable(): +CreateTable CreateTable(boolean isUsingOrReplace): { CreateTable createTable = new CreateTable(); Table table = null; @@ -5111,8 +5077,7 @@ CreateTable CreateTable(): List columns = new ArrayList(); } { - - [ { createTable.setOrReplace(true);} ] + { createTable.setOrReplace(isUsingOrReplace);} [ { createTable.setUnlogged(true); } ] // table options, not required but 1 or none @@ -5209,10 +5174,10 @@ CreateTable CreateTable(): indexes.add(fkIndex); } [LOOKAHEAD(2) ( (tk= | tk=) action = Action() - { fkIndex.setReferentialAction(ReferentialAction.Type.valueOf(tk.image), action); } + { fkIndex.setReferentialAction(ReferentialAction.Type.from(tk.image), action); } )] [LOOKAHEAD(2) ( (tk= | tk=) action = Action() - { fkIndex.setReferentialAction(ReferentialAction.Type.valueOf(tk.image), action); } + { fkIndex.setReferentialAction(ReferentialAction.Type.from(tk.image), action); } )] ) | @@ -5346,7 +5311,7 @@ ColDataType ColDataType(): [LOOKAHEAD(2) "(" {tk2 =null;} ( ( ( tk= [ LOOKAHEAD(2) (tk2= | tk2=) ] ) | tk= | tk= | tk= ) { argumentsStringList.add(tk.image + (tk2!=null?" " + tk2.image:"")); } ["," {/*argumentsStringList.add(",");*/}] )* ")"] - [( "[" {tk=null;} [ tk= ] { array.add(tk!=null?Integer.valueOf(tk.image):null); } "]" )+ { colDataType.setArrayData(array); } ] + [ LOOKAHEAD(2) ( LOOKAHEAD(2) "[" {tk=null;} [ tk= ] { array.add(tk!=null?Integer.valueOf(tk.image):null); } "]" )+ { colDataType.setArrayData(array); } ] [LOOKAHEAD(2) (tk= | tk=) { colDataType.setCharacterSet(tk.image); } ] { @@ -5371,7 +5336,7 @@ Analyze Analyze(): } } -CreateView CreateView(): +CreateView CreateView(boolean isUsingOrReplace): { CreateView createView = new CreateView(); Table view = null; @@ -5380,8 +5345,7 @@ CreateView CreateView(): Token tk = null; } { - - [ { createView.setOrReplace(true);} ] + { createView.setOrReplace(isUsingOrReplace);} [ { createView.setForce(ForceOption.NO_FORCE); } | { createView.setForce(ForceOption.FORCE); } @@ -5392,7 +5356,7 @@ CreateView CreateView(): ] [ { createView.setMaterialized(true);} ] view=Table() { createView.setView(view); } - [LOOKAHEAD(3) (tk= | tk=) { createView.setAutoRefresh(AutoRefreshOption.valueOf(tk.image)); } ] + [LOOKAHEAD(3) (tk= | tk=) { createView.setAutoRefresh(AutoRefreshOption.from(tk.image)); } ] [LOOKAHEAD(3) {createView.setIfNotExists(true);}] [ columnNames = ColumnsNamesList() { createView.setColumnNames(columnNames); } ] @@ -5421,7 +5385,7 @@ ReferentialAction.Action Action(): { return action; } } -AlterView AlterView(): +AlterView AlterView(boolean useReplace): { AlterView alterView = new AlterView(); Table view = null; @@ -5429,8 +5393,7 @@ AlterView AlterView(): List columnNames = null; } { - ( ( ) | ( {alterView.setUseReplace(true);}) ) - view=Table() { alterView.setView(view); } + view=Table() { alterView.setView(view); alterView.setUseReplace(useReplace); } [ columnNames = ColumnsNamesList() { alterView.setColumnNames(columnNames); } ] select=Select() { alterView.setSelect(select); } @@ -5440,125 +5403,70 @@ AlterView AlterView(): List CreateParameter(): { String retval = ""; - Token tk = null; - Token tk2 = null; - StringBuilder identifier = new StringBuilder(""); + Token tk = null, tk2 = null; Expression exp = null; - List param = new ArrayList(); ColDataType colDataType; + + List param = new ArrayList(); } { + ( + // Postgres: nextval('public.actor_actor_id_seq'::regclass) + ( "(" tk= "::" colDataType = ColDataType() ")" ) + { + param.add("NextVal( " + tk.image + "::" + colDataType + ")" ); + } + | ( - (((tk= | tk=) { identifier.append(tk.image); } - ["." (tk2= | tk2=) { identifier.append("."); identifier.append(tk2.image); }]) - { param.add(identifier.toString()); }) - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - ("+" {retval = "+";} | "-" {retval = "-";})? - ( - tk= { retval += tk.image; } - | - tk= { retval += tk.image; } - ) - { param.add(retval); } - | - tk= ( - ("(" exp = Expression() ")") { param.add("AS"); param.add("(" + exp.toString() + ")");} - | - { param.add(tk.image);} - ) - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(new TimeKeyExpression(tk.image).toString()); } - | - "=" { param.add("="); } - | - LOOKAHEAD(3) retval=RelObjectName() { param.add("USING"); param.add("INDEX"); param.add("TABLESPACE"); param.add(retval); } - | - retval=RelObjectName() { param.add("TABLESPACE"); param.add(retval); } - | - retval=AList() { param.add(retval); } - | - ("(" exp = Expression() ")") { param.add("CHECK"); param.add("(" + exp.toString() + ")");} - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - tk= { param.add(tk.image); } - | - (tk= tk2=) { param.add(tk.image); param.add(tk2.image);} - | - ( exp=ArrayConstructor(true)) { param.add(exp.toString()); } - | - tk="::" colDataType = ColDataType() { param.add(tk.image); param.add(colDataType.toString()); } + (tk= | tk=) + { retval+=tk.image; } + + [ + "." + (tk2= | tk2=) + { retval+="."+tk2.image; } + ] + { param.add(retval); } + ) + | + LOOKAHEAD(3) [ { param.add("USING INDEX"); }] retval=RelObjectName() + { param.add("TABLESPACE " + retval); } + | + ( + tk= | tk= | tk= | tk= | tk= + | tk= | tk= | tk= | tk= | tk= | tk= + | tk= | tk= | tk= | tk= | tk= + | tk= | tk= | tk= | tk= | tk= + | tk= | tk= | tk= | tk= | tk= + | tk= | tk= | tk= | tk= | tk= + | tk= | tk= | tk= | tk= | tk= | tk= + | tk= + | tk="=" + ) + { param.add(tk.image); } + | + ( tk= | tk= | tk= ) [ LOOKAHEAD(2) "(" exp = Expression() ")" ] + { + param.add(tk.image); + if (exp!=null) { + param.add("(" + exp + ")"); + } + } + | + ( + [ ( tk="+" | tk="-" ) { retval = tk.image; } ] + tk= | tk= ) + { param.add( retval + tk.image ); } + | + retval=AList() { param.add(retval); } + | + (tk= tk2=) { param.add(tk.image); param.add(tk2.image);} + | + ( exp=ArrayConstructor(true)) { param.add(exp.toString()); } + | + tk="::" colDataType = ColDataType() { param.add(tk.image); param.add(colDataType.toString()); } + ) {return param;} } @@ -5940,10 +5848,10 @@ AlterExpression AlterExpression(): } [LOOKAHEAD(2) ( (tk= | tk=) action = Action() - { alterExp.setReferentialAction(ReferentialAction.Type.valueOf(tk.image), action); } + { alterExp.setReferentialAction(ReferentialAction.Type.from(tk.image), action); } )] [LOOKAHEAD(2) ( (tk= | tk=) action = Action() - { alterExp.setReferentialAction(ReferentialAction.Type.valueOf(tk.image), action); } + { alterExp.setReferentialAction(ReferentialAction.Type.from(tk.image), action); } )] ) | @@ -5966,10 +5874,10 @@ AlterExpression AlterExpression(): } [LOOKAHEAD(2) ( (tk= | tk=) action = Action() - { fkIndex.setReferentialAction(ReferentialAction.Type.valueOf(tk.image), action); } + { fkIndex.setReferentialAction(ReferentialAction.Type.from(tk.image), action); } )] [LOOKAHEAD(2) ( (tk= | tk=) action = Action() - { fkIndex.setReferentialAction(ReferentialAction.Type.valueOf(tk.image), action); } + { fkIndex.setReferentialAction(ReferentialAction.Type.from(tk.image), action); } )] constraints=AlterExpressionConstraintState() { alterExp.setConstraints(constraints); } ) @@ -6146,6 +6054,49 @@ AlterExpression AlterExpression(): } } +Statement Alter(): +{ + Statement statement; + List captureRest; +} +{ + ( + ( + + ( + statement = AlterTable() + | + statement = AlterSession() + | + statement = AlterView(false) + | + statement = AlterSystemStatement() + | + statement = AlterSequence() + | + captureRest = captureRest() + { + statement = new UnsupportedStatement("ALTER", captureRest); + } + ) + ) + | + ( + + ( + statement = AlterView(true) + | + captureRest = captureRest() + { + statement = new UnsupportedStatement("REPLACE", captureRest); + } + ) + ) + ) + { + return statement; + } +} Alter AlterTable(): { @@ -6155,7 +6106,7 @@ Alter AlterTable(): boolean usingIfExists = false; } { - + [ { alter.setUseOnly(true); } ] [ LOOKAHEAD(2) { usingIfExists = true; } ] @@ -6180,7 +6131,7 @@ AlterSession AlterSession(): Token token; } { - ( + ( ( ( { operation = AlterSessionOperation.ADVISE_COMMIT; } | { operation = AlterSessionOperation.ADVISE_ROLLBACK; } @@ -6246,7 +6197,7 @@ AlterSystemStatement AlterSystemStatement(): List parameters = new LinkedList(); } { - ( + ( ( "ARCHIVE" "LOG" { operation = AlterSystemOperation.ARCHIVE_LOG; } ) @@ -6592,7 +6543,6 @@ CreateSequence CreateSequence(): List sequenceParameters; } { - sequence=Sequence() { createSequence.setSequence(sequence); } sequenceParameters = SequenceParameters() { sequence.setParameters(sequenceParameters); } { @@ -6607,7 +6557,6 @@ AlterSequence AlterSequence(): List sequenceParameters; } { - sequence=Sequence() { alterSequence.setSequence(sequence); } sequenceParameters = SequenceParameters() { sequence.setParameters(sequenceParameters); } { @@ -6615,49 +6564,88 @@ AlterSequence AlterSequence(): } } -CreateFunctionalStatement CreateFunctionStatement(): +Statement Create(): +{ + boolean isUsingOrReplace=false; + Token tk; + Statement statement; + List captureRest; +} +{ + [ { isUsingOrReplace = true; } ] + ( + statement = CreateFunctionStatement(isUsingOrReplace) + | + statement = CreateSchema() + | + statement = CreateSequence() + | + statement = CreateSynonym(isUsingOrReplace) + | + LOOKAHEAD(3) statement = CreateTable(isUsingOrReplace) + | + LOOKAHEAD(2) statement = CreateView(isUsingOrReplace) + | + // @fixme: must appear with TRIGGER before INDEX or it will collide with INDEX's CreateParameter() production + ( tk= | tk= ) captureRest = captureRest() + { + statement = new UnsupportedStatement("CREATE " + tk.image, captureRest); + } + | + /* @fixme + * Create Index uses CreateParameter() which allows all kind of tokens + * it can conflict with other statements and must be at the end right now + */ + statement = CreateIndex() + | + captureRest = captureRest() + { + statement = new UnsupportedStatement("CREATE", captureRest); + } + ) + { + return statement; + } +} + +CreateFunctionalStatement CreateFunctionStatement(boolean isUsingOrReplace): { CreateFunctionalStatement type = null; List tokens = new LinkedList(); String statementType = null; - boolean orReplace = false; } { - [ { orReplace = true; } ] ( { statementType = "FUNCTION"; } | { statementType = "PROCEDURE"; } ) - tokens=captureRest() + tokens=captureFunctionBody() { if(statementType.equals("FUNCTION")) { - type = new CreateFunction(orReplace, tokens); + type = new CreateFunction(isUsingOrReplace, tokens); } if(statementType.equals("PROCEDURE")) { - type = new CreateProcedure(orReplace, tokens); + type = new CreateProcedure(isUsingOrReplace, tokens); } return type; } } -CreateSynonym CreateSynonym(): +CreateSynonym CreateSynonym(boolean isUsingOrReplace): { CreateSynonym createSynonym = new CreateSynonym(); Synonym synonym; - boolean orReplace = false; boolean publicSynonym = false; List data = new ArrayList(); } { - - [ { orReplace = true; } ] [ { publicSynonym = true; } ] synonym=Synonym() { createSynonym.setSynonym(synonym); } data = RelObjectNameList() { - createSynonym.setOrReplace(orReplace); + createSynonym.setOrReplace(isUsingOrReplace); createSynonym.setPublicSynonym(publicSynonym); createSynonym.setForList(data); return createSynonym; @@ -6695,10 +6683,47 @@ List captureRest() { Token tok; while(true) { tok = getToken(1); - if(tok.kind == EOF) { + int l = tokens.size(); + if( tok.kind == EOF ) { break; + } else if ( l>0 && ( tok.image.equals(".") || tokens.get(l-1).endsWith(".")) ) { + tokens.set(l-1, tokens.get(l-1) + tok.image); + } else { + tokens.add(tok.image); } - tokens.add(tok.image); + tok = getNextToken(); + } + return tokens; +} + +/** +* Reads the tokens of a function or procedure body. +* A function body can end in 2 ways: +* 1) BEGIN...END; +* 2) Postgres: $$...$$...; +*/ + +JAVACODE +List captureFunctionBody() { + List tokens = new LinkedList(); + Token tok; + boolean foundEnd = false; + while(true) { + tok = getToken(1); + int l = tokens.size(); + if( tok.kind == EOF || ( foundEnd && tok.kind == ST_SEMICOLON) ) { + if (tok.kind == ST_SEMICOLON) { + tokens.add(tok.image); + } + break; + } else if ( l>0 && ( tok.image.equals(".") || tokens.get(l-1).endsWith(".")) ) { + tokens.set(l-1, tokens.get(l-1) + tok.image); + } else { + tokens.add(tok.image); + } + foundEnd |= (tok.kind == K_END) + || ( tok.image.trim().startsWith("$$") && tok.image.trim().endsWith("$$")) ; + tok = getNextToken(); } return tokens; @@ -6719,3 +6744,94 @@ List captureUnsupportedStatementDeclaration() { } return tokens; } + +String IdentifierChain(): +{ + String identifierChain; + String part; +} +{ + identifierChain=RelObjectNameExt2() + ( "." part=RelObjectNameExt2() { identifierChain += "." + part; } )* + + { + return identifierChain; + } +} + +Expression CharacterPrimary(): +{ + Expression expression; +} +{ + ( + expression = TranscodingFunction() + | + expression = TrimFunction() + ) + // @todo + // @see https://manticore-projects.com/SQL2016Parser/syntax.html#character-value-function + // | character_substring_function + // | regular_expression_substring_function + // | regex_substring_function + // | fold + // | character_transliteration + // | regex_transliteration + // | character_overlay_function + // | normalize_function + // | specific_type_method + + { + return expression; + } +} + +TranscodingFunction TranscodingFunction(): +{ + Expression expression; + String transcodingName; +} +{ + "(" expression = Expression() transcodingName=IdentifierChain() ")" + + { + return new TranscodingFunction(expression, transcodingName); + } +} + +TrimFunction TrimFunction(): +{ + TrimFunction.TrimSpecification trimSpecification=null; + Expression expression = null; + boolean usesFrom = false; + Expression fromExpression = null; +} +{ + "(" + [ + LOOKAHEAD(2) ( + { trimSpecification = TrimFunction.TrimSpecification.LEADING; } + | + { trimSpecification = TrimFunction.TrimSpecification.TRAILING; } + | + { trimSpecification = TrimFunction.TrimSpecification.BOTH; } + ) + ] + + // This is not SQL:2016 compliant, but Postgres supports it + [ expression = Expression() ] + + [ + ( + "," + | + { usesFrom = true; } + ) + fromExpression = Expression() + ] + ")" + + { + return new TrimFunction(trimSpecification, expression, fromExpression, usesFrom); + } +} diff --git a/src/main/resources/rr/xhtml2rst.xsl b/src/main/resources/rr/xhtml2rst.xsl index 918685a4f..5d0132bad 100644 --- a/src/main/resources/rr/xhtml2rst.xsl +++ b/src/main/resources/rr/xhtml2rst.xsl @@ -9,7 +9,7 @@ #L% --> - + + + +.. raw:: html + + <div id="floating-toc"> + <div class="search-container"> + <input type="button" id="toc-hide-show-btn"></input> + <input type="text" id="toc-search" placeholder="Search" /> + </div> + <ul id="toc-list"></ul> + </div> + + + -******************** -Supported SQL Syntax -******************** +********************************************************************* +SQL Syntax |JSQLPARSER_SNAPSHOT_VERSION| +********************************************************************* The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. @@ -41,12 +56,10 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ====================================================================================================================== - - - + ====================================================================================================================== - + .. raw:: html @@ -92,12 +105,12 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
  • - + - - + + - +
  • diff --git a/src/site/sphinx/_static/floating_toc.css b/src/site/sphinx/_static/floating_toc.css new file mode 100644 index 000000000..7080e42fd --- /dev/null +++ b/src/site/sphinx/_static/floating_toc.css @@ -0,0 +1,83 @@ +/* Styling for the floating TOC */ +#floating-toc { + position: fixed; + top: 50%; + right: 20px; + transform: translateY(-50%); + background-color: rgba(255, 255, 255, 0.72); + border: 1px solid rgba(64, 64, 64, 0.2); /* Set the border style */ + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + z-index: 9999; + height: 66%; + overflow-y: hide; + overflow-x: auto; + width: 240px; +} + +/* Styling for TOC list items */ +#floating-toc ul { + list-style-type: none; + padding-left: 26px; + margin-top: 36px; + line-height: 2px; +} + +/* Styling for heading levels in TOC */ +#floating-toc ul li { + /* no line breaks please */ + width: 250%; +} + +#floating-toc ul li a { + font-size: 14px; + font-weight: normal; +} + +#floating-toc ul li h1 a { + font-weight: bold; + font-size: 16px; +} + +#floating-toc ul li h2 a { + font-weight: bold; +} + +#floating-toc ul li h3 a { + font-style: italic; +} + + +/* Styling for search input */ +#floating-toc .search-container { + position: sticky; + top: 6px; + padding: 0px; +} + +#floating-toc input[type="text"] { + width: 186px; + height: 24px; + box-sizing: border-box; + background-color: rgba(255, 255, 255, 1.00); + color: rgba(128, 128, 128, 1.0); /* Set the text color */ + border: 1px solid rgba(0, 0, 0, 0.2); /* Set the border style */ + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +} + + +#floating-toc input[type="button"] { + position: float; + width: 24px; + height: 24px; + padding: 0; + margin: 0; + box-sizing: border-box; + background-color: rgba(255, 255, 255, 0.72); + color: rgba(128, 128, 128, 1.0); /* Set the text color */ + border: 0px solid rgba(0, 0, 0, 0.2); /* Set the border style */ +} + +/* Highlighting current caption in TOC */ +#floating-toc ul li a.active { + font-weight: bold; +} diff --git a/src/site/sphinx/_static/floating_toc.js b/src/site/sphinx/_static/floating_toc.js new file mode 100644 index 000000000..eb2aeab20 --- /dev/null +++ b/src/site/sphinx/_static/floating_toc.js @@ -0,0 +1,98 @@ +// JavaScript code for creating the floating TOC +window.addEventListener('DOMContentLoaded', function() { + var tocContainer = document.getElementById('floating-toc'); + var showBtn = document.getElementById('toc-hide-show-btn'); + var tocList = document.getElementById('toc-list'); + var headings = document.querySelectorAll('h1, h2, h3'); + var tocLevels = [0, 0, 0]; + + // Calculate the initial position of the TOC + const tocContainerRect = tocContainer.getBoundingClientRect(); + const tocContainerRight = tocContainer.style.right; + const buttonText = document.getElementById('buttonText'); + + headings.forEach(function(heading) { + var level = parseInt(heading.tagName.substr(1), 10) - 1; + + tocLevels[level]++; + for (var i = level + 1; i < 3; i++) { + tocLevels[i] = 0; + } + + var listItem = document.createElement('li'); + var link = document.createElement('a'); + + var number = tocLevels.slice(0, level + 1).join('.') + ' '; + link.textContent = number + heading.textContent.trim().replace(/#$/, '').replace(/¶$/, ''); + + var headingId = 'heading-' + Math.random().toString(36).substr(2, 9); + heading.setAttribute('id', headingId); + link.href = '#' + headingId; + + var styledHeading = document.createElement('h' + (level + 1)); + styledHeading.appendChild(link); + listItem.appendChild(styledHeading); + + tocList.appendChild(listItem); + }); + + // Toggle TOC visibility + showBtn.addEventListener('click', function() { + if (tocContainer.style.right != tocContainerRight) { + tocContainer.style.right = tocContainerRight; + // buttonText.innerText="H"; + } else { + tocContainer.style.right = `-${tocContainerRect.width-26}px`; + // buttonText.innerText="S"; + }; + }); + + // JavaScript code for searching the TOC + var searchInput = document.getElementById('toc-search'); + var tocItems = Array.from(tocList.getElementsByTagName('li')); + + searchInput.addEventListener('input', function() { + var searchValue = this.value.toLowerCase(); + + tocItems.forEach(function(item) { + var link = item.querySelector('a'); + var linkText = link.textContent.toLowerCase(); + + if (linkText.includes(searchValue)) { + item.style.display = 'block'; + } else { + item.style.display = 'none'; + } + }); + }); + + // JavaScript code for updating the floating TOC on scroll + window.addEventListener('scroll', function() { + var scrollPosition = window.pageYOffset || document.documentElement.scrollTop; + + var visibleHeading = null; + headings.forEach(function(heading) { + var rect = heading.getBoundingClientRect(); + if (rect.top > 0 && rect.top < window.innerHeight) { + visibleHeading = heading; + return; + } + }); + + if (visibleHeading) { + var activeLink = tocList.querySelector('a[href="#' + visibleHeading.id + '"]'); + if (activeLink) { + activeLink.classList.add('active'); + tocContainer.scrollTop = activeLink.offsetTop - tocContainer.offsetTop; + } + + // Remove 'active' class from other links + var allLinks = tocList.querySelectorAll('a'); + allLinks.forEach(function(link) { + if (link !== activeLink) { + link.classList.remove('active'); + } + }); + } + }); +}); diff --git a/src/site/sphinx/_static/svg.css b/src/site/sphinx/_static/svg.css index 919a09e2a..bd6b55128 100644 --- a/src/site/sphinx/_static/svg.css +++ b/src/site/sphinx/_static/svg.css @@ -7,10 +7,10 @@ div .ebnf } @namespace "http://www.w3.org/2000/svg"; - .line {fill: none; stroke: #001133; stroke-width: 1;} + .line {fill: none; stroke: #0063db; stroke-width: 1;} .bold-line {stroke: #000714; shape-rendering: crispEdges; stroke-width: 2;} .thin-line {stroke: #000A1F; shape-rendering: crispEdges;} - .filled {fill: #001133; stroke: none;} + .filled {fill: #0063db; stroke: none;} text.terminal {font-family: Roboto, Sans-serif; font-size: 10px; fill: #000714; @@ -26,9 +26,9 @@ div .ebnf fill: #000A1F; font-weight: normal; } - rect, circle, polygon {fill: #001133; stroke: #001133;} - rect.terminal {fill: #4D88FF; stroke: #001133; stroke-width: 1;} - rect.nonterminal {fill: #9EBFFF; stroke: #001133; stroke-width: 1;} + rect, circle, polygon {fill: #0063db; stroke: #0063db;} + rect.terminal {fill: #4D88FF; stroke: #0063db; stroke-width: 1;} + rect.nonterminal {fill: #9EBFFF; stroke: #0063db; stroke-width: 1;} rect.text {fill: none; stroke: none;} - polygon.regexp {fill: #C7DAFF; stroke: #001133; stroke-width: 1;} + polygon.regexp {fill: #C7DAFF; stroke: #0063db; stroke-width: 1;} diff --git a/src/site/sphinx/_static/tabs.css b/src/site/sphinx/_static/tabs.css deleted file mode 100644 index 371024886..000000000 --- a/src/site/sphinx/_static/tabs.css +++ /dev/null @@ -1,89 +0,0 @@ -.sphinx-tabs { - margin-bottom: 1rem; -} - -[role="tablist"] { - border-bottom: 1px solid rgb(3, 1, 70); -} - -.sphinx-tabs-tab { - position: relative; - font-family: Roboto,sans-serif; - color: rgb(3, 1, 70); - line-height: 24px; - margin: 0; - font-size: 16px; - font-weight: 400; - background-color: rgba(255, 255, 255, 0); - border-radius: 5px 5px 0 0; - border: 0; - padding: 1rem 1.5rem; - margin-bottom: 0; -} - -.sphinx-tabs-tab[aria-selected="true"] { - font-weight: 700; - border: 1px solid rgb(3, 1, 70); - border-bottom: 1px solid white; - margin: -1px; - background-color: white; -} - -.sphinx-tabs-tab:focus { - z-index: 1; - outline-offset: 1px; -} - -.sphinx-tabs-panel { - position: relative; - padding: 1rem; - border: 1px solid rgb(3, 1, 70); - margin: 0px -1px -1px -1px; - border-radius: 0 0 5px 5px; - border-top: 0; - background: white; -} - -.sphinx-tabs-panel.code-tab { - padding: 0.4rem; -} - -.sphinx-tab img { - margin-bottom: 24 px; -} - -/* Dark theme preference styling */ - -@media (prefers-color-scheme: dark) { - body[data-theme="auto"] .sphinx-tabs-panel { - color: white; - background-color: rgb(3, 1, 70); - } - - body[data-theme="auto"] .sphinx-tabs-tab { - color: white; - background-color: rgba(255, 255, 255, 0.05); - } - - body[data-theme="auto"] .sphinx-tabs-tab[aria-selected="true"] { - border-bottom: 1px solid rgb(3, 1, 70); - background-color: rgb(3, 1, 70); - } -} - -/* Explicit dark theme styling */ - -body[data-theme="dark"] .sphinx-tabs-panel { - color: white; - background-color: rgb(3, 1, 70); -} - -body[data-theme="dark"] .sphinx-tabs-tab { - color: white; - background-color: rgba(255, 255, 255, 0.05); -} - -body[data-theme="dark"] .sphinx-tabs-tab[aria-selected="true"] { - border-bottom: 2px solid rgb(3, 1, 70); - background-color: rgb(3, 1, 70); -} diff --git a/src/site/sphinx/changelog.rst b/src/site/sphinx/changelog.rst index bfbe03195..427db83c8 100644 --- a/src/site/sphinx/changelog.rst +++ b/src/site/sphinx/changelog.rst @@ -8,69 +8,225 @@ Latest Changes since |JSQLPARSER_VERSION| ============================================================= - * **feat: Refactor SelectBody implementations** + * **build: improve Upload task** - Andreas Reichel, 2023-03-27 - * **feat: Refactor SelectBody implementations** + Andreas Reichel, 2023-05-19 + * **feat: Quoted Identifiers can contain double-quotes (PostgreSQL)** - Andreas Reichel, 2023-03-26 - * **style: Appease PMD/Codacy** + Andreas Reichel, 2023-05-18 + * **feat: functions blocks, parenthesed JSON Expressions** - Andreas Reichel, 2023-03-25 - * **style: Appease PMD/Codacy** + Andreas Reichel, 2023-05-18 + * **feat: functions blocks, parenthesed JSON Expressions** - Andreas Reichel, 2023-03-25 - * **feat: ParenthesedSelectBody and ParenthesedFromItem** + Andreas Reichel, 2023-05-18 + * **feat: parse CREATE TRIGGER as UnsupportedStatement** - Andreas Reichel, 2023-03-25 - * **feat: ParenthesedSelectBody and ParenthesedFromItem** + Andreas Reichel, 2023-05-17 + * **build: try to work around the Maven/JDK8 issue on GitHub** - Andreas Reichel, 2023-03-24 - * **feat: ParenthesedSelectBody and ParenthesedFromItem** + Andreas Reichel, 2023-05-17 + * **refact: Statements extends List** - Andreas Reichel, 2023-03-23 - * **feat: ParenthesedSelectBody and ParenthesedFromItem** + Andreas Reichel, 2023-05-17 + * **style: remove unused imports** - Andreas Reichel, 2023-03-23 - * **feat: ParenthesedSelectBody and ParenthesedFromItem** + Andreas Reichel, 2023-05-17 + * **feat: chaining JSON Expressions** - Andreas Reichel, 2023-03-23 - * **feat: ParenthesedSelectBody and ParenthesedFromItem** + Andreas Reichel, 2023-05-17 + * **style: Cosmetic improvements** - Andreas Reichel, 2023-03-23 - * **Assorted Fixes #7 (#1745)** + Andreas Reichel, 2023-05-17 + * **style: Quieten the logger** - manticore-projects, 2023-03-21 - * **disable xml report (#1748)** + Andreas Reichel, 2023-05-17 + * **fix: Complex Parsing Approach** - optimizing-ci-builds, 2023-03-21 - * **build: better Upload Groovy Task** + Andreas Reichel, 2023-05-17 + * **refactor: CREATE and ALTER productions** - Andreas Reichel, 2023-03-18 - * **doc: fix reference in the Java Doc** + Andreas Reichel, 2023-05-16 + * **refactor: RETURNING clause** - Andreas Reichel, 2023-03-18 - * **feat: `ConflictTarget` allows multiple `IndexColumnNames`** + Andreas Reichel, 2023-05-16 + * **refactor: SHOW statement, supporting any RDBMS specific implementation** - Andreas Reichel, 2023-03-18 - * **style: Appease PMD/Codacy** + Andreas Reichel, 2023-05-16 + * **refactor: simplify production `CreateParameter()`** + + Andreas Reichel, 2023-05-16 + * **fix: issue #1789** + + Andreas Reichel, 2023-05-16 + * **fix: issue #1789** + + Andreas Reichel, 2023-05-16 + * **fix: issue #1791** + + Andreas Reichel, 2023-05-15 + * **build: improve the GIT Snapshot detection** + + Andreas Reichel, 2023-05-15 + * **build: Sphinx build fixes** + + Andreas Reichel, 2023-05-14 + * **build: Sphinx build fixes** + + Andreas Reichel, 2023-05-14 + * **build: Sphinx build fixes** + + Andreas Reichel, 2023-05-14 + * **Update sphinx.yml** + + manticore-projects, 2023-05-14 + * **feat: Write API documentation to the WebSite via XMLDoclet** + + Andreas Reichel, 2023-05-14 + * **test: add unit test for issue #1778** + + Andreas Reichel, 2023-05-11 + * **style: appease PMD/Codacy** + + Andreas Reichel, 2023-05-11 + * **style: appease PMD/Codacy** + + Andreas Reichel, 2023-05-11 + * **feat: `MEMBER OF` condition as shown at https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_member-of** + + Andreas Reichel, 2023-05-11 + * **feat: access Elements of Array Columns** + + Andreas Reichel, 2023-05-11 + * **feat: JdbcNamedParameter allows "&" (instead of ":")** + + Andreas Reichel, 2023-05-11 + * **fix: Java Version 8** + + Andreas Reichel, 2023-05-09 + * **refactor: generify `SelectItem` and remove `FunctionItem` and `ExpressionListItem`** + + Andreas Reichel, 2023-05-09 + * **style: replace all List with ExpressionList<> and enforce policy via Acceptance Test** + + Andreas Reichel, 2023-05-09 + * **fix: find the correct position when field belongs to an internal class** + + Andreas Reichel, 2023-05-09 + * **style: Appease PMD** + + Andreas Reichel, 2023-05-07 + * **style: Appease Checkstyle** + + Andreas Reichel, 2023-05-07 + * **test: Disable API Sanitation for the moment** + + Andreas Reichel, 2023-05-07 + * **refactor: `Insert` uses `ExpressionList` and `UpdateSet`** + + Andreas Reichel, 2023-05-07 + * **build: improve Gradle Build** + + Andreas Reichel, 2023-05-07 + * **refactor: remove SimpleFunction** - Andreas Reichel, 2023-03-17 - * **style: expose `SetStatement` key-value list** + Andreas Reichel, 2023-05-06 + * **doc: RR chart colors cater for Dark Mode** - Andreas Reichel, 2023-03-17 - * **feat: Add support for Hangul "\uAC00"-"\uD7A3"** + Andreas Reichel, 2023-05-06 + * **doc: Better Sphinx Tabs** - Andreas Reichel, 2023-03-17 - * **style: Remove unused variable** + Andreas Reichel, 2023-05-06 + * **style: Rework all the ENUMs** - Andreas Reichel, 2023-03-14 - * **style: Reformat changed files and headers** + Andreas Reichel, 2023-05-05 + * **style: Appease Codacy** - Andreas Reichel, 2023-03-14 - * **fix: JSon Operator can use Simple Function** + Andreas Reichel, 2023-05-04 + * **refactor: Remove `ItemsList`, `MultiExpressionList`, `Replace`** - Andreas Reichel, 2023-03-14 + Andreas Reichel, 2023-05-04 + * **style: Checkstyle** + + Andreas Reichel, 2023-05-03 + * **style: Appease Codacy** + + Andreas Reichel, 2023-05-03 + * **build: Increase TimeOut for the GitHub CI** + + Andreas Reichel, 2023-05-03 + * **refactor: UpdateSets for `Update` and `InsertConflictTarget`** + + Andreas Reichel, 2023-05-03 + * **fix: Remove tests for `()`, since `ParenthesedExpressionList` will catch those too** + + Andreas Reichel, 2023-05-03 + * **feat: Consolidate the `ExpressionList`, removing many redundant List alike Classes and Productions** + + Andreas Reichel, 2023-05-03 + * **fix: assign Enum case insensitive** + + Andreas Reichel, 2023-05-02 + * **doc: Update the README.md** + + Andreas Reichel, 2023-05-01 + * **build: Add missing import** + + Andreas Reichel, 2023-04-30 + * **doc: Update examples** + + Andreas Reichel, 2023-04-30 + * **refactor: remove `SelectExpressionItem` in favor of `SelectItem`** + + Andreas Reichel, 2023-04-30 + * **test: add specific tests for closed issues** + + Andreas Reichel, 2023-04-30 + * **test: add specific tests for closed issues** + + Andreas Reichel, 2023-04-30 + * **feat: ClickHouse `LIMIT ... BY ...` clause** + + Andreas Reichel, 2023-04-30 + * **feat: implement SQL:2016 Convert() and Trim()** + + Andreas Reichel, 2023-04-30 + * **feat: Switch off contradicting `JOIN` qualifiers, when setting a qualifier** + + Andreas Reichel, 2023-04-30 + * **feat: Test if a JOIN is an INNER JOIN according to the SQL:2016** + + Andreas Reichel, 2023-04-30 + * **feat: ClickHouse `Select...` ``FINAL` modifier** + + Andreas Reichel, 2023-04-29 + * **feat: Multi-Part Names for Variables and Parameters** + + Andreas Reichel, 2023-04-29 + * **feat: Oracle `HAVING` before `GROUP BY`** + + Andreas Reichel, 2023-04-29 + * **feat: Lateral View** + + Andreas Reichel, 2023-04-29 + * **Fix #1758: Use long for Feature.timeOut (#1759)** + + Tomasz Zarna, 2023-04-27 + * **Ignoring unnecessarily generated jacoco report (#1762)** + + optimizing-ci-builds, 2023-04-27 + * **Ignoring unnecessarily generated by pmd plugin (#1763)** + + optimizing-ci-builds, 2023-04-27 + * **Refactor Parenthesed SelectBody and FromItem (#1754)** + + manticore-projects, 2023-04-27 + * **Assorted Fixes #7 (#1745)** + + manticore-projects, 2023-03-21 + * **disable xml report (#1748)** + + optimizing-ci-builds, 2023-03-21 * **Assorted Fixes #6 (#1740)** manticore-projects, 2023-03-09 diff --git a/src/site/sphinx/conf.py b/src/site/sphinx/conf.py index b757400c7..29ab663cf 100644 --- a/src/site/sphinx/conf.py +++ b/src/site/sphinx/conf.py @@ -4,19 +4,19 @@ needs_sphinx = '1.0' add_function_parentheses = True -extensions = ['myst_parser', 'sphinx.ext.autodoc', 'sphinx.ext.autosectionlabel', 'sphinx.ext.extlinks', 'sphinx-prompt', 'sphinx_substitution_extensions', 'sphinx_issues', 'sphinx_tabs.tabs', 'pygments.sphinxext', ] +extensions = ['myst_parser', 'sphinx.ext.autodoc', 'sphinx.ext.autosectionlabel', 'sphinx.ext.extlinks', 'sphinx-prompt', 'sphinx_substitution_extensions', 'sphinx_inline_tabs', 'pygments.sphinxext', ] issues_github_path = "JSQLParser/JSqlParser" source_encoding = 'utf-8-sig' -pygments_style = 'friendly' +#pygments_style = 'friendly' show_sphinx = False master_doc = 'index' exclude_patterns = ['_themes', '_static/css'] logo_only = True # HTML options -html_theme = "sphinx_book_theme" +html_theme = "furo" html_theme_path = ["_themes"] html_short_title = "JSQLParser" htmlhelp_basename = "JSQLParser" + '-doc' @@ -25,8 +25,8 @@ html_static_path = ['_static'] html_logo = '_images/logo-no-background.svg' html_favicon = '_images/favicon.svg' -html_css_files = ["svg.css"] - +html_css_files = ['svg.css', 'floating_toc.css'] +html_js_files = ['floating_toc.js',] html_theme_options = { 'path_to_docs': 'site/sphinx', diff --git a/src/site/sphinx/contribution.rst b/src/site/sphinx/contribution.rst index 4309b23b0..e9c93827f 100644 --- a/src/site/sphinx/contribution.rst +++ b/src/site/sphinx/contribution.rst @@ -92,19 +92,18 @@ There is a task ``updateKeywords`` for Gradle and Maven, which will: 5) Run two special Unit Tests to verify parsing of all ``White-Listed Keywords`` (as `Schema`, `Table`, `Column`, `Function` or `Alias`) 6) Update the web page about the Reserved Keywords -.. tabs:: - .. tab:: Gradle - .. code-block:: shell - :caption: Gradle `updateKeywords` Task +.. tab:: Gradle + .. code-block:: shell + :caption: Gradle `updateKeywords` Task - gradle updateKeywords + gradle updateKeywords - .. tab:: Maven - .. code-block:: shell - :caption: Maven `updateKeywords` Task +.. tab:: Maven + .. code-block:: shell + :caption: Maven `updateKeywords` Task - mvn exec:java + mvn exec:java Without this Gradle Task, any new Token or Production will become a ``Reserved Keyword`` automatically and can't be used for Object Names without quoting. diff --git a/src/site/sphinx/index.rst b/src/site/sphinx/index.rst index a20944280..c2294c131 100644 --- a/src/site/sphinx/index.rst +++ b/src/site/sphinx/index.rst @@ -1,3 +1,7 @@ +.. meta:: + :description: Java Software Library for parsing SQL Statements into Abstract Syntax Trees (AST) and manipulation of SQL Statements + :keywords: java sql statement parser abstract syntax tree + ########################### Java SQL Parser Library ########################### @@ -8,7 +12,10 @@ Java SQL Parser Library usage contribution - syntax + syntax_stable + syntax_snapshot + javadoc_stable + javadoc_snapshot keywords changelog @@ -33,7 +40,7 @@ Latest stable release: |JSQLPARSER_STABLE_VERSION_LINK| Development version: |JSQLPARSER_SNAPSHOT_VERSION_LINK| -.. sidebar:: Java SQL Object Hierarchy +.. sidebar:: Java API Website .. image:: _images/JavaAST.png diff --git a/src/site/sphinx/keywords.rst b/src/site/sphinx/keywords.rst index f0e8f7156..54b4d34c9 100644 --- a/src/site/sphinx/keywords.rst +++ b/src/site/sphinx/keywords.rst @@ -49,6 +49,8 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | FETCH | Yes | Yes | +----------------------+-------------+-----------+ +| FINAL | Yes | Yes | ++----------------------+-------------+-----------+ | FOR | Yes | Yes | +----------------------+-------------+-----------+ | FORCE | Yes | Yes | diff --git a/src/site/sphinx/syntax.rst b/src/site/sphinx/syntax_stable.rst similarity index 77% rename from src/site/sphinx/syntax.rst rename to src/site/sphinx/syntax_stable.rst index 15c299280..8ea321548 100644 --- a/src/site/sphinx/syntax.rst +++ b/src/site/sphinx/syntax_stable.rst @@ -1,16 +1,16 @@ -******************** -Supported SQL Syntax -******************** +********************************************************************* +SQL Syntax |JSQLPARSER_VERSION| Release +********************************************************************* The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ====================================================================================================================== - Statement +Statement ====================================================================================================================== - + .. raw:: html @@ -38,7 +38,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. UnsupportedStatement -
    +
             ::= ( 'IF' Condition ( ( SingleStatement | Block ) ST_SEMICOLON? 'ELSE' )? )? ( SingleStatement | Block ) ST_SEMICOLON? EOF
    @@ -49,13 +49,13 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ====================================================================================================================== - SingleStatement +SingleStatement ====================================================================================================================== - + .. raw:: html - + @@ -73,100 +73,62 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Select - Upsert - - AlterTable - - AlterSession - - CreateFunctionStatement - - CreateIndex - - CreateSchema - - CreateSequence - - CreateSynonym - - CreateTable - - CreateView - - AlterView - - AlterSequence - - Drop - - Analyze - - Truncate - - Execute - - Set - - RenameTableStatement - - Reset - - ShowColumns - - ShowIndex - - ShowTables - - Show - - Use - - SavepointStatement - - RollbackStatement - COMMIT - - Comment - - Describe - - Explain - - Declare - - Grant - - PurgeStatement - - AlterSystemStatement + Upsert + + Alter + + RenameTableStatement + + Create + + Drop + + Analyze + + Truncate + + Execute + + Set + + Reset + + Show + + Use + + SavepointStatement + + RollbackStatement + COMMIT + + Comment + + Describe + + Explain + + Declare + + Grant + + PurgeStatement -
    +
             ::= WithList? ( SelectWithWithItems | Insert | Update | Delete | Merge )
               | Select
               | Upsert
    -
               | AlterTable
    -
               | AlterSession
    -
               | CreateFunctionStatement
    -
               | CreateIndex
    -
               | CreateSchema
    -
               | CreateSequence
    -
               | CreateSynonym
    -
               | CreateTable
    -
               | CreateView
    -
               | AlterView
    -
               | AlterSequence
    +
               | Alter
    +
               | RenameTableStatement
    +
               | Create
               | Drop
               | Analyze
               | Truncate
               | Execute
               | Set
    -
               | RenameTableStatement
               | Reset
    -
               | ShowColumns
    -
               | ShowIndex
    -
               | ShowTables
               | Show
               | Use
               | SavepointStatement
    @@ -177,18 +139,17 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | Explain
               | Declare
               | Grant
    -
               | PurgeStatement
    -
               | AlterSystemStatement
    +
               | PurgeStatement
    Referenced by: -
    +
    ====================================================================================================================== - Block +Block ====================================================================================================================== - + .. raw:: html @@ -208,19 +169,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ST_SEMICOLON -
    +
    Block    ::= 'BEGIN' ST_SEMICOLON* ( ( SingleStatement | Block ) ST_SEMICOLON )+ 'END' ST_SEMICOLON?
    Referenced by: -
    +
    ====================================================================================================================== - Statements +Statements ====================================================================================================================== - + .. raw:: html @@ -277,7 +238,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. EOF -
    +
    @@ -287,10 +248,10 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ====================================================================================================================== - Declare +Declare ====================================================================================================================== - + .. raw:: html @@ -322,22 +283,22 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. , -
    +
    Declare  ::= 'DECLARE' UserVariable ( 'TABLE' '(' ColumnDefinition ( ',' ColumnDefinition )* ')' | 'AS' RelObjectName | ColDataType ( '=' Expression )? ( ',' UserVariable ColDataType ( '=' Expression )? )* )
    Referenced by: -
    +
    ====================================================================================================================== - Set +Set ====================================================================================================================== - + .. raw:: html - + @@ -350,34 +311,34 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. K_DATETIMELITERAL ZONE - UserVariable - - RelObjectNameExt - = - - Expression - ZONE - - K_DATETIMELITERAL - = - - RelObjectNameExt - , - - -
    + UserVariable + + IdentifierChain + = + + Expression + ZONE + + K_DATETIMELITERAL + = + + RelObjectNameExt + , + + +
    -
    Set      ::= 'SET' ( 'LOCAL' | 'SESSION' )? ( K_DATETIMELITERAL 'ZONE' | ( UserVariable | RelObjectNameExt ) '='? ) Expression ( ',' ( K_DATETIMELITERAL 'ZONE' | RelObjectNameExt '='? )? Expression )*
    +
    Set      ::= 'SET' ( 'LOCAL' | 'SESSION' )? ( K_DATETIMELITERAL 'ZONE' | ( UserVariable | IdentifierChain ) '='? ) Expression ( ',' ( K_DATETIMELITERAL 'ZONE' | RelObjectNameExt '='? )? Expression )*
    Referenced by: -
    +
    ====================================================================================================================== - Reset +Reset ====================================================================================================================== - + .. raw:: html @@ -393,19 +354,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ALL -
    +
    Reset    ::= 'RESET' ( K_DATETIMELITERAL 'ZONE' | RelObjectName | 'ALL' )
    Referenced by: -
    +
    ====================================================================================================================== - RenameTableStatement +RenameTableStatement ====================================================================================================================== - + .. raw:: html @@ -434,20 +395,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. , -
    +
             ::= 'RENAME' 'TABLE'? ( 'IF' 'EXISTS' )? Table ( 'WAIT' S_LONG | 'NOWAIT' )? 'TO' Table ( ',' Table 'TO' Table )*
    Referenced by: -
    +
    ====================================================================================================================== - PurgeStatement +PurgeStatement ====================================================================================================================== - + .. raw:: html @@ -473,20 +434,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. S_IDENTIFIER -
    +
             ::= 'PURGE' ( 'TABLE' Table | 'INDEX' Index | 'RECYCLEBIN' | 'DBA_RECYCLEBIN' | 'TABLESPACE' S_IDENTIFIER ( 'USER' S_IDENTIFIER )? )
    Referenced by: -
    +
    ====================================================================================================================== - Describe +Describe ====================================================================================================================== - + .. raw:: html @@ -497,19 +458,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Table -
    +
    Describe ::= 'DESCRIBE' Table
    Referenced by: -
    +
    ====================================================================================================================== - Explain +Explain ====================================================================================================================== - + .. raw:: html @@ -522,19 +483,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Select -
    +
    Referenced by: -
    +
    ====================================================================================================================== - ExplainOptionBoolean +ExplainOptionBoolean ====================================================================================================================== - + .. raw:: html @@ -550,20 +511,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. OFF -
    +
             ::= ( 'TRUE' | 'FALSE' | 'ON' | 'OFF' )?
    Referenced by: -
    +
    ====================================================================================================================== - ExplainFormatOption +ExplainFormatOption ====================================================================================================================== - + .. raw:: html @@ -577,20 +538,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. YAML -
    +
             ::= ( 'XML' | 'JSON' | 'YAML' )?
    Referenced by: -
    +
    ====================================================================================================================== - ExplainStatementOptions +ExplainStatementOptions ====================================================================================================================== - + .. raw:: html @@ -610,20 +571,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ExplainFormatOption -
    +
             ::= ( ( 'ANALYZE' | 'BUFFERS' | 'COSTS' | 'VERBOSE' ) ExplainOptionBoolean | 'FORMAT' ExplainFormatOption )*
    Referenced by: -
    +
    ====================================================================================================================== - Use +Use ====================================================================================================================== - + .. raw:: html @@ -636,260 +597,291 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. RelObjectNameExt -
    +
    Use      ::= 'USE' 'SCHEMA'? RelObjectNameExt
    Referenced by: -
    +
    ====================================================================================================================== - ShowColumns +Show ====================================================================================================================== - + .. raw:: html - + - SHOW - - COLUMNS - - FROM - - RelObjectNameExt - -
    + SHOW + + ShowColumns + + ShowIndex + + ShowTables + + captureRest + +
    - -
             ::= 'SHOW' 'COLUMNS' 'FROM' RelObjectNameExt
    +
    Show     ::= 'SHOW' ( ShowColumns | ShowIndex | ShowTables | captureRest )
    Referenced by: -
    +
    ====================================================================================================================== - ShowIndex +ShowColumns ====================================================================================================================== - + .. raw:: html - + - - SHOW - - INDEX - - FROM - - RelObjectNameExt - -
    + + COLUMNS + + FROM + + RelObjectNameExt + +
    - -
             ::= 'SHOW' 'INDEX' 'FROM' RelObjectNameExt
    + +
             ::= 'COLUMNS' 'FROM' RelObjectNameExt
    Referenced by: -
    +
    ====================================================================================================================== - ShowTables +ShowIndex ====================================================================================================================== - + .. raw:: html - + - - SHOW - - EXTENDED - - FULL - - TABLES - - FROM - - IN - - RelObjectNameExt - LIKE - - SimpleExpression - WHERE - - Expression - -
    + + INDEX + + FROM + + RelObjectNameExt + +
    - -
             ::= 'SHOW' 'EXTENDED'? 'FULL'? 'TABLES' ( ( 'FROM' | 'IN' ) RelObjectNameExt )? ( 'LIKE' SimpleExpression | 'WHERE' Expression )?
    + +
             ::= 'INDEX' 'FROM' RelObjectNameExt
    Referenced by: -
    +
    ====================================================================================================================== - Show +ShowTables ====================================================================================================================== - + .. raw:: html - + - - SHOW - - RelObjectNameExt - -
    + + EXTENDED + + FULL + + TABLES + + FROM + + IN + + RelObjectNameExt + LIKE + + SimpleExpression + WHERE + + Expression + +
    -
    Show     ::= 'SHOW' RelObjectNameExt
    + +
             ::= 'EXTENDED'? 'FULL'? 'TABLES' ( ( 'FROM' | 'IN' ) RelObjectNameExt )? ( 'LIKE' SimpleExpression | 'WHERE' Expression )?
    Referenced by: -
    +
    ====================================================================================================================== - Values +Values ====================================================================================================================== - + .. raw:: html - + VALUES - VALUE - - SimpleExpressionList - -
    + VALUE + + ExpressionList + +
    -
    Values   ::= ( 'VALUES' | 'VALUE' ) SimpleExpressionList
    +
    Values   ::= ( 'VALUES' | 'VALUE' ) ExpressionList
    Referenced by: -
    +
    ====================================================================================================================== - Update +ReturningClause ====================================================================================================================== - + .. raw:: html - - - - - UPDATE - - LOW_PRIORITY - - IGNORE - - TableWithAlias - - JoinsList - SET - - Column - = - - SimpleExpression - , - - ( - - Column - , - - ) - - = - - ParenthesedSelectBody - ( - - ComplexExpressionList - ) - - Expression - , - - OutputClause - FROM - - FromItem - - JoinsList - - WhereClause - - OrderByElements - - PlainLimit - RETURNING - - SelectItemsList - -
    - -
    Update   ::= 'UPDATE' 'LOW_PRIORITY'? 'IGNORE'? TableWithAlias JoinsList? 'SET' ( Column '=' SimpleExpression ( ',' Column '=' SimpleExpression )* | '('? Column ( ',' Column )* ')'? '=' ( ParenthesedSelectBody | '(' ComplexExpressionList ')' | Expression ) ( ',' '('? Column ( ',' Column )* ')'? '=' ( ParenthesedSelectBody | '(' ComplexExpressionList ')' | Expression ) )* ) OutputClause? ( 'FROM' FromItem JoinsList? )? WhereClause? OrderByElements? PlainLimit? ( 'RETURNING' SelectItemsList )?
    -
    - Referenced by: -
    - - -====================================================================================================================== - ListExpressionItem -====================================================================================================================== + + + + + RETURNING + + RETURN + + SelectItemsList + INTO + + Table + + UserVariable + , + + +
    + + +
             ::= ( 'RETURNING' | 'RETURN' ) SelectItemsList ( 'INTO' ( Table | UserVariable ) ( ',' ( Table | UserVariable ) )* )?
    +
    + Referenced by: +
    +====================================================================================================================== +Update +====================================================================================================================== + + .. raw:: html - - - - - SelectExpressionItem - , - - -
    + + + + + UPDATE + + LOW_PRIORITY + + IGNORE + + TableWithAlias + + JoinsList + SET + + UpdateSets + + OutputClause + FROM + + FromItem + + JoinsList + + WhereClause + + OrderByElements + + PlainLimit + + ReturningClause + +
    - -
             ::= SelectExpressionItem ( ',' SelectExpressionItem )*
    +
    - Not referenced by any. -
    + Referenced by: +
    ====================================================================================================================== - Insert +UpdateSets ====================================================================================================================== + +.. raw:: html + + + + + + Column + = + + Expression + + ParenthesedExpressionList + = + + ParenthesedSelect + + ParenthesedExpressionList + , + + Column + = + + Expression + + ParenthesedExpressionList + = + + ParenthesedSelect + + ParenthesedExpressionList + +
    + + + +
    + +====================================================================================================================== +Insert +====================================================================================================================== + + .. raw:: html - + @@ -908,63 +900,51 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Table AS - RelObjectNameWithoutValue - ( - - Column - , - - ) - - OutputClause - SET - - Column - = - - SimpleExpression - , - - Select - ON - - DUPLICATE - - KEY - - UPDATE - - Column - = - - SimpleExpression - , - - ON - - CONFLICT - - InsertConflictTarget - - InsertConflictAction - RETURNING - - SelectItemsList - -
    + RelObjectNameWithoutValue + ( + + ColumnList + ) + + OutputClause + SET + + UpdateSets + + Select + ON + + DUPLICATE + + KEY + + UPDATE + + UpdateSets + ON + + CONFLICT + + InsertConflictTarget + + InsertConflictAction + + ReturningClause + +
    Insert   ::= 'INSERT' ( 'LOW_PRIORITY' | 'DELAYED' | 'HIGH_PRIORITY' )? 'IGNORE'? 'INTO'? - Table ( 'AS'? RelObjectNameWithoutValue )? ( '(' Column ( ',' Column )* ')' )? OutputClause? ( 'SET' Column '=' SimpleExpression ( ',' Column '=' SimpleExpression )* | Select ) ( 'ON' 'DUPLICATE' 'KEY' 'UPDATE' Column '=' SimpleExpression ( ',' Column '=' SimpleExpression )* )? ( 'ON' 'CONFLICT' InsertConflictTarget? InsertConflictAction )? ( 'RETURNING' SelectItemsList )?
    + Table ( 'AS'? RelObjectNameWithoutValue )? ( '(' ColumnList ')' )? OutputClause? ( 'SET' UpdateSets | Select ) ( 'ON' 'DUPLICATE' 'KEY' 'UPDATE' UpdateSets )? ( 'ON' 'CONFLICT' InsertConflictTarget? InsertConflictAction )? ReturningClause?
    Referenced by: -
    +
    ====================================================================================================================== - InsertConflictTarget +InsertConflictTarget ====================================================================================================================== - + .. raw:: html @@ -985,75 +965,53 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. RelObjectNameExt2 -
    +
             ::= '(' RelObjectNameExt2 ( ',' RelObjectNameExt2 )* ')' WhereClause?
               | 'ON' 'CONSTRAINT' RelObjectNameExt2
    Referenced by: -
    +
    ====================================================================================================================== - InsertConflictAction +InsertConflictAction ====================================================================================================================== - + .. raw:: html - - - - - DO - - NOTHING - - UPDATE - - SET - - Column - = - - SimpleExpression - , - - ( - - Column - , - - ) - - = - - ParenthesedSelectBody - ( - - ComplexExpressionList - ) - - Expression - , - - WhereClause - -
    + + + + + DO + + NOTHING + + UPDATE + + SET + + UpdateSets + + WhereClause + +
    -
             ::= 'DO' ( 'NOTHING' | 'UPDATE' 'SET' ( Column '=' SimpleExpression ( ',' Column '=' SimpleExpression )* | '('? Column ( ',' Column )* ')'? '=' ( ParenthesedSelectBody | '(' ComplexExpressionList ')' | Expression ) ( ',' '('? Column ( ',' Column )* ')'? '=' ( ParenthesedSelectBody | '(' ComplexExpressionList ')' | Expression ) )* ) WhereClause? )
    +
             ::= 'DO' ( 'NOTHING' | 'UPDATE' 'SET' UpdateSets WhereClause? )
    Referenced by: -
    +
    ====================================================================================================================== - OutputClause +OutputClause ====================================================================================================================== - + .. raw:: html @@ -1071,94 +1029,67 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ColumnsNamesList -
    +
             ::= 'OUTPUT' SelectItemsList ( 'INTO' ( UserVariable | Table ) ColumnsNamesList? )?
    Referenced by: -
    +
    ====================================================================================================================== - Upsert +Upsert ====================================================================================================================== - + .. raw:: html - - - - - UPSERT - - INSERT - - OR - - REPLACE - - INTO - - Table - ( - - Column - , - - ) - - SET - - Column - = - - SimpleExpression - , - - VALUES - - VALUE - - ( - - SimpleExpression - , - - ) - - , - - Select - ON - - DUPLICATE - - KEY - - UPDATE - - Column - = - - SimpleExpression - , - - -
    - -
    Upsert   ::= ( 'UPSERT' | ( 'INSERT' 'OR' )? 'REPLACE' ) 'INTO'? Table ( '(' Column ( ',' Column )* ')' )? ( 'SET' Column '=' SimpleExpression ( ',' Column '=' SimpleExpression )* | ( 'VALUES' | 'VALUE' )? '(' SimpleExpression ( ',' SimpleExpression )* ')' ( ',' '(' SimpleExpression ( ',' SimpleExpression )* ')' )* | Select ) ( 'ON' 'DUPLICATE' 'KEY' 'UPDATE' Column '=' SimpleExpression ( ',' Column '=' SimpleExpression )* )?
    -
    - Referenced by: -
    - - -====================================================================================================================== - Delete -====================================================================================================================== + + + + + UPSERT + + INSERT + + OR + + REPLACE + + INTO + + Table + + ParenthesedColumnList + SET + + UpdateSets + + Select + ON + + DUPLICATE + + KEY + + UPDATE + + UpdateSets + +
    + +
    Upsert   ::= ( 'UPSERT' | ( 'INSERT' 'OR' )? 'REPLACE' ) 'INTO'? Table ParenthesedColumnList? ( 'SET' UpdateSets | Select ) ( 'ON' 'DUPLICATE' 'KEY' 'UPDATE' UpdateSets )?
    +
    + Referenced by: +
    +====================================================================================================================== +Delete +====================================================================================================================== + + .. raw:: html @@ -1190,25 +1121,24 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. WhereClause OrderByElements - - PlainLimit - RETURNING - - SelectItemsList + + PlainLimit + + ReturningClause -
    +
    -
    Delete   ::= 'DELETE' 'LOW_PRIORITY'? 'QUICK'? 'IGNORE'? ( ( TableWithAlias ( ',' TableWithAlias )* OutputClause? )? 'FROM' )? ( TableWithAlias JoinsList? )? ( 'USING' TableWithAlias ( ',' TableWithAlias )* )? WhereClause? OrderByElements? PlainLimit? ( 'RETURNING' SelectItemsList )?
    +
    Delete   ::= 'DELETE' 'LOW_PRIORITY'? 'QUICK'? 'IGNORE'? ( ( TableWithAlias ( ',' TableWithAlias )* OutputClause? )? 'FROM' )? ( TableWithAlias JoinsList? )? ( 'USING' TableWithAlias ( ',' TableWithAlias )* )? WhereClause? OrderByElements? PlainLimit? ReturningClause?
    Referenced by: -
    +
    ====================================================================================================================== - Merge +Merge ====================================================================================================================== - + .. raw:: html @@ -1238,114 +1168,105 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. MergeUpdateClause -
    +
    Referenced by: -
    +
    ====================================================================================================================== - MergeUpdateClause +MergeUpdateClause ====================================================================================================================== - + .. raw:: html - - - - - WHEN - - MATCHED - - THEN - - UPDATE - - SET - - Column - = - - SimpleExpression - , - - WHERE - - Expression - DELETE - - WHERE - - Expression - -
    + + + + + WHEN + + MATCHED + + THEN + + UPDATE + + SET + + UpdateSets + WHERE + + Expression + DELETE + + WHERE + + Expression + +
    -
             ::= 'WHEN' 'MATCHED' 'THEN' 'UPDATE' 'SET' Column '=' SimpleExpression ( ',' Column '=' SimpleExpression )* ( 'WHERE' Expression )? ( 'DELETE' 'WHERE' Expression )?
    +
             ::= 'WHEN' 'MATCHED' 'THEN' 'UPDATE' 'SET' UpdateSets ( 'WHERE' Expression )? ( 'DELETE' 'WHERE' Expression )?
    Referenced by: -
    +
    ====================================================================================================================== - MergeInsertClause +MergeInsertClause ====================================================================================================================== - + .. raw:: html - - - - - WHEN - - NOT - - MATCHED - - THEN - - INSERT - - ( - - Column - , - - ) - - VALUES - - ( - - SimpleExpression - , - - ) - - WHERE - - Expression - -
    + + + + + WHEN + + NOT + + MATCHED + + THEN + + INSERT + + ( + + ColumnList + ) + + VALUES + + ( + + SimpleExpressionList + ) + + WHERE + + Expression + +
    -
             ::= 'WHEN' 'NOT' 'MATCHED' 'THEN' 'INSERT' ( '(' Column ( ',' Column )* ')' )? 'VALUES' '(' SimpleExpression ( ',' SimpleExpression )* ')' ( 'WHERE' Expression )?
    +
             ::= 'WHEN' 'NOT' 'MATCHED' 'THEN' 'INSERT' ( '(' ColumnList ')' )? 'VALUES' '(' SimpleExpressionList ')' ( 'WHERE' Expression )?
    Referenced by: -
    +
    ====================================================================================================================== - RelObjectNameList +RelObjectNameList ====================================================================================================================== - + .. raw:: html @@ -1361,44 +1282,49 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. RelObjectNameExt2 -
    +
             ::= RelObjectNameExt ( ( '.' | ':' ) '.'* RelObjectNameExt2 )*
    +
    ====================================================================================================================== - Column +Column ====================================================================================================================== - + .. raw:: html - + - RelObjectNameList - -
    + RelObjectNameList + . + + K_NEXTVAL + + ArrayConstructor + +
    - +
    +
    ====================================================================================================================== - RelObjectNameWithoutValue +RelObjectNameWithoutValue ====================================================================================================================== - + .. raw:: html - + @@ -1494,349 +1420,357 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. COMMIT CONFLICT - - COSTS - - CS - - CYCLE - - DATABASE - - DDL - - DECLARE + + CONVERT + + COSTS + + CS + + CYCLE + + DATABASE + + DDL - DEFAULT - - DEFERRABLE - - DELAYED - - DELETE - - DESC - - DESCRIBE - - DISABLE - - DISCONNECT - - DIV - - DML - - DO - - DROP - - DUMP - - DUPLICATE - - EMIT - - ENABLE - - END + DECLARE + + DEFAULT + + DEFERRABLE + + DELAYED + + DELETE + + DESC + + DESCRIBE + + DISABLE + + DISCONNECT + + DIV + + DML + + DO + + DOMAIN + + DROP + + DUMP + + DUPLICATE + + EMIT - ESCAPE - - EXCLUDE - - EXEC + ENABLE + + END + + ESCAPE - EXECUTE - - EXPLAIN - - EXTENDED - - EXTRACT - - FALSE - - FILTER - - FIRST + EXCLUDE + + EXEC + + EXECUTE + + EXPLAIN + + EXTENDED + + EXTRACT + + FALSE - FLUSH - - FN - - FOLLOWING - - FORMAT - - FULLTEXT - - FUNCTION - - GLOBAL - - GRANT - - GUARD - - HISTORY - - HOPPING - - INCLUDE - - INCREMENT - - INDEX - - INSERT - - INTERLEAVE + FILTER + + FIRST + + FLUSH + + FN + + FOLLOWING + + FORMAT + + FULLTEXT + + FUNCTION + + GLOBAL + + GRANT + + GUARD + + HISTORY + + HOPPING + + INCLUDE + + INCREMENT + + INDEX - ISNULL - - JSON - - KEEP - - KEY + INSERT + + INTERLEAVE + + ISNULL + + JSON - KEYS - - LAST - - LEADING + KEEP + + KEY + + KEYS - LINK - - LOCAL - - LOCKED - - LOG - - MATCH - - MATCHED - - MATERIALIZED - - MAXVALUE - - MERGE - - MINVALUE - - MODIFY - - MOVEMENT - - NEXT - - NO - - NOCACHE - - NOKEEP - - NOLOCK - - NOMAXVALUE - - NOMINVALUE - - NOORDER - - NOTHING - - NOVALIDATE - - NOWAIT - - NULLS - - OF - - OFF - - OPEN - - OVER - - OVERLAPS - - PARALLEL - - PARENT - - PARTITION - - PATH - - PERCENT - - PLACING - - PRECEDING - - PRECISION - - PRIMARY - - PRIOR - - PURGE - - QUERY + LAST + + LEADING + + LINK + + LOCAL + + LOCKED + + LOG + + MATCH + + MATCHED + + MATERIALIZED + + MAXVALUE + + MEMBER + + MERGE + + MINVALUE + + MODIFY + + MOVEMENT + + NEXT + + NO + + NOCACHE + + NOKEEP + + NOLOCK + + NOMAXVALUE + + NOMINVALUE + + NOORDER + + NOTHING + + NOVALIDATE + + NOWAIT + + NULLS + + OF + + OFF + + OPEN + + OVER + + OVERLAPS + + PARALLEL + + PARENT + + PARTITION + + PATH + + PERCENT + + PLACING + + PRECEDING + + PRECISION + + PRIMARY - QUICK - - QUIESCE + PRIOR + + PURGE - RANGE - - READ - - RECYCLEBIN - - REFERENCES - - REFRESH - - REGISTER - - RENAME + QUERY + + QUICK + + QUIESCE + + RANGE + + READ + + RECYCLEBIN + + REFERENCES - REPLACE - - RESET - - RESTART - - RESTRICT - - RESTRICTED - - RESUMABLE - - RESUME - - RLIKE - - ROLLBACK - - ROW - - ROWS - - RR - - RS - - SAVEPOINT - - SCHEMA - - SEPARATOR - - SEQUENCE - - SESSION - - SETS - - SHOW - - SHUTDOWN - - SIBLINGS - - SIGNED - - SIMILAR - - SIZE - - SKIP + REFRESH + + REGISTER + + RENAME + + REPLACE + + RESET + + RESTART + + RESTRICT + + RESTRICTED + + RESUMABLE + + RESUME + + RLIKE + + ROLLBACK + + ROW + + ROWS + + RR + + RS + + SAVEPOINT + + SCHEMA + + SEPARATOR + + SEQUENCE + + SESSION + + SETS + + SHOW + + SHUTDOWN + + SIBLINGS + + SIGNED - STORED - - STRING - - SUSPEND + SIMILAR + + SIZE + + SKIP - SWITCH - - SYNONYM - - SYSTEM - - TABLE - - TABLESPACE - - TEMP - - TEMPORARY - - THEN - - TIMEOUT - - TIMESTAMPTZ - - TO - - TRUE - - TRUNCATE - - TUMBLING - - TYPE - - UNLOGGED + STORED + + STRING + + SUSPEND + + SWITCH + + SYNONYM + + SYSTEM + + TABLE + + TABLESPACE + + TEMP + + TEMPORARY + + THEN + + TIMEOUT + + TIMESTAMPTZ + + TO + + TRIGGER + + TRUE - UNQIESCE + TRUNCATE - UNSIGNED - - UPDATE - - UPSERT - - UR - - USER - - VALIDATE - - VERBOSE - - VIEW - - WAIT - - WITHIN - - WITHOUT - - WORK - - XML - - XMLAGG - - XMLTEXT - - YAML - - YES - - ZONE - + TUMBLING + + TYPE + + UNLOGGED + + UNQIESCE + + UNSIGNED + + UPDATE + + UPSERT + + UR + + USER + + VALIDATE + + VERBOSE + + VIEW + + WAIT + + WITHIN + + WITHOUT + + WORK + + XML + + XMLAGG + + XMLTEXT + + YAML + + YES + + ZONE + -
    +
             ::= S_IDENTIFIER
    @@ -1886,6 +1820,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'COMMENT'
               | 'COMMIT'
               | 'CONFLICT'
    +
               | 'CONVERT'
               | 'COSTS'
               | 'CS'
               | 'CYCLE'
    @@ -1903,6 +1838,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'DIV'
               | 'DML'
               | 'DO'
    +
               | 'DOMAIN'
               | 'DROP'
               | 'DUMP'
               | 'DUPLICATE'
    @@ -1950,6 +1886,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'MATCHED'
               | 'MATERIALIZED'
               | 'MAXVALUE'
    +
               | 'MEMBER'
               | 'MERGE'
               | 'MINVALUE'
               | 'MODIFY'
    @@ -2032,6 +1969,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'TIMEOUT'
               | 'TIMESTAMPTZ'
               | 'TO'
    +
               | 'TRIGGER'
               | 'TRUE'
               | 'TRUNCATE'
               | 'TUMBLING'
    @@ -2058,14 +1996,14 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'ZONE'
    +
    ====================================================================================================================== - RelObjectName +RelObjectName ====================================================================================================================== - + .. raw:: html @@ -2096,7 +2034,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. IGNORE -
    +
             ::= RelObjectNameWithoutValue
    @@ -2113,14 +2051,14 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'IGNORE'
    +
    ====================================================================================================================== - RelObjectNameWithoutStart +RelObjectNameWithoutStart ====================================================================================================================== - + .. raw:: html @@ -2137,7 +2075,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. INTERVAL -
    +
             ::= RelObjectNameWithoutValue
    @@ -2147,14 +2085,14 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'INTERVAL'
    Referenced by: -
    +
    ====================================================================================================================== - RelObjectNameExt +RelObjectNameExt ====================================================================================================================== - + .. raw:: html @@ -2199,7 +2137,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ORDER -
    +
             ::= RelObjectName
    @@ -2223,14 +2161,14 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'ORDER'
    +
    ====================================================================================================================== - RelObjectNameExt2 +RelObjectNameExt2 ====================================================================================================================== - + .. raw:: html @@ -2244,7 +2182,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. CURRENT -
    +
             ::= RelObjectNameExt
    @@ -2253,14 +2191,14 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'CURRENT'
    +
    ====================================================================================================================== - Table +Table ====================================================================================================================== - + .. raw:: html @@ -2269,19 +2207,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. RelObjectNameList -
    +
    +
    ====================================================================================================================== - TableWithAlias +TableWithAlias ====================================================================================================================== - + .. raw:: html @@ -2292,160 +2230,193 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Alias -
    +
             ::= Table Alias?
    Referenced by: -
    +
    ====================================================================================================================== - SelectWithWithItems +SelectWithWithItems ====================================================================================================================== - + .. raw:: html - + - - - SelectBody - -
    + + + Select + +
    -
             ::= SelectBody
    +
             ::= Select
    Referenced by: -
    +
    ====================================================================================================================== - Select +Select ====================================================================================================================== - + .. raw:: html - + - - - SelectBody - -
    + + + WithList + + PlainSelect + + Values + + ParenthesedSelect + + SetOperationList + + OrderByElements + + LimitWithOffset + + Offset + + Fetch + + WithIsolation + +
    - +
    +
    ====================================================================================================================== - SelectBody +ParenthesedSelect ====================================================================================================================== - + .. raw:: html - + - - - WithList - - PlainSelect - - Values - - ParenthesedSelectBody - - SetOperationList - - OrderByElements - - LimitWithOffset - - Offset - - Fetch - - WithIsolation - -
    + + + ( + + Select + ) + + +
    - - + +
             ::= '(' Select ')'
    +
    ====================================================================================================================== - ParenthesedSelectBody +LateralView ====================================================================================================================== - + .. raw:: html - + - - ( - - SelectBody - ) - - -
    + + LATERAL + + VIEW + + OUTER + + Function + + RelObjectNameWithoutStart + AS + + RelObjectNameWithoutStart + +
    - -
             ::= '(' SelectBody ')'
    + +
             ::= 'LATERAL' 'VIEW' 'OUTER'? Function RelObjectNameWithoutStart? 'AS' RelObjectNameWithoutStart
    +
    ====================================================================================================================== - LateralSubSelect +LateralViews ====================================================================================================================== + +.. raw:: html + + + + + + LateralView + +
    + + +
             ::= LateralView+
    +
    + Referenced by: +
    + +====================================================================================================================== +LateralSubSelect +====================================================================================================================== + + .. raw:: html - + LATERAL - ( - - SelectBody - ) - - -
    + ( + + Select + ) + + +
    -
             ::= 'LATERAL' '(' SelectBody ')'
    +
             ::= 'LATERAL' '(' Select ')'
    Referenced by: -
    +
    ====================================================================================================================== - PlainSelect +PlainSelect ====================================================================================================================== - + .. raw:: html - + @@ -2475,94 +2446,101 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SQL_CACHE Top - - SelectItemsList - - IntoClause - FROM - - FromItem - - JoinsList - - KSQLWindowClause - - WhereClause - - OracleHierarchicalQueryClause - - GroupByColumnReferences - - Having - - OrderByElements - WINDOW - - RelObjectName - AS - - windowDefinition - , - - OrderByElements - EMIT - - CHANGES - - LimitWithOffset - - Offset - - LimitWithOffset - - Fetch - - WithIsolation - FOR - - UPDATE - - OF - - Table - - Wait - NOWAIT - - SKIP - - LOCKED - - OptimizeFor - FOR - - XML - - PATH - - ( - - S_CHAR_LITERAL - ) - - -
    + + SelectItemsList + + IntoClause + FROM + + FromItem + + LateralViews + + JoinsList + FINAL + + KSQLWindowClause + + WhereClause + + OracleHierarchicalQueryClause + + Having + + GroupByColumnReferences + + Having + + OrderByElements + WINDOW + + RelObjectName + AS + + windowDefinition + , + + OrderByElements + EMIT + + CHANGES + + LimitBy + + LimitWithOffset + + Offset + + LimitWithOffset + + Fetch + + WithIsolation + FOR + + UPDATE + + OF + + Table + + Wait + NOWAIT + + SKIP + + LOCKED + + OptimizeFor + FOR + + XML + + PATH + + ( + + S_CHAR_LITERAL + ) + + +
    -
             ::= K_SELECT 'STRAIGHT_JOIN'? Skip? First? ( 'ALL' | 'DISTINCT' ( 'ON' '(' SelectItemsList ')' )? | 'UNIQUE' | 'SQL_CALC_FOUND_ROWS' | 'SQL_NO_CACHE' | 'SQL_CACHE' )? Top? SelectItemsList IntoClause? ( 'FROM' FromItem JoinsList? )? KSQLWindowClause? WhereClause? OracleHierarchicalQueryClause? GroupByColumnReferences? Having? OrderByElements? ( 'WINDOW' RelObjectName 'AS' windowDefinition ( ',' RelObjectName 'AS' windowDefinition )* )? OrderByElements? ( 'EMIT' 'CHANGES' )? LimitWithOffset? Offset? LimitWithOffset? Fetch? WithIsolation? ( 'FOR' 'UPDATE' ( 'OF' Table )? Wait? ( 'NOWAIT' | 'SKIP' 'LOCKED' )? )? OptimizeFor? ( 'FOR' 'XML' 'PATH' '(' S_CHAR_LITERAL ')' )?
    +
             ::= K_SELECT 'STRAIGHT_JOIN'? Skip? First? ( 'ALL' | 'DISTINCT' ( 'ON' '(' SelectItemsList ')' )? | 'UNIQUE' | 'SQL_CALC_FOUND_ROWS' | 'SQL_NO_CACHE' | 'SQL_CACHE' )? Top? SelectItemsList IntoClause? ( 'FROM' FromItem LateralViews? JoinsList? )? 'FINAL'? KSQLWindowClause? WhereClause? OracleHierarchicalQueryClause? Having? GroupByColumnReferences? Having? OrderByElements? ( 'WINDOW' RelObjectName 'AS' windowDefinition ( ',' RelObjectName 'AS' windowDefinition )* )? OrderByElements? ( 'EMIT' 'CHANGES' )? LimitBy? LimitWithOffset? Offset? LimitWithOffset? Fetch? WithIsolation? ( 'FOR' 'UPDATE' ( 'OF' Table )? Wait? ( 'NOWAIT' | 'SKIP' 'LOCKED' )? )? OptimizeFor? ( 'FOR' 'XML' 'PATH' '(' S_CHAR_LITERAL ')' )?
    Referenced by: -
    +
    ====================================================================================================================== - SetOperationList +SetOperationList ====================================================================================================================== - + .. raw:: html - + @@ -2580,37 +2558,37 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. PlainSelect - Values - - ParenthesedSelectBody - - OrderByElements - - LimitWithOffset - - Offset - - LimitWithOffset - - Fetch - - WithIsolation - -
    + Values + + ParenthesedSelect + + OrderByElements + + LimitWithOffset + + Offset + + LimitWithOffset + + Fetch + + WithIsolation + +
             ::= ( ( 'UNION' ( 'ALL' | 'DISTINCT' )? | 'INTERSECT' | 'MINUS' | 'EXCEPT' - ) ( PlainSelect | Values | ParenthesedSelectBody ) )+ OrderByElements? LimitWithOffset? Offset? LimitWithOffset? Fetch? WithIsolation?
    + ) ( PlainSelect | Values | ParenthesedSelect ) )+ OrderByElements? LimitWithOffset? Offset? LimitWithOffset? Fetch? WithIsolation?
    Referenced by: -
    +
    ====================================================================================================================== - WithList +WithList ====================================================================================================================== - + .. raw:: html @@ -2623,22 +2601,22 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. , -
    +
    WithList ::= 'WITH' WithItem ( ',' WithItem )*
    Referenced by: -
    +
    ====================================================================================================================== - WithItem +WithItem ====================================================================================================================== - + .. raw:: html - + @@ -2650,23 +2628,23 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SelectItemsList ) - AS - - ParenthesedSelectBody - -
    + AS + + ParenthesedSelect + +
    -
    WithItem ::= 'RECURSIVE'? RelObjectName ( '(' SelectItemsList ')' )? 'AS' ParenthesedSelectBody
    +
    WithItem ::= 'RECURSIVE'? RelObjectName ( '(' SelectItemsList ')' )? 'AS' ParenthesedSelect
    Referenced by: -
    +
    ====================================================================================================================== - SelectItemsList +SelectItemsList ====================================================================================================================== - + .. raw:: html @@ -2677,76 +2655,52 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. , -
    +
             ::= SelectItem ( ',' SelectItem )*
    +
    ====================================================================================================================== - SelectExpressionItem +SelectItem ====================================================================================================================== - -.. raw:: html - - - - - - Condition - - ConcatExpression - - Expression - - Alias - -
    - - -
             ::= ( Condition | ConcatExpression | Expression ) Alias?
    -
    - Referenced by: -
    - - -====================================================================================================================== - SelectItem -====================================================================================================================== - .. raw:: html - + * - AllTableColumns - - SelectExpressionItem - -
    + AllTableColumns + + Condition + + ConcatExpression + + Expression + + Alias + +
    -
             ::= '*'
    -
               | AllTableColumns
    -
               | SelectExpressionItem
    +
             ::= ( '*' | AllTableColumns | Condition | ConcatExpression | Expression ) Alias?
    Referenced by: -
    +
    ====================================================================================================================== - AllTableColumns +AllTableColumns ====================================================================================================================== - + .. raw:: html @@ -2759,20 +2713,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. * -
    +
             ::= Table '.' '*'
    +
    ====================================================================================================================== - Alias +Alias ====================================================================================================================== - + .. raw:: html @@ -2794,19 +2748,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
    +
    ====================================================================================================================== - SQLServerHint +SQLServerHint ====================================================================================================================== - + .. raw:: html @@ -2823,21 +2777,21 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. NOLOCK -
    +
             ::= 'INDEX' '(' RelObjectName ')'
               | 'NOLOCK'
    Referenced by: -
    +
    ====================================================================================================================== - SQLServerHints +SQLServerHints ====================================================================================================================== - + .. raw:: html @@ -2854,20 +2808,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= 'WITH' '(' SQLServerHint ( ',' SQLServerHint )* ')'
    Referenced by: -
    +
    ====================================================================================================================== - MySQLIndexHint +MySQLIndexHint ====================================================================================================================== - + .. raw:: html @@ -2894,20 +2848,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= ( 'USE' | 'SHOW' | 'IGNORE' | 'FORCE' ) ( 'INDEX' | 'KEY' ) '(' RelObjectNameWithoutValue ( ',' RelObjectNameWithoutValue )* ')'
    Referenced by: -
    +
    ====================================================================================================================== - FunctionItem +FunctionItem ====================================================================================================================== - + .. raw:: html @@ -2918,50 +2872,45 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Alias -
    +
             ::= Function Alias?
    Referenced by: -
    +
    ====================================================================================================================== - PivotForColumns +PivotForColumns ====================================================================================================================== - + .. raw:: html - - - - - ( - - Column - , - - ) - - Column - -
    + + + + + ParenthesedColumnList + + Column + +
    -
             ::= '(' Column ( ',' Column )* ')'
    +
             ::= ParenthesedColumnList
               | Column
    Referenced by: -
    +
    ====================================================================================================================== - PivotFunctionItems +PivotFunctionItems ====================================================================================================================== - + .. raw:: html @@ -2972,95 +2921,44 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. , -
    +
             ::= FunctionItem ( ',' FunctionItem )*
    Referenced by: -
    +
    ====================================================================================================================== - PivotSingleInItems +ExpressionListItem ====================================================================================================================== - -.. raw:: html - - - - - - PivotSelectExprItem - , - - -
    - - -
             ::= PivotSelectExprItem ( ',' PivotSelectExprItem )*
    -
    - Referenced by: -
    - -====================================================================================================================== - PivotSelectExprItem -====================================================================================================================== - - .. raw:: html - + - - - SimpleExpression - - Alias - -
    - - -
             ::= SimpleExpression Alias?
    -
    - Referenced by: -
    - - -====================================================================================================================== - ExpressionListItem -====================================================================================================================== - - -.. raw:: html - - - - - - ( - - SimpleExpressionList - ) - - Alias - -
    + + + ParenthesedExpressionList + + Alias + +
    -
             ::= '(' SimpleExpressionList ')' Alias?
    +
             ::= ParenthesedExpressionList Alias?
    Referenced by: -
    +
    ====================================================================================================================== - PivotMultiInItems +PivotMultiInItems ====================================================================================================================== - + .. raw:: html @@ -3071,23 +2969,23 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. , -
    +
             ::= ExpressionListItem ( ',' ExpressionListItem )*
    Referenced by: -
    +
    ====================================================================================================================== - Pivot +Pivot ====================================================================================================================== - + .. raw:: html - + @@ -3101,33 +2999,33 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. PivotForColumns IN - ( - - PivotSingleInItems + ( + + SelectItemsList - PivotMultiInItems - ) - - ) - - Alias - -
    + PivotMultiInItems + ) + + ) + + Alias + +
    -
    Pivot    ::= 'PIVOT' '(' PivotFunctionItems 'FOR' PivotForColumns 'IN' '(' ( PivotSingleInItems | PivotMultiInItems ) ')' ')' Alias?
    +
    Pivot    ::= 'PIVOT' '(' PivotFunctionItems 'FOR' PivotForColumns 'IN' '(' ( SelectItemsList | PivotMultiInItems ) ')' ')' Alias?
    Referenced by: -
    +
    ====================================================================================================================== - PivotXml +PivotXml ====================================================================================================================== - + .. raw:: html - + @@ -3145,34 +3043,34 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ( - ANY - - SelectBody - - PivotSingleInItems + ANY + + Select + + SelectItemsList - PivotMultiInItems - ) - - ) - - -
    + PivotMultiInItems + ) + + ) + + +
    -
    PivotXml ::= 'PIVOT' 'XML' '(' PivotFunctionItems 'FOR' PivotForColumns 'IN' '(' ( 'ANY' | SelectBody | PivotSingleInItems | PivotMultiInItems ) ')' ')'
    +
    PivotXml ::= 'PIVOT' 'XML' '(' PivotFunctionItems 'FOR' PivotForColumns 'IN' '(' ( 'ANY' | Select | SelectItemsList | PivotMultiInItems ) ')' ')'
    Referenced by: -
    +
    ====================================================================================================================== - UnPivot +UnPivot ====================================================================================================================== - + .. raw:: html - + @@ -3192,28 +3090,28 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. PivotForColumns IN - ( - - PivotSingleInItems - ) - - ) - - Alias - -
    + ( + + SelectItemsList + ) + + ) + + Alias + +
    -
    UnPivot  ::= 'UNPIVOT' ( ( 'INCLUDE' | 'EXCLUDE' ) 'NULLS' )? '(' PivotForColumns 'FOR' PivotForColumns 'IN' '(' PivotSingleInItems ')' ')' Alias?
    +
    UnPivot  ::= 'UNPIVOT' ( ( 'INCLUDE' | 'EXCLUDE' ) 'NULLS' )? '(' PivotForColumns 'FOR' PivotForColumns 'IN' '(' SelectItemsList ')' ')' Alias?
    Referenced by: -
    +
    ====================================================================================================================== - IntoClause +IntoClause ====================================================================================================================== - + .. raw:: html @@ -3226,20 +3124,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. , -
    +
             ::= 'INTO' Table ( ',' Table )*
    Referenced by: -
    +
    ====================================================================================================================== - ParenthesedFromItem +ParenthesedFromItem ====================================================================================================================== - + .. raw:: html @@ -3254,23 +3152,23 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= '(' FromItem JoinsList? ')'
    Referenced by: -
    +
    ====================================================================================================================== - FromItem +FromItem ====================================================================================================================== - + .. raw:: html - + @@ -3278,41 +3176,41 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Table - ParenthesedFromItem - - ParenthesedSelectBody - - Pivot - - UnPivot + ParenthesedFromItem + + ParenthesedSelect + + Pivot + + UnPivot LateralSubSelect - - Alias - - UnPivot - - PivotXml - - Pivot - - MySQLIndexHint - - SQLServerHints - -
    + + Alias + + UnPivot + + PivotXml + + Pivot + + MySQLIndexHint + + SQLServerHints + +
    - +
    +
    ====================================================================================================================== - JoinsList +JoinsList ====================================================================================================================== - + .. raw:: html @@ -3321,20 +3219,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. JoinerExpression -
    +
             ::= JoinerExpression+
    +
    ====================================================================================================================== - JoinerExpression +JoinerExpression ====================================================================================================================== - + .. raw:: html @@ -3392,7 +3290,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= 'GLOBAL'? 'NATURAL'? ( ( 'RIGHT' | 'FULL' )? 'OUTER'? | 'LEFT' ( 'SEMI' @@ -3400,14 +3298,14 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) FromItem ( ( 'WITHIN' '(' JoinWindow ')' )? ( 'ON' Expression )+ | 'USING' '(' Column ( ',' Column )* ')' )?
    Referenced by: -
    +
    ====================================================================================================================== - JoinWindow +JoinWindow ====================================================================================================================== - + .. raw:: html @@ -3427,20 +3325,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. K_DATE_LITERAL -
    +
             ::= S_LONG ( S_IDENTIFIER | K_DATE_LITERAL ) ( ',' S_LONG ( S_IDENTIFIER | K_DATE_LITERAL ) )?
    Referenced by: -
    +
    ====================================================================================================================== - KSQLWindowClause +KSQLWindowClause ====================================================================================================================== - + .. raw:: html @@ -3480,20 +3378,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= 'WINDOW' ( 'HOPPING' '(' 'SIZE' S_LONG S_IDENTIFIER ',' 'ADVANCE' 'BY' | 'SESSION' '(' | 'TUMBLING' '(' 'SIZE' ) S_LONG S_IDENTIFIER ')'
    Referenced by: -
    +
    ====================================================================================================================== - WhereClause +WhereClause ====================================================================================================================== - + .. raw:: html @@ -3504,20 +3402,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Expression -
    +
             ::= 'WHERE' Expression
    +
    ====================================================================================================================== - OracleHierarchicalQueryClause +OracleHierarchicalQueryClause ====================================================================================================================== - + .. raw:: html @@ -3548,82 +3446,93 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. AndExpression -
    +
             ::= ( 'START' 'WITH' AndExpression 'CONNECT' 'BY' 'NOCYCLE'? | 'CONNECT' 'BY' 'NOCYCLE'? ( AndExpression 'START' 'WITH' )? ) AndExpression
    Referenced by: -
    +
    ====================================================================================================================== - GroupByColumnReferences +GroupByColumnReferences ====================================================================================================================== - + .. raw:: html - + GROUP BY - - ( - - ) - - ComplexExpressionList - GROUPING - - SETS - - ( - - ( - - SimpleExpressionList - ) - - SimpleExpression - , - - ) - - GROUPING - - SETS - - ( - - ( - - SimpleExpressionList - ) - - SimpleExpression - , - - ) - - -
    + + GROUPING + + SETS + + ( + + GroupingSet + , + + ) + + ExpressionList + GROUPING + + SETS + + ( + + GroupingSet + , + + ) + + +
    -
             ::= 'GROUP' 'BY' ( ( '(' ')' | ComplexExpressionList ) ( 'GROUPING' 'SETS' '(' ( '(' SimpleExpressionList? ')' | SimpleExpression ) ( ',' ( '(' SimpleExpressionList? ')' | SimpleExpression ) )* ')' )? | 'GROUPING' 'SETS' '(' ( '(' SimpleExpressionList? ')' | SimpleExpression ) ( ',' ( '(' SimpleExpressionList? ')' | SimpleExpression ) )* ')' )
    +
             ::= 'GROUP' 'BY' ( 'GROUPING' 'SETS' '(' GroupingSet ( ',' GroupingSet )* ')' | ExpressionList ( 'GROUPING' 'SETS' '(' GroupingSet ( ',' GroupingSet )* ')' )? )
    Referenced by: -
    +
    ====================================================================================================================== - Having +GroupingSet ====================================================================================================================== + +.. raw:: html + + + + + + ParenthesedExpressionList + + SimpleExpression + +
    + + +
             ::= ParenthesedExpressionList
    +
               | SimpleExpression
    +
    + Referenced by: +
    + +====================================================================================================================== +Having +====================================================================================================================== + + .. raw:: html @@ -3634,19 +3543,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Expression -
    +
    Having   ::= 'HAVING' Expression
    Referenced by: -
    +
    ====================================================================================================================== - OrderByElements +OrderByElements ====================================================================================================================== - + .. raw:: html @@ -3663,20 +3572,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. , -
    +
             ::= 'ORDER' 'SIBLINGS'? 'BY' OrderByElement ( ',' OrderByElement )*
    +
    ====================================================================================================================== - OrderByElement +OrderByElement ====================================================================================================================== - + .. raw:: html @@ -3695,20 +3604,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. LAST -
    +
             ::= Expression ( 'ASC' | 'DESC' )? ( 'NULLS' ( 'FIRST' | 'LAST' )? )?
    Referenced by: -
    +
    ====================================================================================================================== - SimpleJdbcParameter +SimpleJdbcParameter ====================================================================================================================== - + .. raw:: html @@ -3719,20 +3628,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. S_LONG -
    +
             ::= '?' S_LONG?
    +
    ====================================================================================================================== - SimpleJdbcNamedParameter +SimpleJdbcNamedParameter ====================================================================================================================== - + .. raw:: html @@ -3743,20 +3652,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. RelObjectNameExt -
    +
             ::= ':' RelObjectNameExt
    Referenced by: -
    +
    ====================================================================================================================== - LimitWithOffset +LimitWithOffset ====================================================================================================================== - + .. raw:: html @@ -3772,50 +3681,71 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. PlainLimit -
    +
             ::= 'LIMIT' Expression ',' Expression
               | PlainLimit
    +
    ====================================================================================================================== - PlainLimit +PlainLimit ====================================================================================================================== - + .. raw:: html - + - LIMIT - - ( - - ParenthesedSelectBody - ) + LIMIT + + ParenthesedSelect - Expression - -
    + Expression + +
    -
             ::= 'LIMIT' ( '(' ParenthesedSelectBody ')' | Expression )
    +
             ::= 'LIMIT' ( ParenthesedSelect | Expression )
    Referenced by: -
    +
    ====================================================================================================================== - Offset +LimitBy ====================================================================================================================== + +.. raw:: html + + + + + + LimitWithOffset + BY + + ExpressionList + +
    + + +
    + Referenced by: +
    + +====================================================================================================================== +Offset +====================================================================================================================== + + .. raw:: html @@ -3830,19 +3760,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ROW -
    +
    Offset   ::= 'OFFSET' Expression ( 'ROWS' | 'ROW' )?
    +
    ====================================================================================================================== - Fetch +Fetch ====================================================================================================================== - + .. raw:: html @@ -3863,19 +3793,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ONLY -
    +
    Fetch    ::= 'FETCH' ( 'FIRST' | 'NEXT' ) Expression ( 'ROWS' | 'ROW' ) 'ONLY'
    +
    ====================================================================================================================== - WithIsolation +WithIsolation ====================================================================================================================== - + .. raw:: html @@ -3886,20 +3816,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. K_ISOLATION -
    +
             ::= 'WITH' K_ISOLATION
    +
    ====================================================================================================================== - OptimizeFor +OptimizeFor ====================================================================================================================== - + .. raw:: html @@ -3914,20 +3844,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ROWS -
    +
             ::= 'OPTIMIZE' 'FOR' S_LONG 'ROWS'
    Referenced by: -
    +
    ====================================================================================================================== - Top +Top ====================================================================================================================== - + .. raw:: html @@ -3952,19 +3882,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. WITH TIES -
    +
    Top      ::= 'TOP' ( S_LONG | SimpleJdbcParameter | ':' S_IDENTIFIER? | '(' AdditiveExpression ')' ) 'PERCENT'? 'WITH TIES'?
    Referenced by: -
    +
    ====================================================================================================================== - Skip +Skip ====================================================================================================================== - + .. raw:: html @@ -3979,19 +3909,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SimpleJdbcParameter -
    +
    Skip     ::= 'SKIP' ( S_LONG | S_IDENTIFIER | SimpleJdbcParameter )
    Referenced by: -
    +
    ====================================================================================================================== - First +First ====================================================================================================================== - + .. raw:: html @@ -4008,19 +3938,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SimpleJdbcParameter -
    +
    First    ::= ( 'FIRST' | 'LIMIT' ) ( S_LONG | S_IDENTIFIER | SimpleJdbcParameter )
    Referenced by: -
    +
    ====================================================================================================================== - Expression +Expression ====================================================================================================================== - + .. raw:: html @@ -4029,20 +3959,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. XorExpression -
    +
             ::= XorExpression
    +
    ====================================================================================================================== - XorExpression +XorExpression ====================================================================================================================== - + .. raw:: html @@ -4053,20 +3983,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. XOR -
    +
             ::= OrExpression ( 'XOR' OrExpression )*
    Referenced by: -
    +
    ====================================================================================================================== - OrExpression +OrExpression ====================================================================================================================== - + .. raw:: html @@ -4077,20 +4007,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. OR -
    +
             ::= AndExpression ( 'OR' AndExpression )*
    Referenced by: -
    +
    ====================================================================================================================== - AndExpression +AndExpression ====================================================================================================================== - + .. raw:: html @@ -4112,20 +4042,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. && -
    +
             ::= ( Condition | ( 'NOT' | '!' )? '(' XorExpression ')' ) ( ( 'AND' | '&&' ) ( Condition | ( 'NOT' | '!' )? '(' XorExpression ')' ) )*
    +
    ====================================================================================================================== - Condition +Condition ====================================================================================================================== - + .. raw:: html @@ -4140,53 +4070,45 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SQLCondition -
    +
             ::= ( 'NOT' | '!' )? ( RegularCondition | SQLCondition )
    +
    ====================================================================================================================== - OverlapsCondition +OverlapsCondition ====================================================================================================================== - + .. raw:: html - + - - - ( - - SimpleExpressionListAtLeastTwoItems - ) - - OVERLAPS - - ( - - SimpleExpressionListAtLeastTwoItems - ) - - -
    + + + ParenthesedExpressionList + OVERLAPS + + ParenthesedExpressionList + +
    -
             ::= '(' SimpleExpressionListAtLeastTwoItems ')' 'OVERLAPS' '(' SimpleExpressionListAtLeastTwoItems ')'
    +
             ::= ParenthesedExpressionList 'OVERLAPS' ParenthesedExpressionList
    Referenced by: -
    +
    ====================================================================================================================== - RegularCondition +RegularCondition ====================================================================================================================== - + .. raw:: html @@ -4262,24 +4184,24 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= 'PRIOR'? ComparisonItem ( '(' '+' ')' )? ( '>' | '<' | '=' | OP_GREATERTHANEQUALS | OP_MINORTHANEQUALS | OP_NOTEQUALSSTANDARD | OP_NOTEQUALSBANG | '@@' | '~' | ( 'NOT'? 'REGEXP' | 'RLIKE' ) 'BINARY'? | '~*' | '!~' | '!~*' | '@>' | '<@' | '?' | '?|' | '?&' | OP_CONCAT | '-' | '-#' | '<->' | '<#>' ) 'PRIOR'? ComparisonItem ( '(' '+' ')' )?
    Referenced by: -
    +
    ====================================================================================================================== - SQLCondition +SQLCondition ====================================================================================================================== - + .. raw:: html - + @@ -4291,38 +4213,40 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SimpleExpression - Between - - IsNullExpression - - IsBooleanExpression - - LikeExpression - - IsDistinctExpression + Between + + MemberOfExpression + + IsNullExpression + + IsBooleanExpression + + LikeExpression - SimilarToExpression - -
    + IsDistinctExpression + + SimilarToExpression + +
             ::= ExistsExpression
               | InExpression
               | OverlapsCondition
    -
    +
    Referenced by: -
    +
    ====================================================================================================================== - InExpression +InExpression ====================================================================================================================== - + .. raw:: html - + @@ -4339,62 +4263,28 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. S_CHAR_LITERAL - Function - ( - - ComplexExpressionList - ) - - ParenthesedSelectBody + Function + + ParenthesedSelect + + ParenthesedExpressionList - SimpleExpression - -
    + SimpleExpression + +
    -
             ::= SimpleExpression ( '(' '+' ')' )? 'NOT'? 'IN' ( S_CHAR_LITERAL | Function | '(' ComplexExpressionList ')' | ParenthesedSelectBody | SimpleExpression )
    +
             ::= SimpleExpression ( '(' '+' ')' )? 'NOT'? 'IN' ( S_CHAR_LITERAL | Function | ParenthesedSelect | ParenthesedExpressionList | SimpleExpression )
    Referenced by: -
    +
    ====================================================================================================================== - MultiInExpressions +Between ====================================================================================================================== - -.. raw:: html - - - - - - ( - - ( - - SimpleExpressionList - ) - - , - - ) - - -
    - - -
             ::= '(' '(' SimpleExpressionList ')' ( ',' '(' SimpleExpressionList ')' )* ')'
    -
    - Not referenced by any. -
    - - -====================================================================================================================== - Between -====================================================================================================================== - .. raw:: html @@ -4410,19 +4300,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SimpleExpression -
    +
    Between  ::= 'NOT'? 'BETWEEN' SimpleExpression 'AND' SimpleExpression
    Referenced by: -
    +
    ====================================================================================================================== - LikeExpression +LikeExpression ====================================================================================================================== - + .. raw:: html @@ -4442,20 +4332,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Expression -
    +
             ::= 'NOT'? ( 'LIKE' | 'ILIKE' ) SimpleExpression ( 'ESCAPE' ( S_CHAR_LITERAL | Expression ) )?
    Referenced by: -
    +
    ====================================================================================================================== - SimilarToExpression +SimilarToExpression ====================================================================================================================== - + .. raw:: html @@ -4473,20 +4363,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. S_CHAR_LITERAL -
    +
             ::= 'NOT'? 'SIMILAR' 'TO' SimpleExpression ( 'ESCAPE' S_CHAR_LITERAL )?
    Referenced by: -
    +
    ====================================================================================================================== - IsDistinctExpression +IsDistinctExpression ====================================================================================================================== - + .. raw:: html @@ -4503,20 +4393,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SimpleExpression -
    +
             ::= 'IS' 'NOT'? 'DISTINCT' 'FROM' SimpleExpression
    Referenced by: -
    +
    ====================================================================================================================== - IsNullExpression +IsNullExpression ====================================================================================================================== - + .. raw:: html @@ -4532,21 +4422,21 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. NULL -
    +
             ::= 'ISNULL'
               | 'IS' 'NOT'? 'NULL'
    Referenced by: -
    +
    ====================================================================================================================== - IsBooleanExpression +IsBooleanExpression ====================================================================================================================== - + .. raw:: html @@ -4562,20 +4452,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. FALSE -
    +
             ::= 'IS' 'NOT'? ( 'TRUE' | 'FALSE' )
    Referenced by: -
    +
    ====================================================================================================================== - ExistsExpression +ExistsExpression ====================================================================================================================== - + .. raw:: html @@ -4586,44 +4476,102 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SimpleExpression -
    +
             ::= 'EXISTS' SimpleExpression
    Referenced by: -
    +
    ====================================================================================================================== - SQLExpressionList +MemberOfExpression ====================================================================================================================== + +.. raw:: html + + + + + + MEMBER + + OF + + Expression + +
    + + +
             ::= 'MEMBER' 'OF' Expression
    +
    + Referenced by: +
    + +====================================================================================================================== +ExpressionList +====================================================================================================================== + + .. raw:: html - - - - - Expression - , - - -
    + + + + + ComplexExpressionList + + SimpleExpressionList + + ParenthesedExpressionList + +
    - -
             ::= Expression ( ',' Expression )*
    + +
             ::= ComplexExpressionList
    +
               | SimpleExpressionList
    +
               | ParenthesedExpressionList
    - Not referenced by any. -
    + Referenced by: +
    ====================================================================================================================== - SimpleExpressionList +ParenthesedExpressionList ====================================================================================================================== + +.. raw:: html + + + + + + ( + + ComplexExpressionList + + SimpleExpressionList + ) + + +
    + + +
             ::= '(' ( ComplexExpressionList | SimpleExpressionList )? ')'
    +
    + +====================================================================================================================== +SimpleExpressionList +====================================================================================================================== + + .. raw:: html @@ -4634,81 +4582,96 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. , -
    +
             ::= SimpleExpression ( ',' SimpleExpression )*
    +
    ====================================================================================================================== - ComplexExpressionList +ColumnList ====================================================================================================================== - + .. raw:: html - + - - - OracleNamedFunctionParameter - - Expression + + + Column , - - -
    + + +
    - - + +
             ::= Column ( ',' Column )*
    +
    ====================================================================================================================== - NamedExpressionList1 +ParenthesedColumnList ====================================================================================================================== - + .. raw:: html - + - - BOTH - - LEADING - - TRAILING - - SimpleExpression - FROM - - IN - - PLACING - - SimpleExpression - -
    + + ( + + ColumnList + ) + + +
    - -
             ::= ( 'BOTH' | 'LEADING' | 'TRAILING' ) SimpleExpression ( 'FROM' | 'IN' | 'PLACING' ) SimpleExpression
    + +
             ::= '(' ColumnList ')'
    +
    ====================================================================================================================== - NamedExpressionListExprFirst +ComplexExpressionList ====================================================================================================================== + +.. raw:: html + + + + + + OracleNamedFunctionParameter + + Expression + , + + +
    + + + +
    + +====================================================================================================================== +NamedExpressionListExprFirst +====================================================================================================================== + + .. raw:: html @@ -4732,82 +4695,57 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SimpleExpression -
    +
             ::= SimpleExpression ( 'FROM' | 'IN' | 'PLACING' ) SimpleExpression ( ( 'FOR' | 'FROM' ) SimpleExpression ( 'FOR' SimpleExpression )? )?
    +
    ====================================================================================================================== - SimpleExpressionListAtLeastTwoItems +ComparisonItem ====================================================================================================================== - -.. raw:: html - - - - - - SimpleExpression - , - - SimpleExpression - -
    - - -
             ::= SimpleExpression ( ',' SimpleExpression )+
    -
    - - -====================================================================================================================== - ComparisonItem -====================================================================================================================== - .. raw:: html - AnyComparisonExpression - - ValueListExpression - - SimpleExpression + AnyComparisonExpression + + SimpleExpression + + ParenthesedExpressionList RowConstructor - PrimaryExpression + PrimaryExpression -
    +
             ::= AnyComparisonExpression
    -
               | ValueListExpression
               | SimpleExpression
    +
               | ParenthesedExpressionList
               | RowConstructor
               | PrimaryExpression
    Referenced by: -
    +
    ====================================================================================================================== - AnyComparisonExpression +AnyComparisonExpression ====================================================================================================================== - + .. raw:: html - + @@ -4815,32 +4753,24 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SOME - ALL - - ( - - VALUES - - SimpleExpressionList - - ParenthesedSelectBody - ) - - -
    + ALL + + Select + +
    -
             ::= ( 'ANY' | 'SOME' | 'ALL' ) '(' ( 'VALUES' SimpleExpressionList | ParenthesedSelectBody ) ')'
    +
             ::= ( 'ANY' | 'SOME' | 'ALL' ) Select
    Referenced by: -
    +
    ====================================================================================================================== - SimpleExpression +SimpleExpression ====================================================================================================================== - + .. raw:: html @@ -4854,20 +4784,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ConcatExpression -
    +
             ::= ( UserVariable ( '=' | ':=' ) )? ConcatExpression
    +
    ====================================================================================================================== - ConcatExpression +ConcatExpression ====================================================================================================================== - + .. raw:: html @@ -4878,20 +4808,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. OP_CONCAT -
    +
             ::= BitwiseAndOr ( OP_CONCAT BitwiseAndOr )*
    +
    ====================================================================================================================== - BitwiseAndOr +BitwiseAndOr ====================================================================================================================== - + .. raw:: html @@ -4908,20 +4838,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. >> -
    +
             ::= AdditiveExpression ( ( '|' | '&' | '<<' | '>>' ) AdditiveExpression )*
    Referenced by: -
    +
    ====================================================================================================================== - AdditiveExpression +AdditiveExpression ====================================================================================================================== - + .. raw:: html @@ -4934,20 +4864,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. - -
    +
             ::= MultiplicativeExpression ( ( '+' | '-' ) MultiplicativeExpression )*
    Referenced by: -
    +
    ====================================================================================================================== - MultiplicativeExpression +MultiplicativeExpression ====================================================================================================================== - + .. raw:: html @@ -4964,20 +4894,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. % -
    +
             ::= BitwiseXor ( ( '*' | '/' | 'DIV' | '%' ) BitwiseXor )*
    Referenced by: -
    +
    ====================================================================================================================== - BitwiseXor +BitwiseXor ====================================================================================================================== - + .. raw:: html @@ -4988,20 +4918,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ^ -
    +
             ::= PrimaryExpression ( '^' PrimaryExpression )*
    Referenced by: -
    +
    ====================================================================================================================== - ArrayExpression +ArrayExpression ====================================================================================================================== - + .. raw:: html @@ -5017,23 +4947,23 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ] -
    +
             ::= ( '[' SimpleExpression? ( ':' SimpleExpression? )? ']' )+
    Referenced by: -
    +
    ====================================================================================================================== - PrimaryExpression +PrimaryExpression ====================================================================================================================== - + .. raw:: html - + @@ -5085,79 +5015,72 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. S_HEX - CastExpression - - TryCastExpression - - SafeCastExpression - - K_TIME_KEY_EXPR - CURRENT - - DateTimeLiteralExpression - ARRAY - - ArrayConstructor - - NextValExpression - - ConnectByRootOperator - ALL - - Column - - S_CHAR_LITERAL - {d - - {t - - {ts - - S_CHAR_LITERAL - } - - ParenthesedSelectBody - ( - - ComplexExpressionList - - SimpleExpressionList - ) - - . - - RelObjectNameExt - COLLATE - - S_IDENTIFIER - - IntervalExpressionWithoutInterval - - ArrayExpression - :: - - ColDataType - AT - - K_DATETIMELITERAL - ZONE - - PrimaryExpression - -
    + CastExpression + + CharacterPrimary + + K_TIME_KEY_EXPR + CURRENT + + DateTimeLiteralExpression + ARRAY + + ArrayConstructor + + NextValExpression + + ConnectByRootOperator + ALL + + Column + + S_CHAR_LITERAL + {d + + {t + + {ts + + S_CHAR_LITERAL + } + + ParenthesedSelect + + ParenthesedExpressionList + . + + RelObjectNameExt + COLLATE + + S_IDENTIFIER + + IntervalExpressionWithoutInterval + + ArrayExpression + :: + + ColDataType + AT + + K_DATETIMELITERAL + ZONE + + PrimaryExpression + +
    -
             ::= ( 'NOT' | '!' )? ( '+' | '-' | '~' )? ( 'NULL' | CaseWhenExpression | SimpleJdbcParameter | JdbcNamedParameter | UserVariable | NumericBind | ExtractExpression | MySQLGroupConcat | XMLSerializeExpr | JsonExpression | JsonFunction | JsonAggregateFunction | FullTextSearch | Function AnalyticExpression? | IntervalExpression | S_DOUBLE | S_LONG | S_HEX | CastExpression | TryCastExpression | SafeCastExpression | K_TIME_KEY_EXPR | 'CURRENT' | DateTimeLiteralExpression | 'ARRAY' ArrayConstructor | NextValExpression | ConnectByRootOperator | 'ALL' | Column | S_CHAR_LITERAL | ( '{d' | '{t' | '{ts' ) S_CHAR_LITERAL '}' | ParenthesedSelectBody | '(' ( ComplexExpressionList | SimpleExpressionList ) ')' ( '.' RelObjectNameExt )? ) ( 'COLLATE' S_IDENTIFIER )? IntervalExpressionWithoutInterval? ArrayExpression? ( '::' ColDataType )* ( 'AT' K_DATETIMELITERAL 'ZONE' PrimaryExpression )*
    +
             ::= ( 'NOT' | '!' )? ( '+' | '-' | '~' )? ( 'NULL' | CaseWhenExpression | SimpleJdbcParameter | JdbcNamedParameter | UserVariable | NumericBind | ExtractExpression | MySQLGroupConcat | XMLSerializeExpr | JsonExpression | JsonFunction | JsonAggregateFunction | FullTextSearch | Function AnalyticExpression? | IntervalExpression | S_DOUBLE | S_LONG | S_HEX | CastExpression | CharacterPrimary | K_TIME_KEY_EXPR | 'CURRENT' | DateTimeLiteralExpression | 'ARRAY' ArrayConstructor | NextValExpression | ConnectByRootOperator | 'ALL' | Column | S_CHAR_LITERAL | ( '{d' | '{t' | '{ts' ) S_CHAR_LITERAL '}' | ParenthesedSelect | ParenthesedExpressionList ( '.' RelObjectNameExt )? ) ( 'COLLATE' S_IDENTIFIER )? IntervalExpressionWithoutInterval? ArrayExpression? ( '::' ColDataType )* ( 'AT' K_DATETIMELITERAL 'ZONE' PrimaryExpression )*
    +
    ====================================================================================================================== - ConnectByRootOperator +ConnectByRootOperator ====================================================================================================================== - + .. raw:: html @@ -5168,20 +5091,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Column -
    +
             ::= 'CONNECT_BY_ROOT' Column
    Referenced by: -
    +
    ====================================================================================================================== - NextValExpression +NextValExpression ====================================================================================================================== - + .. raw:: html @@ -5192,44 +5115,46 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. RelObjectNameList -
    +
             ::= K_NEXTVAL RelObjectNameList
    Referenced by: -
    +
    ====================================================================================================================== - JdbcNamedParameter +JdbcNamedParameter ====================================================================================================================== - + .. raw:: html - + - - : - - RelObjectNameExt2 - -
    + + : + + & + + IdentifierChain + +
    -
             ::= ':' RelObjectNameExt2
    +
             ::= ( ':' | '&' ) IdentifierChain
    +
    ====================================================================================================================== - OracleNamedFunctionParameter +OracleNamedFunctionParameter ====================================================================================================================== - + .. raw:: html @@ -5241,48 +5166,46 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Expression -
    +
             ::= RelObjectNameExt2 '=>' Expression
    Referenced by: -
    +
    ====================================================================================================================== - UserVariable +UserVariable ====================================================================================================================== - + .. raw:: html - - - - - @ - - @@ - - RelObjectNameExt2 - . - - -
    + + + + + @ + + @@ + + IdentifierChain + +
    -
             ::= ( '@' | '@@' ) RelObjectNameExt2 ( '.' RelObjectNameExt2 )*
    +
             ::= ( '@' | '@@' ) IdentifierChain
    +
    ====================================================================================================================== - NumericBind +NumericBind ====================================================================================================================== - + .. raw:: html @@ -5293,20 +5216,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. S_LONG -
    +
             ::= ':' S_LONG
    Referenced by: -
    +
    ====================================================================================================================== - DateTimeLiteralExpression +DateTimeLiteralExpression ====================================================================================================================== - + .. raw:: html @@ -5317,53 +5240,105 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. S_CHAR_LITERAL -
    +
             ::= K_DATETIMELITERAL S_CHAR_LITERAL
    Referenced by: -
    +
    ====================================================================================================================== - ArrayConstructor +RangeExpression ====================================================================================================================== + +.. raw:: html + + + + + + : + + Expression + +
    + + +
             ::= ':' Expression
    +
    + Referenced by: +
    + +====================================================================================================================== +ArrayConstructor +====================================================================================================================== + + .. raw:: html - + - [ - - SimpleExpression - - ArrayConstructor + [ + + Expression + + RangeExpression + + ArrayConstructor , - - ] - - -
    + + ] + + +
    -
             ::= '[' ( ( SimpleExpression | ArrayConstructor ) ( ',' ( SimpleExpression | ArrayConstructor ) )* )? ']'
    +
             ::= '[' ( ( Expression RangeExpression? | ArrayConstructor ) ( ',' ( Expression RangeExpression? | ArrayConstructor ) )* )? ']'
    +
    ====================================================================================================================== - JsonExpression +ParenthesedExpression ====================================================================================================================== + +.. raw:: html + + + + + + ( + + PrimaryExpression + ) + + +
    + + +
             ::= '(' PrimaryExpression ')'
    +
    + Referenced by: +
    + +====================================================================================================================== +JsonExpression +====================================================================================================================== + + .. raw:: html - + @@ -5379,48 +5354,62 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. JsonAggregateFunction - FullTextSearch - - SimpleFunction + FullTextSearch + + Function Column - S_CHAR_LITERAL - ( - - ParenthesedSelectBody - ) - - :: - - ColDataType - -> - - ->> - - S_CHAR_LITERAL - - S_LONG - #> - - #>> - - S_CHAR_LITERAL - -
    + S_CHAR_LITERAL + + ParenthesedExpression + + ParenthesedSelect + :: + + ColDataType + -> + + ->> + + S_CHAR_LITERAL + + S_LONG + #> + + #>> + + S_CHAR_LITERAL + :: + + ColDataType + -> + + ->> + + S_CHAR_LITERAL + + S_LONG + #> + + #>> + + S_CHAR_LITERAL + +
    - +
             ::= ( CaseWhenExpression | SimpleJdbcParameter | JdbcNamedParameter | UserVariable | JsonFunction | JsonAggregateFunction | FullTextSearch | Function | Column | S_CHAR_LITERAL | ParenthesedExpression | ParenthesedSelect ) ( '::' ColDataType )* ( ( '->' | '->>' ) ( S_CHAR_LITERAL | S_LONG ) | ( '#>' | '#>>' ) S_CHAR_LITERAL )+ ( ( '::' ColDataType )+ ( ( '->' | '->>' ) ( S_CHAR_LITERAL | S_LONG ) | ( '#>' | '#>>' ) S_CHAR_LITERAL )* )*
    Referenced by: -
    +
    ====================================================================================================================== - JsonFunction +JsonFunction ====================================================================================================================== - + .. raw:: html @@ -5503,21 +5492,21 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= ( 'JSON_OBJECT' '(' ( 'KEY'? S_CHAR_LITERAL ( ( ':' | ',' | 'VALUE' ) Expression ( 'FORMAT' 'JSON' )? )? ( ',' 'KEY'? S_CHAR_LITERAL ( ':' | ',' | 'VALUE' ) Expression ( 'FORMAT' 'JSON' )? )* )? ( ( 'NULL' | 'ABSENT' ) 'ON' 'NULL' )? ( ( 'WITH' | 'WITHOUT' ) 'UNIQUE' 'KEYS' )? | 'JSON_ARRAY' '(' ( 'NULL' 'ON' 'NULL' | Expression ( 'FORMAT' 'JSON' )? ( ',' Expression ( 'FORMAT' 'JSON' )? )* )* ( 'ABSENT' 'ON' 'NULL' )? ) ')'
    +
    ====================================================================================================================== - JsonAggregateFunction +JsonAggregateFunction ====================================================================================================================== - + .. raw:: html @@ -5619,21 +5608,21 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= ( 'JSON_OBJECTAGG' '(' 'KEY'? ( DT_ZONE | S_DOUBLE | S_LONG | S_HEX | S_CHAR_LITERAL | S_IDENTIFIER | S_QUOTED_IDENTIFIER ) ( ':' | 'VALUE' ) ( S_IDENTIFIER | S_QUOTED_IDENTIFIER ) ( 'FORMAT' 'JSON' )? ( ( 'NULL' | 'ABSENT' ) 'ON' 'NULL' )? ( ( 'WITH' | 'WITHOUT' ) 'UNIQUE' 'KEYS' )? | 'JSON_ARRAYAGG' '(' Expression ( 'FORMAT' 'JSON' )? OrderByElements? ( ( 'NULL' | 'ABSENT' ) 'ON' 'NULL' )? ) ')' ( 'FILTER' '(' 'WHERE' Expression ')' )? ( 'OVER' '(' ( 'PARTITION' 'BY' ( ComplexExpressionList | '(' ComplexExpressionList ')' ) )? OrderByElements? WindowElement? ')' )?
    +
    ====================================================================================================================== - IntervalExpression +IntervalExpression ====================================================================================================================== - + .. raw:: html @@ -5662,20 +5651,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. K_DATE_LITERAL -
    +
    Referenced by: -
    +
    ====================================================================================================================== - IntervalExpressionWithoutInterval +IntervalExpressionWithoutInterval ====================================================================================================================== - + .. raw:: html @@ -5684,20 +5673,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. K_DATE_LITERAL -
    +
             ::= K_DATE_LITERAL
    Referenced by: -
    +
    ====================================================================================================================== - KeepExpression +KeepExpression ====================================================================================================================== - + .. raw:: html @@ -5717,20 +5706,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= 'KEEP' '(' S_IDENTIFIER ( 'FIRST' | 'LAST' ) OrderByElements ')'
    +
    ====================================================================================================================== - windowFun +windowFun ====================================================================================================================== - + .. raw:: html @@ -5767,20 +5756,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= ( ( 'IGNORE' 'NULLS' )? 'OVER' | 'WITHIN' 'GROUP' ) ( RelObjectName | windowDefinition ( 'OVER' '(' ( 'PARTITION' 'BY' ( ComplexExpressionList | '(' ComplexExpressionList ')' ) )? ')' )? )
    Referenced by: -
    +
    ====================================================================================================================== - windowDefinition +windowDefinition ====================================================================================================================== - + .. raw:: html @@ -5805,20 +5794,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= '(' ( 'PARTITION' 'BY' ( ComplexExpressionList | '(' ComplexExpressionList ')' ) )? OrderByElements? WindowElement? ')'
    Referenced by: -
    +
    ====================================================================================================================== - AnalyticExpression +AnalyticExpression ====================================================================================================================== - + .. raw:: html @@ -5838,21 +5827,21 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. windowFun -
    +
             ::= 'FILTER' '(' 'WHERE' Expression ')' windowFun?
               | windowFun
    Referenced by: -
    +
    ====================================================================================================================== - WindowElement +WindowElement ====================================================================================================================== - + .. raw:: html @@ -5870,20 +5859,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. WindowOffset -
    +
             ::= ( 'ROWS' | 'RANGE' ) ( 'BETWEEN' WindowOffset 'AND' )? WindowOffset
    +
    ====================================================================================================================== - WindowOffset +WindowOffset ====================================================================================================================== - + .. raw:: html @@ -5902,21 +5891,21 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ROW -
    +
             ::= ( 'UNBOUNDED' | SimpleExpression ) ( 'PRECEDING' | 'FOLLOWING' )
               | 'CURRENT' 'ROW'
    Referenced by: -
    +
    ====================================================================================================================== - ExtractExpression +ExtractExpression ====================================================================================================================== - + .. raw:: html @@ -5936,122 +5925,67 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= 'EXTRACT' '(' ( RelObjectName | S_CHAR_LITERAL ) 'FROM' SimpleExpression ')'
    Referenced by: -
    +
    ====================================================================================================================== - CastExpression +CastExpression ====================================================================================================================== - -.. raw:: html - - - - - - CAST - - ( - - SimpleExpression - AS - - RowConstructor - - ColDataType - ) - - -
    - - -
             ::= 'CAST' '(' SimpleExpression 'AS' ( RowConstructor | ColDataType ) ')'
    -
    - Referenced by: -
    - - -====================================================================================================================== - TryCastExpression -====================================================================================================================== - .. raw:: html - - - - - TRY_CAST - - ( - - SimpleExpression - AS - - RowConstructor - - ColDataType - ) - - -
    + + + + + CAST + + SAFE_CAST + + TRY_CAST + + ( + + SimpleExpression + AS + + ROW + + ( + + ColumnDefinition + , + + ) + + ColDataType + ) + + +
    - -
             ::= 'TRY_CAST' '(' SimpleExpression 'AS' ( RowConstructor | ColDataType ) ')'
    + +
             ::= ( 'CAST' | 'SAFE_CAST' | 'TRY_CAST' ) '(' SimpleExpression 'AS' ( 'ROW' '(' ColumnDefinition ( ',' ColumnDefinition )* ')' | ColDataType ) ')'
    Referenced by: -
    +
    ====================================================================================================================== - SafeCastExpression +CaseWhenExpression ====================================================================================================================== - -.. raw:: html - - - - - - SAFE_CAST - - ( - - SimpleExpression - AS - - RowConstructor - - ColDataType - ) - - -
    - - -
             ::= 'SAFE_CAST' '(' SimpleExpression 'AS' ( RowConstructor | ColDataType ) ')'
    -
    - Referenced by: -
    - - -====================================================================================================================== - CaseWhenExpression -====================================================================================================================== - .. raw:: html - + @@ -6061,92 +5995,87 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. WhenThenSearchCondition ELSE - - ( - - CaseWhenExpression - ) - - Expression - END - - -
    + + ( + + CaseWhenExpression + ) + + CaseWhenExpression + + Expression + + SimpleExpression + END + + +
    -
             ::= 'CASE' Expression? WhenThenSearchCondition+ ( 'ELSE' ( '('? CaseWhenExpression ')'? | Expression ) )? 'END'
    +
             ::= 'CASE' Expression? WhenThenSearchCondition+ ( 'ELSE' ( '(' CaseWhenExpression ')' | CaseWhenExpression | Expression | SimpleExpression ) )? 'END'
    +
    ====================================================================================================================== - WhenThenSearchCondition +WhenThenSearchCondition ====================================================================================================================== - + .. raw:: html - + WHEN Expression - THEN - - ( - - CaseWhenExpression - ) - - Expression - -
    + THEN + + Expression + + SimpleExpression + +
    -
             ::= 'WHEN' Expression 'THEN' ( '('? CaseWhenExpression ')'? | Expression )
    +
             ::= 'WHEN' Expression 'THEN' ( Expression | SimpleExpression )
    Referenced by: -
    +
    ====================================================================================================================== - RowConstructor +RowConstructor ====================================================================================================================== - + .. raw:: html - - - - - ROW - - ( - - ColumnDefinition - , - - ) - - -
    + + + + + ROW + + ParenthesedExpressionList + +
    -
             ::= 'ROW'? '(' ColumnDefinition ( ',' ColumnDefinition )* ')'
    +
             ::= 'ROW' ParenthesedExpressionList
    +
    ====================================================================================================================== - VariableExpression +VariableExpression ====================================================================================================================== - + .. raw:: html @@ -6158,107 +6087,97 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SimpleExpression -
    +
             ::= UserVariable '=' SimpleExpression
    - Referenced by: -
    + Not referenced by any. +
    ====================================================================================================================== - Execute +Execute ====================================================================================================================== - + .. raw:: html - - - - - EXEC - - EXECUTE - - CALL - - RelObjectNameList - - VariableExpression - , - - SimpleExpressionList - ( - - SimpleExpressionList - ) - - -
    + + + + + EXEC + + EXECUTE + + CALL + + RelObjectNameList + + ExpressionList + +
    -
    Execute  ::= ( 'EXEC' | 'EXECUTE' | 'CALL' ) RelObjectNameList ( VariableExpression ( ',' VariableExpression )* | SimpleExpressionList | '(' SimpleExpressionList ')' )?
    +
    Execute  ::= ( 'EXEC' | 'EXECUTE' | 'CALL' ) RelObjectNameList ExpressionList?
    Referenced by: -
    +
    ====================================================================================================================== - FullTextSearch +FullTextSearch ====================================================================================================================== - + .. raw:: html - - - - - MATCH - - ( - - Column - , - - ) - - AGAINST - - ( - - S_CHAR_LITERAL - - SimpleJdbcParameter - - SimpleJdbcNamedParameter - IN NATURAL LANGUAGE MODE - - IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION - - IN BOOLEAN MODE - - WITH QUERY EXPANSION - - ) - - -
    + + + + + MATCH + + ( + + ColumnList + ) + + AGAINST + + ( + + S_CHAR_LITERAL + + SimpleJdbcParameter + + SimpleJdbcNamedParameter + IN NATURAL LANGUAGE MODE + + IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION + + IN BOOLEAN MODE + + WITH QUERY EXPANSION + + ) + + +
    -
             ::= 'MATCH' '(' Column ( ',' Column )* ')' 'AGAINST' '(' ( S_CHAR_LITERAL | SimpleJdbcParameter | SimpleJdbcNamedParameter ) ( 'IN NATURAL LANGUAGE MODE' | 'IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION' +
             ::= 'MATCH' '(' ColumnList ')' 'AGAINST' '(' ( S_CHAR_LITERAL | SimpleJdbcParameter | SimpleJdbcNamedParameter ) ( 'IN NATURAL LANGUAGE MODE' | 'IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION' | 'IN BOOLEAN MODE' | 'WITH QUERY EXPANSION' )? ')'
    +
    ====================================================================================================================== - Function +Function ====================================================================================================================== - + .. raw:: html @@ -6276,57 +6195,53 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. InternalFunction -
    +
    Function ::= '{' 'FN' InternalFunction '}'
               | InternalFunction
    +
    ====================================================================================================================== - SpecialStringFunctionWithNamedParameters +SpecialStringFunctionWithNamedParameters ====================================================================================================================== - + .. raw:: html - + K_STRING_FUNCTION_NAME - ( - - NamedExpressionList1 - - NamedExpressionListExprFirst - - ComplexExpressionList - - SimpleExpressionList + ( + + NamedExpressionListExprFirst + + ExpressionList ) - + -
    +
    - +
    Referenced by: -
    +
    ====================================================================================================================== - InternalFunction +InternalFunction ====================================================================================================================== - + .. raw:: html - + @@ -6341,87 +6256,41 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. * - AllTableColumns - - ComplexExpressionList - - SimpleExpressionList - - OrderByElements - - SelectBody - IGNORE - - NULLS - - ) - - . - - Function - - Column - - KeepExpression - -
    + AllTableColumns + + ExpressionList + + OrderByElements + + Select + IGNORE + + NULLS + + ) + + . + + Function + + Column + + KeepExpression + +
    -
             ::= RelObjectNameList '(' ( ( 'DISTINCT' | 'ALL' | 'UNIQUE' )? ( '*' | AllTableColumns | ( ComplexExpressionList | SimpleExpressionList ) OrderByElements? | SelectBody ) )? ( 'IGNORE' 'NULLS' )? ')' ( '.' ( Function | Column ) )? KeepExpression?
    +
             ::= RelObjectNameList '(' ( ( 'DISTINCT' | 'ALL' | 'UNIQUE' )? ( '*' | AllTableColumns | ExpressionList OrderByElements? | Select ) )? ( 'IGNORE' 'NULLS' )? ')' ( '.' ( Function | Column ) )? KeepExpression?
    Referenced by: -
    +
    ====================================================================================================================== - SimpleFunction +XMLSerializeExpr ====================================================================================================================== - -.. raw:: html - - - - - - RelObjectNameList - ( - - DISTINCT - - ALL - - UNIQUE - - * - - AllTableColumns - - SimpleExpressionList - - OrderByElements - IGNORE - - NULLS - - ) - - KeepExpression - -
    - - -
             ::= RelObjectNameList '(' ( ( 'DISTINCT' | 'ALL' | 'UNIQUE' )? ( '*' | AllTableColumns | SimpleExpressionList OrderByElements? ) )? ( 'IGNORE' 'NULLS' )? ')' KeepExpression?
    -
    - Referenced by: -
    - - -====================================================================================================================== - XMLSerializeExpr -====================================================================================================================== - .. raw:: html @@ -6452,23 +6321,23 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= 'XMLSERIALIZE' '(' 'XMLAGG' '(' 'XMLTEXT' '(' SimpleExpression ')' OrderByElements? ')' 'AS' ColDataType ')'
    Referenced by: -
    +
    ====================================================================================================================== - MySQLGroupConcat +MySQLGroupConcat ====================================================================================================================== - + .. raw:: html - + @@ -6476,57 +6345,31 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ( - DISTINCT - - SimpleExpressionList - - OrderByElements - SEPARATOR - - S_CHAR_LITERAL - ) - - -
    + DISTINCT + + ExpressionList + + OrderByElements + SEPARATOR + + S_CHAR_LITERAL + ) + + +
    -
             ::= 'GROUP_CONCAT' '(' 'DISTINCT'? SimpleExpressionList OrderByElements? ( 'SEPARATOR' S_CHAR_LITERAL )? ')'
    +
             ::= 'GROUP_CONCAT' '(' 'DISTINCT'? ExpressionList OrderByElements? ( 'SEPARATOR' S_CHAR_LITERAL )? ')'
    Referenced by: -
    +
    ====================================================================================================================== - ValueListExpression +TableFunction ====================================================================================================================== - -.. raw:: html - - - - - - ( - - SimpleExpressionListAtLeastTwoItems - ) - - -
    - - -
             ::= '(' SimpleExpressionListAtLeastTwoItems ')'
    -
    - Referenced by: -
    - - -====================================================================================================================== - TableFunction -====================================================================================================================== - .. raw:: html @@ -6537,20 +6380,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Alias -
    +
             ::= Function Alias?
    Referenced by: -
    +
    ====================================================================================================================== - ColumnNamesWithParamsList +ColumnNamesWithParamsList ====================================================================================================================== - + .. raw:: html @@ -6567,20 +6410,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= '(' RelObjectName CreateParameter? ( ',' RelObjectName CreateParameter? )* ')'
    Referenced by: -
    +
    ====================================================================================================================== - Index +Index ====================================================================================================================== - + .. raw:: html @@ -6589,56 +6432,54 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. RelObjectNameList -
    +
    Referenced by: -
    +
    ====================================================================================================================== - CreateIndex +CreateIndex ====================================================================================================================== - + .. raw:: html - + - - - CREATE - - CreateParameter - INDEX - - Index - ON - - Table - USING - - S_IDENTIFIER - - ColumnNamesWithParamsList - - CreateParameter - -
    + + + CreateParameter + INDEX + + Index + ON + + Table + USING + + S_IDENTIFIER + + ColumnNamesWithParamsList + + CreateParameter + +
    -
             ::= 'CREATE' CreateParameter? 'INDEX' Index 'ON' Table ( 'USING' S_IDENTIFIER )? ColumnNamesWithParamsList CreateParameter*
    +
             ::= CreateParameter? 'INDEX' Index 'ON' Table ( 'USING' S_IDENTIFIER )? ColumnNamesWithParamsList CreateParameter*
    Referenced by: -
    +
    ====================================================================================================================== - ColumnDefinition +ColumnDefinition ====================================================================================================================== - + .. raw:: html @@ -6651,59 +6492,58 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. CreateParameter -
    +
    +
    ====================================================================================================================== - CreateSchema +CreateSchema ====================================================================================================================== - + .. raw:: html - + - - CREATE - - SCHEMA - - S_IDENTIFIER - - S_QUOTED_IDENTIFIER - AUTHORIZATION - - S_IDENTIFIER - - S_QUOTED_IDENTIFIER - - PathSpecification - - CreateTable - - CreateView - -
    + + SCHEMA + + S_IDENTIFIER + + S_QUOTED_IDENTIFIER + AUTHORIZATION + + S_IDENTIFIER + + S_QUOTED_IDENTIFIER + + PathSpecification + CREATE + + CreateTable + + CreateView + +
    -
             ::= 'CREATE' 'SCHEMA' ( S_IDENTIFIER | S_QUOTED_IDENTIFIER )? ( 'AUTHORIZATION' ( S_IDENTIFIER | S_QUOTED_IDENTIFIER ) )? PathSpecification? ( CreateTable | CreateView )*
    +
             ::= 'SCHEMA' ( S_IDENTIFIER | S_QUOTED_IDENTIFIER )? ( 'AUTHORIZATION' ( S_IDENTIFIER | S_QUOTED_IDENTIFIER ) )? PathSpecification? ( 'CREATE' CreateTable | CreateView )*
    Referenced by: -
    +
    ====================================================================================================================== - PathSpecification +PathSpecification ====================================================================================================================== - + .. raw:: html @@ -6718,46 +6558,40 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. , -
    +
             ::= 'PATH' ( S_IDENTIFIER | S_QUOTED_IDENTIFIER ) ( ',' ( S_IDENTIFIER | S_QUOTED_IDENTIFIER ) )*
    Referenced by: -
    +
    ====================================================================================================================== - CreateTable +CreateTable ====================================================================================================================== - + .. raw:: html - - CREATE - - OR - - REPLACE - - UNLOGGED - - GLOBAL - - CreateParameter - TABLE - - IF - - NOT - - EXISTS - - Table + + UNLOGGED + + GLOBAL + + CreateParameter + TABLE + + IF + + NOT + + EXISTS + + Table ( ColumnDefinition @@ -6853,22 +6687,22 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Table , - SpannerInterleaveIn + SpannerInterleaveIn -
    +
    -
             ::= 'CREATE' ( 'OR' 'REPLACE' )? 'UNLOGGED'? 'GLOBAL'? CreateParameter* 'TABLE' ( 'IF' 'NOT' 'EXISTS' )? Table ( '(' ( RelObjectName ( ',' RelObjectName )* | ColumnDefinition ( ',' ( ( 'INDEX' | 'UNIQUE'? 'FULLTEXT'? 'KEY' ) RelObjectName ColumnNamesWithParamsList CreateParameter* | ( 'CONSTRAINT' RelObjectName )? ( ( 'PRIMARY' 'KEY' | 'UNIQUE' 'KEY'? ) ColumnNamesWithParamsList CreateParameter* | 'FOREIGN' 'KEY' ColumnNamesWithParamsList 'REFERENCES' Table ColumnsNamesList ( 'ON' ( 'DELETE' | 'UPDATE' ) Action )? ( 'ON' ( 'DELETE' | 'UPDATE' ) Action )? | 'CHECK' ( '(' Expression ')' )* ) | 'EXCLUDE' 'WHERE' ( '(' Expression ')' )* | ColumnDefinition ) )* ) ')' )? CreateParameter* RowMovement? ( 'AS' Select )? ( 'LIKE' ( '(' Table ')' | Table ) )? ( ',' SpannerInterleaveIn )?
    +
             ::= 'UNLOGGED'? 'GLOBAL'? CreateParameter* 'TABLE' ( 'IF' 'NOT' 'EXISTS' )? Table ( '(' ( RelObjectName ( ',' RelObjectName )* | ColumnDefinition ( ',' ( ( 'INDEX' | 'UNIQUE'? 'FULLTEXT'? 'KEY' ) RelObjectName ColumnNamesWithParamsList CreateParameter* | ( 'CONSTRAINT' RelObjectName )? ( ( 'PRIMARY' 'KEY' | 'UNIQUE' 'KEY'? ) ColumnNamesWithParamsList CreateParameter* | 'FOREIGN' 'KEY' ColumnNamesWithParamsList 'REFERENCES' Table ColumnsNamesList ( 'ON' ( 'DELETE' | 'UPDATE' ) Action )? ( 'ON' ( 'DELETE' | 'UPDATE' ) Action )? | 'CHECK' ( '(' Expression ')' )* ) | 'EXCLUDE' 'WHERE' ( '(' Expression ')' )* | ColumnDefinition ) )* ) ')' )? CreateParameter* RowMovement? ( 'AS' Select )? ( 'LIKE' ( '(' Table ')' | Table ) )? ( ',' SpannerInterleaveIn )?
    Referenced by: -
    +
    ====================================================================================================================== - SpannerInterleaveIn +SpannerInterleaveIn ====================================================================================================================== - + .. raw:: html @@ -6893,20 +6727,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. CASCADE -
    +
             ::= 'INTERLEAVE' 'IN' 'PARENT' Table ( 'ON' 'DELETE' ( 'NO' 'ACTION' | 'CASCADE' ) )?
    Referenced by: -
    +
    ====================================================================================================================== - ColDataType +ColDataType ====================================================================================================================== - + .. raw:: html @@ -7004,20 +6838,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. BINARY -
    +
             ::= ( 'ARRAY' '<' ColDataType '>' | ( 'BYTES' | 'STRING' | 'JSON' ) '(' ( S_LONG | S_IDENTIFIER ) ')' | ( 'CHARACTER' | 'BIT' ) 'VARYING'? | 'DOUBLE' 'PRECISION'? | ( S_IDENTIFIER | S_QUOTED_IDENTIFIER | K_DATETIMELITERAL | K_DATE_LITERAL | 'XML' | 'INTERVAL' | DT_ZONE | 'CHAR' | 'SET' | 'BINARY' | 'JSON' | 'STRING' ) ( '.' ( S_IDENTIFIER | S_QUOTED_IDENTIFIER ) )? | ( 'UNSIGNED' | 'SIGNED' ) S_IDENTIFIER? ) ( '(' ( ( S_LONG ( 'BYTE' | 'CHAR' )? | S_CHAR_LITERAL | S_IDENTIFIER | 'CHAR' ) ','? )* ')' )? ( '[' S_LONG? ']' )* ( 'CHARACTER' 'SET' ( S_IDENTIFIER | 'BINARY' ) )?
    +
    ====================================================================================================================== - Analyze +Analyze ====================================================================================================================== - + .. raw:: html @@ -7028,84 +6862,77 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. Table -
    +
    Analyze  ::= 'ANALYZE' Table
    Referenced by: -
    +
    ====================================================================================================================== - CreateView +CreateView ====================================================================================================================== - + .. raw:: html - - - - - CREATE - - OR - - REPLACE - - NO - - FORCE - - TEMP - - TEMPORARY - - MATERIALIZED - - VIEW - - Table - AUTO - - REFRESH - - YES - - NO - - IF - - NOT - - EXISTS - - ColumnsNamesList - AS - - Select - WITH - - READ - - ONLY - - -
    + + + + + NO + + FORCE + + TEMP + + TEMPORARY + + MATERIALIZED + + VIEW + + Table + AUTO + + REFRESH + + YES + + NO + + IF + + NOT + + EXISTS + + ColumnsNamesList + AS + + Select + WITH + + READ + + ONLY + + +
    -
             ::= 'CREATE' ( 'OR' 'REPLACE' )? ( 'NO'? 'FORCE' )? ( 'TEMP' | 'TEMPORARY' - )? 'MATERIALIZED'? 'VIEW' Table ( 'AUTO' 'REFRESH' ( 'YES' | 'NO' ) )? ( 'IF' 'NOT' 'EXISTS' )? ColumnsNamesList? 'AS' Select ( 'WITH' 'READ' 'ONLY' )?
    +
             ::= ( 'NO'? 'FORCE' )? ( 'TEMP' | 'TEMPORARY' )? 'MATERIALIZED'? 'VIEW' Table ( 'AUTO' 'REFRESH' ( 'YES' | 'NO' ) )? ( 'IF' 'NOT' 'EXISTS' )? ColumnsNamesList? 'AS' Select ( 'WITH' 'READ' 'ONLY' )?
    Referenced by: -
    +
    ====================================================================================================================== - Action +Action ====================================================================================================================== - + .. raw:: html @@ -7127,7 +6954,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. DEFAULT -
    +
    Action   ::= 'CASCADE'
               | 'RESTRICT'
    @@ -7135,193 +6962,194 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'SET' ( 'NULL' | 'DEFAULT' )
    Referenced by: -
    +
    ====================================================================================================================== - AlterView +AlterView ====================================================================================================================== - + .. raw:: html - + - - ALTER - - REPLACE - - VIEW - - Table - - ColumnsNamesList - AS - - SelectBody - -
    + + VIEW + + Table + + ColumnsNamesList + AS + + Select + +
    -
             ::= ( 'ALTER' | 'REPLACE' ) 'VIEW' Table ColumnsNamesList? 'AS' SelectBody
    +
             ::= 'VIEW' Table ColumnsNamesList? 'AS' Select
    Referenced by: -
    +
    ====================================================================================================================== - CreateParameter +CreateParameter ====================================================================================================================== - + .. raw:: html - + - - - S_IDENTIFIER - - S_QUOTED_IDENTIFIER - . - - S_IDENTIFIER - - S_QUOTED_IDENTIFIER - NULL - - NOT - - PRIMARY - - DEFAULT - - FOREIGN - - REFERENCES - - KEY - - S_CHAR_LITERAL - + - - - - - S_LONG - - S_DOUBLE - AS - - ( - - Expression - ) - - STORED - - ON - - COMMIT - - DROP - - ROWS - - UNIQUE - - CASCADE - - DELETE - - UPDATE - - K_TIME_KEY_EXPR - = - - USING - - INDEX - - TABLESPACE - - RelObjectName - TABLESPACE - - RelObjectName - - AList - CHECK - - ( - - Expression - ) - - CONSTRAINT - - WITH - - EXCLUDE - - WHERE - - UNSIGNED - - TEMP - - TEMPORARY - - PARTITION - - BY - - IN - - TYPE - - COMMENT - - COLLATE - - ASC - - DESC - - TRUE - - FALSE - - PARALLEL - - BINARY - - CHARACTER - - SET - - ARRAY - - ArrayConstructor - :: - - ColDataType + + + K_NEXTVAL + ( + + S_CHAR_LITERAL + :: + + ColDataType + ) + + S_IDENTIFIER + + S_QUOTED_IDENTIFIER + . + + S_IDENTIFIER + + S_QUOTED_IDENTIFIER + USING + + INDEX + + TABLESPACE + + RelObjectName + + S_CHAR_LITERAL + NULL + + NOT + + PRIMARY + + FOREIGN + + REFERENCES + + KEY + + STORED + + ON + + COMMIT + + DROP + + ROWS + + UNIQUE + + CASCADE + + DELETE + + UPDATE + + CONSTRAINT + + WITH + + EXCLUDE + + WHERE + + UNSIGNED + + TEMP + + TEMPORARY + + PARTITION + + BY + + IN + + TYPE + + COMMENT + + USING + + COLLATE + + ASC + + DESC + + TRUE + + FALSE + + PARALLEL + + BINARY + + START + + K_TIME_KEY_EXPR + = + + DEFAULT + + AS + + CHECK + + ( + + Expression + ) + + + + + - + + S_LONG + + S_DOUBLE + + AList + CHARACTER + + SET + + ARRAY + + ArrayConstructor + :: + + ColDataType -
    +
    -
             ::= ( S_IDENTIFIER | S_QUOTED_IDENTIFIER ) ( '.' ( S_IDENTIFIER | S_QUOTED_IDENTIFIER ) )?
    +
             ::= K_NEXTVAL '(' S_CHAR_LITERAL '::' ColDataType ')'
    +
               | ( S_IDENTIFIER | S_QUOTED_IDENTIFIER ) ( '.' ( S_IDENTIFIER | S_QUOTED_IDENTIFIER ) )?
    +
               | ( 'USING' 'INDEX' )? 'TABLESPACE' RelObjectName
    +
               | S_CHAR_LITERAL
               | 'NULL'
               | 'NOT'
               | 'PRIMARY'
    -
               | 'DEFAULT'
               | 'FOREIGN'
               | 'REFERENCES'
               | 'KEY'
    -
               | S_CHAR_LITERAL
    -
               | ( '+' | '-' )? ( S_LONG | S_DOUBLE )
    -
               | 'AS' ( '(' Expression ')' )?
               | 'STORED'
               | 'ON'
               | 'COMMIT'
    @@ -7331,12 +7159,6 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'CASCADE'
               | 'DELETE'
               | 'UPDATE'
    -
               | K_TIME_KEY_EXPR
    -
               | '='
    -
               | 'USING' ( 'INDEX' 'TABLESPACE' RelObjectName )?
    -
               | 'TABLESPACE' RelObjectName
    -
               | AList
    -
               | 'CHECK' '(' Expression ')'
               | 'CONSTRAINT'
               | 'WITH'
               | 'EXCLUDE'
    @@ -7349,6 +7171,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'IN'
               | 'TYPE'
               | 'COMMENT'
    +
               | 'USING'
               | 'COLLATE'
               | 'ASC'
               | 'DESC'
    @@ -7356,19 +7179,26 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'FALSE'
               | 'PARALLEL'
               | 'BINARY'
    +
               | 'START'
    +
               | K_TIME_KEY_EXPR
    +
               | '='
    +
               | ( 'DEFAULT' | 'AS' | 'CHECK' ) ( '(' Expression ')' )?
    +
               | ( '+' | '-' )? S_LONG
    +
               | S_DOUBLE
    +
               | AList
               | 'CHARACTER' 'SET'
               | 'ARRAY' ArrayConstructor
               | '::' ColDataType
    +
    ====================================================================================================================== - RowMovement +RowMovement ====================================================================================================================== - + .. raw:: html @@ -7384,20 +7214,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. MOVEMENT -
    +
             ::= ( 'ENABLE' | 'DISABLE' ) 'ROW' 'MOVEMENT'
    Referenced by: -
    +
    ====================================================================================================================== - AList +AList ====================================================================================================================== - + .. raw:: html @@ -7420,19 +7250,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
    AList    ::= '(' ( ( S_LONG | S_DOUBLE | S_CHAR_LITERAL | RelObjectNameWithoutValue ) ( ',' | '=' )? )* ')'
    Referenced by: -
    +
    ====================================================================================================================== - ColumnsNamesListItem +ColumnsNamesListItem ====================================================================================================================== - + .. raw:: html @@ -7446,20 +7276,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= RelObjectName ( '(' S_LONG ')' )?
    Referenced by: -
    +
    ====================================================================================================================== - ColumnsNamesList +ColumnsNamesList ====================================================================================================================== - + .. raw:: html @@ -7474,20 +7304,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= '(' ColumnsNamesListItem ( ',' ColumnsNamesListItem )* ')'
    +
    ====================================================================================================================== - FuncArgsListItem +FuncArgsListItem ====================================================================================================================== - + .. raw:: html @@ -7503,20 +7333,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= RelObjectName RelObjectName? ( '(' S_LONG ')' )?
    Referenced by: -
    +
    ====================================================================================================================== - FuncArgsList +FuncArgsList ====================================================================================================================== - + .. raw:: html @@ -7531,20 +7361,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ) -
    +
             ::= '(' ( FuncArgsListItem ( ',' FuncArgsListItem )* )? ')'
    Referenced by: -
    +
    ====================================================================================================================== - Drop +Drop ====================================================================================================================== - + .. raw:: html @@ -7586,20 +7416,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ON -
    +
    Drop     ::= 'DROP' 'MATERIALIZED'? ( S_IDENTIFIER | 'TEMPORARY'? 'TABLE' | 'INDEX' | 'VIEW' | 'SCHEMA' | 'SEQUENCE' | 'FUNCTION' ) ( 'IF' 'EXISTS' )? Table FuncArgsList? ( S_IDENTIFIER | 'CASCADE' | 'RESTRICT' | 'ON' )*
    Referenced by: -
    +
    ====================================================================================================================== - Truncate +Truncate ====================================================================================================================== - + .. raw:: html @@ -7616,19 +7446,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. CASCADE -
    +
    Truncate ::= 'TRUNCATE' 'TABLE'? 'ONLY'? Table 'CASCADE'?
    Referenced by: -
    +
    ====================================================================================================================== - AlterExpressionColumnDataType +AlterExpressionColumnDataType ====================================================================================================================== - + .. raw:: html @@ -7642,20 +7472,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. CreateParameter -
    +
             ::= RelObjectName 'TYPE'? ColDataType CreateParameter*
    Referenced by: -
    +
    ====================================================================================================================== - AlterExpressionColumnDropNotNull +AlterExpressionColumnDropNotNull ====================================================================================================================== - + .. raw:: html @@ -7670,20 +7500,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. NULL -
    +
             ::= RelObjectName 'DROP' 'NOT'? 'NULL'
    Referenced by: -
    +
    ====================================================================================================================== - AlterExpressionColumnDropDefault +AlterExpressionColumnDropDefault ====================================================================================================================== - + .. raw:: html @@ -7696,20 +7526,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. DEFAULT -
    +
             ::= RelObjectName 'DROP' 'DEFAULT'
    Referenced by: -
    +
    ====================================================================================================================== - AlterExpressionConstraintState +AlterExpressionConstraintState ====================================================================================================================== - + .. raw:: html @@ -7729,21 +7559,21 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. DISABLE -
    +
             ::= ( 'NOT'? 'DEFERRABLE' | 'VALIDATE' | 'NOVALIDATE' | 'ENABLE' | 'DISABLE' )*
    Referenced by: -
    +
    ====================================================================================================================== - AlterExpression +AlterExpression ====================================================================================================================== - + .. raw:: html @@ -7966,7 +7796,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. captureRest -
    +
             ::= ( 'ADD' | 'ALTER' | 'MODIFY' ) ( ( ( 'PRIMARY' 'KEY' | ( 'KEY' | 'INDEX' @@ -7979,214 +7809,247 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | captureRest
    Referenced by: -
    +
    ====================================================================================================================== - AlterTable +Alter ====================================================================================================================== + +.. raw:: html + + + + + + ALTER + + AlterTable + + AlterSession + + AlterView + + AlterSystemStatement + + AlterSequence + + captureRest + REPLACE + + AlterView + + captureRest + +
    + + +
               | 'REPLACE' ( AlterView | captureRest )
    +
    + Referenced by: +
    + +====================================================================================================================== +AlterTable +====================================================================================================================== + + .. raw:: html - + - ALTER - - TABLE - - ONLY - - IF - - EXISTS - - Table - - AlterExpression - , - - -
    + TABLE + + ONLY + + IF + + EXISTS + + Table + + AlterExpression + , + + +
    -
             ::= 'ALTER' 'TABLE' 'ONLY'? ( 'IF' 'EXISTS' )? Table AlterExpression ( ',' AlterExpression )*
    +
             ::= 'TABLE' 'ONLY'? ( 'IF' 'EXISTS' )? Table AlterExpression ( ',' AlterExpression )*
    Referenced by: -
    +
    ====================================================================================================================== - AlterSession +AlterSession ====================================================================================================================== - + .. raw:: html - + - - ALTER - - SESSION - - ADVISE - - COMMIT - - ROLLBACK - - NOTHING - - CLOSE - - DATABASE - - LINK - - ENABLE - - DISABLE - - COMMIT - - IN - - PROCEDURE - - GUARD - - PARALLEL - - DML - - DDL - - QUERY - - RESUMABLE - - FORCE - - PARALLEL - - DML - - DDL - - QUERY - - SET - - S_CHAR_LITERAL - - S_IDENTIFIER - = - - S_LONG - PARALLEL - - -
    + + SESSION + + ADVISE + + COMMIT + + ROLLBACK + + NOTHING + + CLOSE + + DATABASE + + LINK + + ENABLE + + DISABLE + + COMMIT + + IN + + PROCEDURE + + GUARD + + PARALLEL + + DML + + DDL + + QUERY + + RESUMABLE + + FORCE + + PARALLEL + + DML + + DDL + + QUERY + + SET + + S_CHAR_LITERAL + + S_IDENTIFIER + = + + S_LONG + PARALLEL + + +
    -
             ::= 'ALTER' 'SESSION' ( 'ADVISE' ( 'COMMIT' | 'ROLLBACK' | 'NOTHING' ) | - 'CLOSE' 'DATABASE' 'LINK' | ( 'ENABLE' | 'DISABLE' ) ( 'COMMIT' 'IN' 'PROCEDURE' | - 'GUARD' | 'PARALLEL' ( 'DML' | 'DDL' | 'QUERY' ) | 'RESUMABLE' ) | 'FORCE' 'PARALLEL' - ( 'DML' | 'DDL' | 'QUERY' ) | 'SET' ) ( S_CHAR_LITERAL | S_IDENTIFIER | '=' | S_LONG | 'PARALLEL' )*
    +
             ::= 'SESSION' ( 'ADVISE' ( 'COMMIT' | 'ROLLBACK' | 'NOTHING' ) | 'CLOSE' + 'DATABASE' 'LINK' | ( 'ENABLE' | 'DISABLE' ) ( 'COMMIT' 'IN' 'PROCEDURE' | 'GUARD' + | 'PARALLEL' ( 'DML' | 'DDL' | 'QUERY' ) | 'RESUMABLE' ) | 'FORCE' 'PARALLEL' ( 'DML' + | 'DDL' | 'QUERY' ) | 'SET' ) ( S_CHAR_LITERAL | S_IDENTIFIER | '=' | S_LONG | 'PARALLEL' )*
    Referenced by: -
    +
    ====================================================================================================================== - AlterSystemStatement +AlterSystemStatement ====================================================================================================================== - + .. raw:: html - + - - ALTER - - SYSTEM - - ARCHIVE - - LOG - - CHECKPOINT - - DUMP - - ACTIVE - - SESSION - - HISTORY - - ENABLE - - DISABLE - - DISTRIBUTED RECOVERY - - RESTRICTED SESSION - - FLUSH - - DISCONNECT - - SESSION - - KILL SESSION - - SWITCH - - SUSPEND - - RESUME - - QUIESCE - - RESTRICTED - - UNQUIESCE - - SHUTDOWN - - REGISTER - - SET - - RESET - - captureRest - -
    + + SYSTEM + + ARCHIVE + + LOG + + CHECKPOINT + + DUMP + + ACTIVE + + SESSION + + HISTORY + + ENABLE + + DISABLE + + DISTRIBUTED RECOVERY + + RESTRICTED SESSION + + FLUSH + + DISCONNECT + + SESSION + + KILL SESSION + + SWITCH + + SUSPEND + + RESUME + + QUIESCE + + RESTRICTED + + UNQUIESCE + + SHUTDOWN + + REGISTER + + SET + + RESET + + captureRest + +
    -
             ::= 'ALTER' 'SYSTEM' ( 'ARCHIVE' 'LOG' | 'CHECKPOINT' | 'DUMP' 'ACTIVE' 'SESSION' +
             ::= 'SYSTEM' ( 'ARCHIVE' 'LOG' | 'CHECKPOINT' | 'DUMP' 'ACTIVE' 'SESSION' 'HISTORY' | ( 'ENABLE' | 'DISABLE' ) ( 'DISTRIBUTED RECOVERY' | 'RESTRICTED SESSION' ) | 'FLUSH' | 'DISCONNECT' 'SESSION' | 'KILL SESSION' | 'SWITCH' | 'SUSPEND' | 'RESUME' | 'QUIESCE' 'RESTRICTED' | 'UNQUIESCE' | 'SHUTDOWN' | 'REGISTER' | 'SET' | 'RESET' ) captureRest
    Referenced by: -
    +
    ====================================================================================================================== - Wait +Wait ====================================================================================================================== - + .. raw:: html @@ -8197,19 +8060,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. S_LONG -
    +
    Wait     ::= 'WAIT' S_LONG
    Referenced by: -
    +
    ====================================================================================================================== - SavepointStatement +SavepointStatement ====================================================================================================================== - + .. raw:: html @@ -8220,20 +8083,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. S_IDENTIFIER -
    +
             ::= 'SAVEPOINT' S_IDENTIFIER
    Referenced by: -
    +
    ====================================================================================================================== - RollbackStatement +RollbackStatement ====================================================================================================================== - + .. raw:: html @@ -8253,20 +8116,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. S_CHAR_LITERAL -
    +
             ::= 'ROLLBACK' 'WORK'? ( 'TO' 'SAVEPOINT'? S_IDENTIFIER | 'FORCE' S_CHAR_LITERAL )?
    Referenced by: -
    +
    ====================================================================================================================== - Comment +Comment ====================================================================================================================== - + .. raw:: html @@ -8289,19 +8152,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. S_CHAR_LITERAL -
    +
    Comment  ::= 'COMMENT' 'ON' ( ( 'TABLE' | 'VIEW' ) Table | 'COLUMN' Column ) 'IS' S_CHAR_LITERAL
    Referenced by: -
    +
    ====================================================================================================================== - Grant +Grant ====================================================================================================================== - + .. raw:: html @@ -8322,19 +8185,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. UsersList -
    +
    Grant    ::= 'GRANT' ( ( readGrantTypes ( ',' readGrantTypes )* )? 'ON' RelObjectNameList | S_IDENTIFIER ) 'TO' UsersList
    Referenced by: -
    +
    ====================================================================================================================== - UsersList +UsersList ====================================================================================================================== - + .. raw:: html @@ -8346,20 +8209,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ColumnsNamesListItem -
    +
             ::= RelObjectName ( ',' ColumnsNamesListItem )*
    Referenced by: -
    +
    ====================================================================================================================== - readGrantTypes +readGrantTypes ====================================================================================================================== - + .. raw:: html @@ -8380,7 +8243,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. DROP -
    +
             ::= K_SELECT
    @@ -8392,14 +8255,14 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'DROP'
    Referenced by: -
    +
    ====================================================================================================================== - Sequence +Sequence ====================================================================================================================== - + .. raw:: html @@ -8408,19 +8271,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. RelObjectNameList -
    +
    Referenced by: -
    +
    ====================================================================================================================== - SequenceParameters +SequenceParameters ====================================================================================================================== - + .. raw:: html @@ -8470,7 +8333,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. GLOBAL -
    +
             ::= ( ( 'INCREMENT' 'BY' | 'START' 'WITH' | 'MAXVALUE' | 'MINVALUE' | 'CACHE' @@ -8478,73 +8341,69 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. | 'KEEP' | 'NOKEEP' | 'SESSION' | 'GLOBAL' )*
    Referenced by: -
    +
    ====================================================================================================================== - CreateSequence +CreateSequence ====================================================================================================================== - + .. raw:: html - + - - CREATE - - SEQUENCE - - Sequence - - SequenceParameters - -
    + + SEQUENCE + + Sequence + + SequenceParameters + +
    -
             ::= 'CREATE' 'SEQUENCE' Sequence SequenceParameters
    +
             ::= 'SEQUENCE' Sequence SequenceParameters
    Referenced by: -
    +
    ====================================================================================================================== - AlterSequence +AlterSequence ====================================================================================================================== - + .. raw:: html - + - - ALTER - - SEQUENCE - - Sequence - - SequenceParameters - -
    + + SEQUENCE + + Sequence + + SequenceParameters + +
    -
             ::= 'ALTER' 'SEQUENCE' Sequence SequenceParameters
    +
             ::= 'SEQUENCE' Sequence SequenceParameters
    Referenced by: -
    +
    ====================================================================================================================== - CreateFunctionStatement +Create ====================================================================================================================== - + .. raw:: html - + @@ -8552,63 +8411,95 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. OR - REPLACE - - FUNCTION - - PROCEDURE - - captureRest - -
    + REPLACE + + CreateFunctionStatement + + CreateSchema + + CreateSequence + + CreateSynonym + + CreateTable + + CreateView + TRIGGER + + DOMAIN + + captureRest + + CreateIndex + +
    - -
             ::= 'CREATE' ( 'OR' 'REPLACE' )? ( 'FUNCTION' | 'PROCEDURE' ) captureRest
    +
    Create   ::= 'CREATE' ( 'OR' 'REPLACE' )? ( CreateFunctionStatement | CreateSchema | CreateSequence | CreateSynonym | CreateTable | CreateView | ( 'TRIGGER' | 'DOMAIN' )? captureRest | CreateIndex )
    Referenced by: -
    +
    ====================================================================================================================== - CreateSynonym +CreateFunctionStatement ====================================================================================================================== + +.. raw:: html + + + + + + FUNCTION + + PROCEDURE + + captureFunctionBody + +
    + + +
             ::= ( 'FUNCTION' | 'PROCEDURE' ) captureFunctionBody
    +
    + Referenced by: +
    + +====================================================================================================================== +CreateSynonym +====================================================================================================================== + + .. raw:: html - + - - CREATE - - OR - - REPLACE - - PUBLIC - - SYNONYM - - Synonym - FOR - - RelObjectNameList - -
    + + PUBLIC + + SYNONYM + + Synonym + FOR + + RelObjectNameList + +
    -
             ::= 'CREATE' ( 'OR' 'REPLACE' )? 'PUBLIC'? 'SYNONYM' Synonym 'FOR' RelObjectNameList
    +
             ::= 'PUBLIC'? 'SYNONYM' Synonym 'FOR' RelObjectNameList
    Referenced by: -
    +
    ====================================================================================================================== - Synonym +Synonym ====================================================================================================================== - + .. raw:: html @@ -8617,19 +8508,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. RelObjectNameList -
    +
    Referenced by: -
    +
    ====================================================================================================================== - UnsupportedStatement +UnsupportedStatement ====================================================================================================================== - + .. raw:: html @@ -8638,20 +8529,139 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. captureUnsupportedStatementDeclaration -
    +
    Referenced by: -
    +
    + + +====================================================================================================================== +IdentifierChain +====================================================================================================================== + + +.. raw:: html + + + + + + RelObjectNameExt2 + . + + +
    + + +
             ::= RelObjectNameExt2 ( '.' RelObjectNameExt2 )*
    +
    + + +====================================================================================================================== +CharacterPrimary +====================================================================================================================== + + +.. raw:: html + + + + + + TranscodingFunction + + TrimFunction + +
    + + +
             ::= TranscodingFunction
    +
               | TrimFunction
    +
    + Referenced by: +
    + + +====================================================================================================================== +TranscodingFunction +====================================================================================================================== + + +.. raw:: html + + + + + + CONVERT + + ( + + Expression + USING + + IdentifierChain + ) + + +
    + + +
             ::= 'CONVERT' '(' Expression 'USING' IdentifierChain ')'
    +
    + Referenced by: +
    ====================================================================================================================== - WHITESPACE +TrimFunction ====================================================================================================================== + +.. raw:: html + + + + + + TRIM + + ( + + LEADING + + TRAILING + + BOTH + + Expression + , + + FROM + + Expression + ) + + +
    + + +
             ::= 'TRIM' '(' ( 'LEADING' | 'TRAILING' | 'BOTH' )? Expression? ( ( ',' | 'FROM' ) Expression )? ')'
    +
    + Referenced by: +
    + +====================================================================================================================== +WHITESPACE +====================================================================================================================== + + .. raw:: html @@ -8667,20 +8677,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#xA] -
    +
             ::= [ #x9#xD#xA]
    +
    ====================================================================================================================== - K_DATETIMELITERAL +K_DATETIMELITERAL ====================================================================================================================== - + .. raw:: html @@ -8696,7 +8706,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. TIMESTAMPTZ -
    +
             ::= 'DATE'
    @@ -8705,14 +8715,14 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'TIMESTAMPTZ'
    +
    ====================================================================================================================== - K_DATE_LITERAL +K_DATE_LITERAL ====================================================================================================================== - + .. raw:: html @@ -8732,7 +8742,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SECOND -
    +
             ::= 'YEAR'
    @@ -8743,14 +8753,14 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'SECOND'
    +
    ====================================================================================================================== - K_ISOLATION +K_ISOLATION ====================================================================================================================== - + .. raw:: html @@ -8766,7 +8776,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. CS -
    +
             ::= 'UR'
    @@ -8775,47 +8785,52 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'CS'
    +
    ====================================================================================================================== - K_NEXTVAL +K_NEXTVAL ====================================================================================================================== - + .. raw:: html - + NEXTVAL - - NEXT - - - - VALUE - - - - FOR - + + + + FOR + + NEXT + + + + VALUE + + + + FOR + -
    +
    -
             ::= ( 'NEXTVAL' | 'NEXT' ' '+ 'VALUE' ) ' '+ 'FOR'
    +
             ::= 'NEXTVAL' ( ' '+ 'FOR' )?
    +
               | 'NEXT' ' '+ 'VALUE' ' '+ 'FOR'
    Referenced by: -
    +
    ====================================================================================================================== - K_SELECT +K_SELECT ====================================================================================================================== - + .. raw:: html @@ -8827,20 +8842,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. SEL -
    +
    K_SELECT ::= 'SELECT'
               | 'SEL'
    +
    ====================================================================================================================== - K_TIME_KEY_EXPR +K_TIME_KEY_EXPR ====================================================================================================================== - + .. raw:: html @@ -8862,20 +8877,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. () -
    +
             ::= 'CURRENT' ( '_' | ' '+ ) ( 'TIMESTAMP' | 'TIME' | 'DATE' ) '()'?
    +
    ====================================================================================================================== - K_STRING_FUNCTION_NAME +K_STRING_FUNCTION_NAME ====================================================================================================================== - + .. raw:: html @@ -8893,7 +8908,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. OVERLAY -
    +
             ::= 'SUBSTR'
    @@ -8903,14 +8918,14 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | 'OVERLAY'
    +
    ====================================================================================================================== - ST_SEMICOLON +ST_SEMICOLON ====================================================================================================================== - + .. raw:: html @@ -8930,21 +8945,21 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. go -
    +
             ::= ';'
               | #xA ( [/#xA] #xA | 'go' )
    Referenced by: -
    +
    ====================================================================================================================== - OP_GREATERTHANEQUALS +OP_GREATERTHANEQUALS ====================================================================================================================== - + .. raw:: html @@ -8957,20 +8972,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. = -
    +
             ::= '>' WHITESPACE* '='
    Referenced by: -
    +
    ====================================================================================================================== - OP_MINORTHANEQUALS +OP_MINORTHANEQUALS ====================================================================================================================== - + .. raw:: html @@ -8983,20 +8998,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. = -
    +
             ::= '<' WHITESPACE* '='
    Referenced by: -
    +
    ====================================================================================================================== - OP_NOTEQUALSSTANDARD +OP_NOTEQUALSSTANDARD ====================================================================================================================== - + .. raw:: html @@ -9009,20 +9024,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. > -
    +
             ::= '<' WHITESPACE* '>'
    Referenced by: -
    +
    ====================================================================================================================== - OP_NOTEQUALSBANG +OP_NOTEQUALSBANG ====================================================================================================================== - + .. raw:: html @@ -9035,20 +9050,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. = -
    +
             ::= '!' WHITESPACE* '='
    Referenced by: -
    +
    ====================================================================================================================== - OP_CONCAT +OP_CONCAT ====================================================================================================================== - + .. raw:: html @@ -9061,20 +9076,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. | -
    +
             ::= '|' WHITESPACE* '|'
    +
    ====================================================================================================================== - DT_ZONE +DT_ZONE ====================================================================================================================== - + .. raw:: html @@ -9104,19 +9119,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ZONE -
    +
    DT_ZONE  ::= K_DATETIMELITERAL WHITESPACE* ( '(' S_LONG ')' )? WHITESPACE* ( 'WITH' | 'WITHOUT' ) WHITESPACE+ ( 'LOCAL' WHITESPACE+ )? 'TIME' WHITESPACE+ 'ZONE'
    +
    ====================================================================================================================== - S_DOUBLE +S_DOUBLE ====================================================================================================================== - + .. raw:: html @@ -9159,20 +9174,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. S_LONG -
    +
    S_DOUBLE ::= S_LONG? '.' S_LONG ( [eE] [+#x2D]? S_LONG )?
               | S_LONG ( '.' ( [eE] [+#x2D]? S_LONG )? | [eE] [+#x2D]? S_LONG )
    +
    ====================================================================================================================== - S_LONG +S_LONG ====================================================================================================================== - + .. raw:: html @@ -9181,19 +9196,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. DIGIT -
    +
    S_LONG   ::= DIGIT+
    +
    ====================================================================================================================== - DIGIT +DIGIT ====================================================================================================================== - + .. raw:: html @@ -9203,19 +9218,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [0-9] -
    +
    DIGIT    ::= [0-9]
    Referenced by: -
    +
    ====================================================================================================================== - S_HEX +S_HEX ====================================================================================================================== - + .. raw:: html @@ -9231,20 +9246,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. HEX_VALUE -
    +
    S_HEX    ::= "x'" HEX_VALUE+ "'"
               | '0x' HEX_VALUE+
    +
    ====================================================================================================================== - HEX_VALUE +HEX_VALUE ====================================================================================================================== - + .. raw:: html @@ -9256,20 +9271,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [A-F] -
    +
             ::= [0-9A-F]
    Referenced by: -
    +
    ====================================================================================================================== - LINE_COMMENT +LINE_COMMENT ====================================================================================================================== - + .. raw:: html @@ -9283,7 +9298,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [^#xD#xA] -
    +
             ::= ( '--' | '//' ) [^#xD#xA]*
    @@ -9293,10 +9308,10 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ====================================================================================================================== - MULTI_LINE_COMMENT +MULTI_LINE_COMMENT ====================================================================================================================== - + .. raw:: html @@ -9316,7 +9331,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. / -
    +
             ::= '/*' [^*]* '*' ( ( [^*/] [^*]* )? '*' )* '/'
    @@ -9326,10 +9341,10 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. ====================================================================================================================== - S_IDENTIFIER +S_IDENTIFIER ====================================================================================================================== - + .. raw:: html @@ -9340,20 +9355,20 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. PART_LETTER -
    +
             ::= LETTER PART_LETTER*
    +
    ====================================================================================================================== - LETTER +LETTER ====================================================================================================================== - + .. raw:: html @@ -9370,21 +9385,21 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#x23] -
    +
               | Nd
               | [$_#x23]
    Referenced by: -
    +
    ====================================================================================================================== - PART_LETTER +PART_LETTER ====================================================================================================================== - + .. raw:: html @@ -9403,7 +9418,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#x23] -
    +
             ::= UnicodeIdentifierStart
    @@ -9411,14 +9426,14 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | [$_@#x23]
    Referenced by: -
    +
    ====================================================================================================================== - UnicodeIdentifierStart +UnicodeIdentifierStart ====================================================================================================================== - + .. raw:: html @@ -9441,7 +9456,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. CJK -
    +
             ::= #xB7
    @@ -9454,14 +9469,14 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | CJK
    Referenced by: -
    +
    ====================================================================================================================== - Ll +Ll ====================================================================================================================== - + .. raw:: html @@ -10703,19 +10718,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#xFF41-#xFF5A] -
    +
    Ll       ::= [a-z#xB5#xDF-#xF6#xF8-#xFF#x101#x103#x105#x107#x109#x10B#x10D#x10F#x111#x113#x115#x117#x119#x11B#x11D#x11F#x121#x123#x125#x127#x129#x12B#x12D#x12F#x131#x133#x135#x137-#x138#x13A#x13C#x13E#x140#x142#x144#x146#x148-#x149#x14B#x14D#x14F#x151#x153#x155#x157#x159#x15B#x15D#x15F#x161#x163#x165#x167#x169#x16B#x16D#x16F#x171#x173#x175#x177#x17A#x17C#x17E-#x180#x183#x185#x188#x18C-#x18D#x192#x195#x199-#x19B#x19E#x1A1#x1A3#x1A5#x1A8#x1AA-#x1AB#x1AD#x1B0#x1B4#x1B6#x1B9-#x1BA#x1BD-#x1BF#x1C6#x1C9#x1CC#x1CE#x1D0#x1D2#x1D4#x1D6#x1D8#x1DA#x1DC-#x1DD#x1DF#x1E1#x1E3#x1E5#x1E7#x1E9#x1EB#x1ED#x1EF-#x1F0#x1F3#x1F5#x1F9#x1FB#x1FD#x1FF#x201#x203#x205#x207#x209#x20B#x20D#x20F#x211#x213#x215#x217#x219#x21B#x21D#x21F#x221#x223#x225#x227#x229#x22B#x22D#x22F#x231#x233-#x239#x23C#x23F-#x240#x242#x247#x249#x24B#x24D#x24F-#x293#x295-#x2AF#x371#x373#x377#x37B-#x37D#x390#x3AC-#x3CE#x3D0-#x3D1#x3D5-#x3D7#x3D9#x3DB#x3DD#x3DF#x3E1#x3E3#x3E5#x3E7#x3E9#x3EB#x3ED#x3EF-#x3F3#x3F5#x3F8#x3FB-#x3FC#x430-#x45F#x461#x463#x465#x467#x469#x46B#x46D#x46F#x471#x473#x475#x477#x479#x47B#x47D#x47F#x481#x48B#x48D#x48F#x491#x493#x495#x497#x499#x49B#x49D#x49F#x4A1#x4A3#x4A5#x4A7#x4A9#x4AB#x4AD#x4AF#x4B1#x4B3#x4B5#x4B7#x4B9#x4BB#x4BD#x4BF#x4C2#x4C4#x4C6#x4C8#x4CA#x4CC#x4CE-#x4CF#x4D1#x4D3#x4D5#x4D7#x4D9#x4DB#x4DD#x4DF#x4E1#x4E3#x4E5#x4E7#x4E9#x4EB#x4ED#x4EF#x4F1#x4F3#x4F5#x4F7#x4F9#x4FB#x4FD#x4FF#x501#x503#x505#x507#x509#x50B#x50D#x50F#x511#x513#x515#x517#x519#x51B#x51D#x51F#x521#x523#x525#x527#x529#x52B#x52D#x52F#x560-#x588#x10D0-#x10FA#x10FD-#x10FF#x13F8-#x13FD#x1C80-#x1C88#x1D00-#x1D2B#x1D6B-#x1D77#x1D79-#x1D9A#x1E01#x1E03#x1E05#x1E07#x1E09#x1E0B#x1E0D#x1E0F#x1E11#x1E13#x1E15#x1E17#x1E19#x1E1B#x1E1D#x1E1F#x1E21#x1E23#x1E25#x1E27#x1E29#x1E2B#x1E2D#x1E2F#x1E31#x1E33#x1E35#x1E37#x1E39#x1E3B#x1E3D#x1E3F#x1E41#x1E43#x1E45#x1E47#x1E49#x1E4B#x1E4D#x1E4F#x1E51#x1E53#x1E55#x1E57#x1E59#x1E5B#x1E5D#x1E5F#x1E61#x1E63#x1E65#x1E67#x1E69#x1E6B#x1E6D#x1E6F#x1E71#x1E73#x1E75#x1E77#x1E79#x1E7B#x1E7D#x1E7F#x1E81#x1E83#x1E85#x1E87#x1E89#x1E8B#x1E8D#x1E8F#x1E91#x1E93#x1E95-#x1E9D#x1E9F#x1EA1#x1EA3#x1EA5#x1EA7#x1EA9#x1EAB#x1EAD#x1EAF#x1EB1#x1EB3#x1EB5#x1EB7#x1EB9#x1EBB#x1EBD#x1EBF#x1EC1#x1EC3#x1EC5#x1EC7#x1EC9#x1ECB#x1ECD#x1ECF#x1ED1#x1ED3#x1ED5#x1ED7#x1ED9#x1EDB#x1EDD#x1EDF#x1EE1#x1EE3#x1EE5#x1EE7#x1EE9#x1EEB#x1EED#x1EEF#x1EF1#x1EF3#x1EF5#x1EF7#x1EF9#x1EFB#x1EFD#x1EFF-#x1F07#x1F10-#x1F15#x1F20-#x1F27#x1F30-#x1F37#x1F40-#x1F45#x1F50-#x1F57#x1F60-#x1F67#x1F70-#x1F7D#x1F80-#x1F87#x1F90-#x1F97#x1FA0-#x1FA7#x1FB0-#x1FB4#x1FB6-#x1FB7#x1FBE#x1FC2-#x1FC4#x1FC6-#x1FC7#x1FD0-#x1FD3#x1FD6-#x1FD7#x1FE0-#x1FE7#x1FF2-#x1FF4#x1FF6-#x1FF7#x210A#x210E-#x210F#x2113#x212F#x2134#x2139#x213C-#x213D#x2146-#x2149#x214E#x2184#x2C30-#x2C5F#x2C61#x2C65-#x2C66#x2C68#x2C6A#x2C6C#x2C71#x2C73-#x2C74#x2C76-#x2C7B#x2C81#x2C83#x2C85#x2C87#x2C89#x2C8B#x2C8D#x2C8F#x2C91#x2C93#x2C95#x2C97#x2C99#x2C9B#x2C9D#x2C9F#x2CA1#x2CA3#x2CA5#x2CA7#x2CA9#x2CAB#x2CAD#x2CAF#x2CB1#x2CB3#x2CB5#x2CB7#x2CB9#x2CBB#x2CBD#x2CBF#x2CC1#x2CC3#x2CC5#x2CC7#x2CC9#x2CCB#x2CCD#x2CCF#x2CD1#x2CD3#x2CD5#x2CD7#x2CD9#x2CDB#x2CDD#x2CDF#x2CE1#x2CE3-#x2CE4#x2CEC#x2CEE#x2CF3#x2D00-#x2D25#x2D27#x2D2D#xA641#xA643#xA645#xA647#xA649#xA64B#xA64D#xA64F#xA651#xA653#xA655#xA657#xA659#xA65B#xA65D#xA65F#xA661#xA663#xA665#xA667#xA669#xA66B#xA66D#xA681#xA683#xA685#xA687#xA689#xA68B#xA68D#xA68F#xA691#xA693#xA695#xA697#xA699#xA69B#xA723#xA725#xA727#xA729#xA72B#xA72D#xA72F-#xA731#xA733#xA735#xA737#xA739#xA73B#xA73D#xA73F#xA741#xA743#xA745#xA747#xA749#xA74B#xA74D#xA74F#xA751#xA753#xA755#xA757#xA759#xA75B#xA75D#xA75F#xA761#xA763#xA765#xA767#xA769#xA76B#xA76D#xA76F#xA771-#xA778#xA77A#xA77C#xA77F#xA781#xA783#xA785#xA787#xA78C#xA78E#xA791#xA793-#xA795#xA797#xA799#xA79B#xA79D#xA79F#xA7A1#xA7A3#xA7A5#xA7A7#xA7A9#xA7AF#xA7B5#xA7B7#xA7B9#xA7BB#xA7BD#xA7BF#xA7C1#xA7C3#xA7C8#xA7CA#xA7D1#xA7D3#xA7D5#xA7D7#xA7D9#xA7F6#xA7FA#xAB30-#xAB5A#xAB60-#xAB68#xAB70-#xABBF#xFB00-#xFB06#xFB13-#xFB17#xFF41-#xFF5A]
    Referenced by: -
    +
    ====================================================================================================================== - Lm +Lm ====================================================================================================================== - + .. raw:: html @@ -10837,19 +10852,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#xFF9E-#xFF9F] -
    +
    Lm       ::= [#x2B0-#x2C1#x2C6-#x2D1#x2E0-#x2E4#x2EC#x2EE#x374#x37A#x559#x640#x6E5-#x6E6#x7F4-#x7F5#x7FA#x81A#x824#x828#x8C9#x971#xE46#xEC6#x10FC#x17D7#x1843#x1AA7#x1C78-#x1C7D#x1D2C-#x1D6A#x1D78#x1D9B-#x1DBF#x2071#x207F#x2090-#x209C#x2C7C-#x2C7D#x2D6F#x2E2F#x3005#x3031-#x3035#x303B#x309D-#x309E#x30FC-#x30FE#xA015#xA4F8-#xA4FD#xA60C#xA67F#xA69C-#xA69D#xA717-#xA71F#xA770#xA788#xA7F2-#xA7F4#xA7F8-#xA7F9#xA9CF#xA9E6#xAA70#xAADD#xAAF3-#xAAF4#xAB5C-#xAB5F#xAB69#xFF70#xFF9E-#xFF9F]
    Referenced by: -
    +
    ====================================================================================================================== - Lo +Lo ====================================================================================================================== - + .. raw:: html @@ -11437,19 +11452,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#xFFDA-#xFFDC] -
    +
    Lo       ::= [#xAA#xBA#x1BB#x1C0-#x1C3#x294#x5D0-#x5EA#x5EF-#x5F2#x620-#x63F#x641-#x64A#x66E-#x66F#x671-#x6D3#x6D5#x6EE-#x6EF#x6FA-#x6FC#x6FF#x710#x712-#x72F#x74D-#x7A5#x7B1#x7CA-#x7EA#x800-#x815#x840-#x858#x860-#x86A#x870-#x887#x889-#x88E#x8A0-#x8C8#x904-#x939#x93D#x950#x958-#x961#x972-#x980#x985-#x98C#x98F-#x990#x993-#x9A8#x9AA-#x9B0#x9B2#x9B6-#x9B9#x9BD#x9CE#x9DC-#x9DD#x9DF-#x9E1#x9F0-#x9F1#x9FC#xA05-#xA0A#xA0F-#xA10#xA13-#xA28#xA2A-#xA30#xA32-#xA33#xA35-#xA36#xA38-#xA39#xA59-#xA5C#xA5E#xA72-#xA74#xA85-#xA8D#xA8F-#xA91#xA93-#xAA8#xAAA-#xAB0#xAB2-#xAB3#xAB5-#xAB9#xABD#xAD0#xAE0-#xAE1#xAF9#xB05-#xB0C#xB0F-#xB10#xB13-#xB28#xB2A-#xB30#xB32-#xB33#xB35-#xB39#xB3D#xB5C-#xB5D#xB5F-#xB61#xB71#xB83#xB85-#xB8A#xB8E-#xB90#xB92-#xB95#xB99-#xB9A#xB9C#xB9E-#xB9F#xBA3-#xBA4#xBA8-#xBAA#xBAE-#xBB9#xBD0#xC05-#xC0C#xC0E-#xC10#xC12-#xC28#xC2A-#xC39#xC3D#xC58-#xC5A#xC5D#xC60-#xC61#xC80#xC85-#xC8C#xC8E-#xC90#xC92-#xCA8#xCAA-#xCB3#xCB5-#xCB9#xCBD#xCDD-#xCDE#xCE0-#xCE1#xCF1-#xCF2#xD04-#xD0C#xD0E-#xD10#xD12-#xD3A#xD3D#xD4E#xD54-#xD56#xD5F-#xD61#xD7A-#xD7F#xD85-#xD96#xD9A-#xDB1#xDB3-#xDBB#xDBD#xDC0-#xDC6#xE01-#xE30#xE32-#xE33#xE40-#xE45#xE81-#xE82#xE84#xE86-#xE8A#xE8C-#xEA3#xEA5#xEA7-#xEB0#xEB2-#xEB3#xEBD#xEC0-#xEC4#xEDC-#xEDF#xF00#xF40-#xF47#xF49-#xF6C#xF88-#xF8C#x1000-#x102A#x103F#x1050-#x1055#x105A-#x105D#x1061#x1065-#x1066#x106E-#x1070#x1075-#x1081#x108E#x1100-#x1248#x124A-#x124D#x1250-#x1256#x1258#x125A-#x125D#x1260-#x1288#x128A-#x128D#x1290-#x12B0#x12B2-#x12B5#x12B8-#x12BE#x12C0#x12C2-#x12C5#x12C8-#x12D6#x12D8-#x1310#x1312-#x1315#x1318-#x135A#x1380-#x138F#x1401-#x166C#x166F-#x167F#x1681-#x169A#x16A0-#x16EA#x16F1-#x16F8#x1700-#x1711#x171F-#x1731#x1740-#x1751#x1760-#x176C#x176E-#x1770#x1780-#x17B3#x17DC#x1820-#x1842#x1844-#x1878#x1880-#x1884#x1887-#x18A8#x18AA#x18B0-#x18F5#x1900-#x191E#x1950-#x196D#x1970-#x1974#x1980-#x19AB#x19B0-#x19C9#x1A00-#x1A16#x1A20-#x1A54#x1B05-#x1B33#x1B45-#x1B4C#x1B83-#x1BA0#x1BAE-#x1BAF#x1BBA-#x1BE5#x1C00-#x1C23#x1C4D-#x1C4F#x1C5A-#x1C77#x1CE9-#x1CEC#x1CEE-#x1CF3#x1CF5-#x1CF6#x1CFA#x2135-#x2138#x2D30-#x2D67#x2D80-#x2D96#x2DA0-#x2DA6#x2DA8-#x2DAE#x2DB0-#x2DB6#x2DB8-#x2DBE#x2DC0-#x2DC6#x2DC8-#x2DCE#x2DD0-#x2DD6#x2DD8-#x2DDE#x3006#x303C#x3041-#x3096#x309F#x30A1-#x30FA#x30FF#x3105-#x312F#x3131-#x318E#x31A0-#x31BF#x31F0-#x31FF#x4DBF#x9FFF-#xA014#xA016-#xA48C#xA4D0-#xA4F7#xA500-#xA60B#xA610-#xA61F#xA62A-#xA62B#xA66E#xA6A0-#xA6E5#xA78F#xA7F7#xA7FB-#xA801#xA803-#xA805#xA807-#xA80A#xA80C-#xA822#xA840-#xA873#xA882-#xA8B3#xA8F2-#xA8F7#xA8FB#xA8FD-#xA8FE#xA90A-#xA925#xA930-#xA946#xA960-#xA97C#xA984-#xA9B2#xA9E0-#xA9E4#xA9E7-#xA9EF#xA9FA-#xA9FE#xAA00-#xAA28#xAA40-#xAA42#xAA44-#xAA4B#xAA60-#xAA6F#xAA71-#xAA76#xAA7A#xAA7E-#xAAAF#xAAB1#xAAB5-#xAAB6#xAAB9-#xAABD#xAAC0#xAAC2#xAADB-#xAADC#xAAE0-#xAAEA#xAAF2#xAB01-#xAB06#xAB09-#xAB0E#xAB11-#xAB16#xAB20-#xAB26#xAB28-#xAB2E#xABC0-#xABE2#xD7A3#xD7B0-#xD7C6#xD7CB-#xD7FB#xF900-#xFA6D#xFA70-#xFAD9#xFB1D#xFB1F-#xFB28#xFB2A-#xFB36#xFB38-#xFB3C#xFB3E#xFB40-#xFB41#xFB43-#xFB44#xFB46-#xFBB1#xFBD3-#xFD3D#xFD50-#xFD8F#xFD92-#xFDC7#xFDF0-#xFDFB#xFE70-#xFE74#xFE76-#xFEFC#xFF66-#xFF6F#xFF71-#xFF9D#xFFA0-#xFFBE#xFFC2-#xFFC7#xFFCA-#xFFCF#xFFD2-#xFFD7#xFFDA-#xFFDC]
    Referenced by: -
    +
    ====================================================================================================================== - Lt +Lt ====================================================================================================================== - + .. raw:: html @@ -11477,19 +11492,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#x1FFC] -
    +
    Lt       ::= [#x1C5#x1C8#x1CB#x1F2#x1F88-#x1F8F#x1F98-#x1F9F#x1FA8-#x1FAF#x1FBC#x1FCC#x1FFC]
    Referenced by: -
    +
    ====================================================================================================================== - Lu +Lu ====================================================================================================================== - + .. raw:: html @@ -12707,19 +12722,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#xFF21-#xFF3A] -
    +
    Lu       ::= [A-Z#xC0-#xD6#xD8-#xDE#x100#x102#x104#x106#x108#x10A#x10C#x10E#x110#x112#x114#x116#x118#x11A#x11C#x11E#x120#x122#x124#x126#x128#x12A#x12C#x12E#x130#x132#x134#x136#x139#x13B#x13D#x13F#x141#x143#x145#x147#x14A#x14C#x14E#x150#x152#x154#x156#x158#x15A#x15C#x15E#x160#x162#x164#x166#x168#x16A#x16C#x16E#x170#x172#x174#x176#x178-#x179#x17B#x17D#x181-#x182#x184#x186-#x187#x189-#x18B#x18E-#x191#x193-#x194#x196-#x198#x19C-#x19D#x19F-#x1A0#x1A2#x1A4#x1A6-#x1A7#x1A9#x1AC#x1AE-#x1AF#x1B1-#x1B3#x1B5#x1B7-#x1B8#x1BC#x1C4#x1C7#x1CA#x1CD#x1CF#x1D1#x1D3#x1D5#x1D7#x1D9#x1DB#x1DE#x1E0#x1E2#x1E4#x1E6#x1E8#x1EA#x1EC#x1EE#x1F1#x1F4#x1F6-#x1F8#x1FA#x1FC#x1FE#x200#x202#x204#x206#x208#x20A#x20C#x20E#x210#x212#x214#x216#x218#x21A#x21C#x21E#x220#x222#x224#x226#x228#x22A#x22C#x22E#x230#x232#x23A-#x23B#x23D-#x23E#x241#x243-#x246#x248#x24A#x24C#x24E#x370#x372#x376#x37F#x386#x388-#x38A#x38C#x38E-#x38F#x391-#x3A1#x3A3-#x3AB#x3CF#x3D2-#x3D4#x3D8#x3DA#x3DC#x3DE#x3E0#x3E2#x3E4#x3E6#x3E8#x3EA#x3EC#x3EE#x3F4#x3F7#x3F9-#x3FA#x3FD-#x42F#x460#x462#x464#x466#x468#x46A#x46C#x46E#x470#x472#x474#x476#x478#x47A#x47C#x47E#x480#x48A#x48C#x48E#x490#x492#x494#x496#x498#x49A#x49C#x49E#x4A0#x4A2#x4A4#x4A6#x4A8#x4AA#x4AC#x4AE#x4B0#x4B2#x4B4#x4B6#x4B8#x4BA#x4BC#x4BE#x4C0-#x4C1#x4C3#x4C5#x4C7#x4C9#x4CB#x4CD#x4D0#x4D2#x4D4#x4D6#x4D8#x4DA#x4DC#x4DE#x4E0#x4E2#x4E4#x4E6#x4E8#x4EA#x4EC#x4EE#x4F0#x4F2#x4F4#x4F6#x4F8#x4FA#x4FC#x4FE#x500#x502#x504#x506#x508#x50A#x50C#x50E#x510#x512#x514#x516#x518#x51A#x51C#x51E#x520#x522#x524#x526#x528#x52A#x52C#x52E#x531-#x556#x10A0-#x10C5#x10C7#x10CD#x13A0-#x13F5#x1C90-#x1CBA#x1CBD-#x1CBF#x1E00#x1E02#x1E04#x1E06#x1E08#x1E0A#x1E0C#x1E0E#x1E10#x1E12#x1E14#x1E16#x1E18#x1E1A#x1E1C#x1E1E#x1E20#x1E22#x1E24#x1E26#x1E28#x1E2A#x1E2C#x1E2E#x1E30#x1E32#x1E34#x1E36#x1E38#x1E3A#x1E3C#x1E3E#x1E40#x1E42#x1E44#x1E46#x1E48#x1E4A#x1E4C#x1E4E#x1E50#x1E52#x1E54#x1E56#x1E58#x1E5A#x1E5C#x1E5E#x1E60#x1E62#x1E64#x1E66#x1E68#x1E6A#x1E6C#x1E6E#x1E70#x1E72#x1E74#x1E76#x1E78#x1E7A#x1E7C#x1E7E#x1E80#x1E82#x1E84#x1E86#x1E88#x1E8A#x1E8C#x1E8E#x1E90#x1E92#x1E94#x1E9E#x1EA0#x1EA2#x1EA4#x1EA6#x1EA8#x1EAA#x1EAC#x1EAE#x1EB0#x1EB2#x1EB4#x1EB6#x1EB8#x1EBA#x1EBC#x1EBE#x1EC0#x1EC2#x1EC4#x1EC6#x1EC8#x1ECA#x1ECC#x1ECE#x1ED0#x1ED2#x1ED4#x1ED6#x1ED8#x1EDA#x1EDC#x1EDE#x1EE0#x1EE2#x1EE4#x1EE6#x1EE8#x1EEA#x1EEC#x1EEE#x1EF0#x1EF2#x1EF4#x1EF6#x1EF8#x1EFA#x1EFC#x1EFE#x1F08-#x1F0F#x1F18-#x1F1D#x1F28-#x1F2F#x1F38-#x1F3F#x1F48-#x1F4D#x1F59#x1F5B#x1F5D#x1F5F#x1F68-#x1F6F#x1FB8-#x1FBB#x1FC8-#x1FCB#x1FD8-#x1FDB#x1FE8-#x1FEC#x1FF8-#x1FFB#x2102#x2107#x210B-#x210D#x2110-#x2112#x2115#x2119-#x211D#x2124#x2126#x2128#x212A-#x212D#x2130-#x2133#x213E-#x213F#x2145#x2183#x2C00-#x2C2F#x2C60#x2C62-#x2C64#x2C67#x2C69#x2C6B#x2C6D-#x2C70#x2C72#x2C75#x2C7E-#x2C80#x2C82#x2C84#x2C86#x2C88#x2C8A#x2C8C#x2C8E#x2C90#x2C92#x2C94#x2C96#x2C98#x2C9A#x2C9C#x2C9E#x2CA0#x2CA2#x2CA4#x2CA6#x2CA8#x2CAA#x2CAC#x2CAE#x2CB0#x2CB2#x2CB4#x2CB6#x2CB8#x2CBA#x2CBC#x2CBE#x2CC0#x2CC2#x2CC4#x2CC6#x2CC8#x2CCA#x2CCC#x2CCE#x2CD0#x2CD2#x2CD4#x2CD6#x2CD8#x2CDA#x2CDC#x2CDE#x2CE0#x2CE2#x2CEB#x2CED#x2CF2#xA640#xA642#xA644#xA646#xA648#xA64A#xA64C#xA64E#xA650#xA652#xA654#xA656#xA658#xA65A#xA65C#xA65E#xA660#xA662#xA664#xA666#xA668#xA66A#xA66C#xA680#xA682#xA684#xA686#xA688#xA68A#xA68C#xA68E#xA690#xA692#xA694#xA696#xA698#xA69A#xA722#xA724#xA726#xA728#xA72A#xA72C#xA72E#xA732#xA734#xA736#xA738#xA73A#xA73C#xA73E#xA740#xA742#xA744#xA746#xA748#xA74A#xA74C#xA74E#xA750#xA752#xA754#xA756#xA758#xA75A#xA75C#xA75E#xA760#xA762#xA764#xA766#xA768#xA76A#xA76C#xA76E#xA779#xA77B#xA77D-#xA77E#xA780#xA782#xA784#xA786#xA78B#xA78D#xA790#xA792#xA796#xA798#xA79A#xA79C#xA79E#xA7A0#xA7A2#xA7A4#xA7A6#xA7A8#xA7AA-#xA7AE#xA7B0-#xA7B4#xA7B6#xA7B8#xA7BA#xA7BC#xA7BE#xA7C0#xA7C2#xA7C4-#xA7C7#xA7C9#xA7D0#xA7D6#xA7D8#xA7F5#xFF21-#xFF3A]
    Referenced by: -
    +
    ====================================================================================================================== - Nl +Nl ====================================================================================================================== - + .. raw:: html @@ -12741,19 +12756,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#xA6E6-#xA6EF] -
    +
    Nl       ::= [#x16EE-#x16F0#x2160-#x2182#x2185-#x2188#x3007#x3021-#x3029#x3038-#x303A#xA6E6-#xA6EF]
    Referenced by: -
    +
    ====================================================================================================================== - UnicodeIdentifierExtend +UnicodeIdentifierExtend ====================================================================================================================== - + .. raw:: html @@ -12772,7 +12787,7 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. CJK -
    +
             ::= Mn
    @@ -12783,14 +12798,14 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|.
               | CJK
    Referenced by: -
    +
    ====================================================================================================================== - Cf +Cf ====================================================================================================================== - + .. raw:: html @@ -12826,19 +12841,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#xFFF9-#xFFFB] -
    +
    Cf       ::= [#xAD#x600-#x605#x61C#x6DD#x70F#x890-#x891#x8E2#x180E#x200B-#x200F#x202A-#x202E#x2060-#x2064#x2066-#x206F#xFEFF#xFFF9-#xFFFB]
    Referenced by: -
    +
    ====================================================================================================================== - Mc +Mc ====================================================================================================================== - + .. raw:: html @@ -13070,19 +13085,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#xABEC] -
    +
    Mc       ::= [#x903#x93B#x93E-#x940#x949-#x94C#x94E-#x94F#x982-#x983#x9BE-#x9C0#x9C7-#x9C8#x9CB-#x9CC#x9D7#xA03#xA3E-#xA40#xA83#xABE-#xAC0#xAC9#xACB-#xACC#xB02-#xB03#xB3E#xB40#xB47-#xB48#xB4B-#xB4C#xB57#xBBE-#xBBF#xBC1-#xBC2#xBC6-#xBC8#xBCA-#xBCC#xBD7#xC01-#xC03#xC41-#xC44#xC82-#xC83#xCBE#xCC0-#xCC4#xCC7-#xCC8#xCCA-#xCCB#xCD5-#xCD6#xCF3#xD02-#xD03#xD3E-#xD40#xD46-#xD48#xD4A-#xD4C#xD57#xD82-#xD83#xDCF-#xDD1#xDD8-#xDDF#xDF2-#xDF3#xF3E-#xF3F#xF7F#x102B-#x102C#x1031#x1038#x103B-#x103C#x1056-#x1057#x1062-#x1064#x1067-#x106D#x1083-#x1084#x1087-#x108C#x108F#x109A-#x109C#x1715#x1734#x17B6#x17BE-#x17C5#x17C7-#x17C8#x1923-#x1926#x1929-#x192B#x1930-#x1931#x1933-#x1938#x1A19-#x1A1A#x1A55#x1A57#x1A61#x1A63-#x1A64#x1A6D-#x1A72#x1B04#x1B35#x1B3B#x1B3D-#x1B41#x1B43-#x1B44#x1B82#x1BA1#x1BA6-#x1BA7#x1BAA#x1BE7#x1BEA-#x1BEC#x1BEE#x1BF2-#x1BF3#x1C24-#x1C2B#x1C34-#x1C35#x1CE1#x1CF7#x302E-#x302F#xA823-#xA824#xA827#xA880-#xA881#xA8B4-#xA8C3#xA952-#xA953#xA983#xA9B4-#xA9B5#xA9BA-#xA9BB#xA9BE-#xA9C0#xAA2F-#xAA30#xAA33-#xAA34#xAA4D#xAA7B#xAA7D#xAAEB#xAAEE-#xAAEF#xAAF5#xABE3-#xABE4#xABE6-#xABE7#xABE9-#xABEA#xABEC]
    Referenced by: -
    +
    ====================================================================================================================== - Mn +Mn ====================================================================================================================== - + .. raw:: html @@ -13514,19 +13529,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#xFE20-#xFE2F] -
    +
    Mn       ::= [#x300-#x36F#x483-#x487#x591-#x5BD#x5BF#x5C1-#x5C2#x5C4-#x5C5#x5C7#x610-#x61A#x64B-#x65F#x670#x6D6-#x6DC#x6DF-#x6E4#x6E7-#x6E8#x6EA-#x6ED#x711#x730-#x74A#x7A6-#x7B0#x7EB-#x7F3#x7FD#x816-#x819#x81B-#x823#x825-#x827#x829-#x82D#x859-#x85B#x898-#x89F#x8CA-#x8E1#x8E3-#x902#x93A#x93C#x941-#x948#x94D#x951-#x957#x962-#x963#x981#x9BC#x9C1-#x9C4#x9CD#x9E2-#x9E3#x9FE#xA01-#xA02#xA3C#xA41-#xA42#xA47-#xA48#xA4B-#xA4D#xA51#xA70-#xA71#xA75#xA81-#xA82#xABC#xAC1-#xAC5#xAC7-#xAC8#xACD#xAE2-#xAE3#xAFA-#xAFF#xB01#xB3C#xB3F#xB41-#xB44#xB4D#xB55-#xB56#xB62-#xB63#xB82#xBC0#xBCD#xC00#xC04#xC3C#xC3E-#xC40#xC46-#xC48#xC4A-#xC4D#xC55-#xC56#xC62-#xC63#xC81#xCBC#xCBF#xCC6#xCCC-#xCCD#xCE2-#xCE3#xD00-#xD01#xD3B-#xD3C#xD41-#xD44#xD4D#xD62-#xD63#xD81#xDCA#xDD2-#xDD4#xDD6#xE31#xE34-#xE3A#xE47-#xE4E#xEB1#xEB4-#xEBC#xEC8-#xECE#xF18-#xF19#xF35#xF37#xF39#xF71-#xF7E#xF80-#xF84#xF86-#xF87#xF8D-#xF97#xF99-#xFBC#xFC6#x102D-#x1030#x1032-#x1037#x1039-#x103A#x103D-#x103E#x1058-#x1059#x105E-#x1060#x1071-#x1074#x1082#x1085-#x1086#x108D#x109D#x135D-#x135F#x1712-#x1714#x1732-#x1733#x1752-#x1753#x1772-#x1773#x17B4-#x17B5#x17B7-#x17BD#x17C6#x17C9-#x17D3#x17DD#x180B-#x180D#x180F#x1885-#x1886#x18A9#x1920-#x1922#x1927-#x1928#x1932#x1939-#x193B#x1A17-#x1A18#x1A1B#x1A56#x1A58-#x1A5E#x1A60#x1A62#x1A65-#x1A6C#x1A73-#x1A7C#x1A7F#x1AB0-#x1ABD#x1ABF-#x1ACE#x1B00-#x1B03#x1B34#x1B36-#x1B3A#x1B3C#x1B42#x1B6B-#x1B73#x1B80-#x1B81#x1BA2-#x1BA5#x1BA8-#x1BA9#x1BAB-#x1BAD#x1BE6#x1BE8-#x1BE9#x1BED#x1BEF-#x1BF1#x1C2C-#x1C33#x1C36-#x1C37#x1CD0-#x1CD2#x1CD4-#x1CE0#x1CE2-#x1CE8#x1CED#x1CF4#x1CF8-#x1CF9#x1DC0-#x1DFF#x20D0-#x20DC#x20E1#x20E5-#x20F0#x2CEF-#x2CF1#x2D7F#x2DE0-#x2DFF#x302A-#x302D#x3099-#x309A#xA66F#xA674-#xA67D#xA69E-#xA69F#xA6F0-#xA6F1#xA802#xA806#xA80B#xA825-#xA826#xA82C#xA8C4-#xA8C5#xA8E0-#xA8F1#xA8FF#xA926-#xA92D#xA947-#xA951#xA980-#xA982#xA9B3#xA9B6-#xA9B9#xA9BC-#xA9BD#xA9E5#xAA29-#xAA2E#xAA31-#xAA32#xAA35-#xAA36#xAA43#xAA4C#xAA7C#xAAB0#xAAB2-#xAAB4#xAAB7-#xAAB8#xAABE-#xAABF#xAAC1#xAAEC-#xAAED#xAAF6#xABE5#xABE8#xABED#xFB1E#xFE00-#xFE0F#xFE20-#xFE2F]
    Referenced by: -
    +
    ====================================================================================================================== - Nd +Nd ====================================================================================================================== - + .. raw:: html @@ -13608,19 +13623,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#xFF10-#xFF19] -
    +
    Nd       ::= [0-9#x660-#x669#x6F0-#x6F9#x7C0-#x7C9#x966-#x96F#x9E6-#x9EF#xA66-#xA6F#xAE6-#xAEF#xB66-#xB6F#xBE6-#xBEF#xC66-#xC6F#xCE6-#xCEF#xD66-#xD6F#xDE6-#xDEF#xE50-#xE59#xED0-#xED9#xF20-#xF29#x1040-#x1049#x1090-#x1099#x17E0-#x17E9#x1810-#x1819#x1946-#x194F#x19D0-#x19D9#x1A80-#x1A89#x1A90-#x1A99#x1B50-#x1B59#x1BB0-#x1BB9#x1C40-#x1C49#x1C50-#x1C59#xA620-#xA629#xA8D0-#xA8D9#xA900-#xA909#xA9D0-#xA9D9#xA9F0-#xA9F9#xAA50-#xAA59#xABF0-#xABF9#xFF10-#xFF19]
    +
    ====================================================================================================================== - Pc +Pc ====================================================================================================================== - + .. raw:: html @@ -13638,19 +13653,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#xFF3F] -
    +
    Pc       ::= [#x203F-#x2040#x2054#xFE33-#xFE34#xFE4D-#xFE4F#xFF3F]
    Referenced by: -
    +
    ====================================================================================================================== - CJK +CJK ====================================================================================================================== - + .. raw:: html @@ -13662,19 +13677,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. [#x4E00-#x9FFF] -
    +
    CJK      ::= [#xAC00-#xD7A3#x4E00-#x9FFF]
    +
    ====================================================================================================================== - ESC +ESC ====================================================================================================================== - + .. raw:: html @@ -13698,19 +13713,19 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. " -
    +
    ESC      ::= '\' [ntbrf\"]
    Referenced by: -
    +
    ====================================================================================================================== - S_CHAR_LITERAL +S_CHAR_LITERAL ====================================================================================================================== - + .. raw:: html @@ -13769,68 +13784,70 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. '' -
    +
             ::= ( [UENRB] | 'RB' | '_utf8' )? ( "'" ( ( ESC | "\'" | [^'\] )* | ( "''" | [^'] )+ ) "'" | "q'{" .* "}'" | "q'(" .* ")'" | "q'[" .* "]'" | "q''" .* "''" )
    +
    ====================================================================================================================== - S_QUOTED_IDENTIFIER +S_QUOTED_IDENTIFIER ====================================================================================================================== - + .. raw:: html - + " - - [^"#xA#xD] - - " - - $$ - - [^"#xA#xD] - - $$ - - ` - - [^`#xA#xD] - - ` - - [ - - [^#x5D#xA#xD] - - ] - - -
    + + "" + + [^"#xA#xD] + + " + + $$ + + [^$] + + $$ + + ` + + [^`#xA#xD] + + ` + + [ + + [^#x5D#xA#xD] + + ] + + +
    -
             ::= '"' [^"#xA#xD]* '"'
    -
               | '$$' [^"#xA#xD]* '$$'
    +
             ::= '"' ( '""' | [^"#xA#xD] )* '"'
    +
               | '$$' [^$]* '$$'
               | '`' [^`#xA#xD]+ '`'
               | '[' [^#x5D#xA#xD]* ']'
    +
    ====================================================================================================================== - EOF +EOF ====================================================================================================================== - + .. raw:: html @@ -13840,11 +13857,11 @@ The EBNF and Railroad Diagrams for JSQLParser-|JSQLPARSER_VERSION|. $ -
    +
    EOF      ::= $
    Referenced by: -
    +
    \ No newline at end of file diff --git a/src/site/sphinx/usage.rst b/src/site/sphinx/usage.rst index a4d7cbee7..47623b174 100644 --- a/src/site/sphinx/usage.rst +++ b/src/site/sphinx/usage.rst @@ -20,90 +20,85 @@ Compile from Source Code You will need to have ``JDK 8`` or ``JDK 11`` installed. -.. tabs:: +.. tab:: Maven - .. tab:: Maven + .. code-block:: shell - .. code-block:: shell + git clone https://github.com/JSQLParser/JSqlParser.git + cd jsqlformatter + mvn install - git clone https://github.com/JSQLParser/JSqlParser.git - cd jsqlformatter - mvn install +.. tab:: Gradle - .. tab:: Gradle + .. code-block:: shell - .. code-block:: shell - - git clone https://github.com/JSQLParser/JSqlParser.git - cd jsqlformatter - gradle build + git clone https://github.com/JSQLParser/JSqlParser.git + cd jsqlformatter + gradle publishToMavenLocal Build Dependencies ============================== -.. tabs:: +.. tab:: Maven Release + .. code-block:: xml + :substitutions: - .. tab:: Maven Release + + com.github.jsqlparser + jsqlparser + |JSQLPARSER_VERSION| + - .. code-block:: xml - :substitutions: +.. tab:: Maven Snapshot - - com.github.jsqlparser - jsqlparser - |JSQLPARSER_VERSION| - + .. code-block:: xml + :substitutions: - .. tab:: Maven Snapshot + + + jsqlparser-snapshots + + true + + https://oss.sonatype.org/content/groups/public/ + + + + com.github.jsqlparser + jsqlparser + |JSQLPARSER_SNAPSHOT_VERSION| + - .. code-block:: xml - :substitutions: - - - - jsqlparser-snapshots - - true - - https://oss.sonatype.org/content/groups/public/ - - - - com.github.jsqlparser - jsqlparser - |JSQLPARSER_SNAPSHOT_VERSION| - +.. tab:: Gradle Stable - .. tab:: Gradle Stable + .. code-block:: groovy + :substitutions: - .. code-block:: groovy - :substitutions: - - repositories { - mavenCentral() - } + repositories { + mavenCentral() + } - dependencies { - implementation 'com.github.jsqlparser:jsqlparser:|JSQLPARSER_VERSION|' - } + dependencies { + implementation 'com.github.jsqlparser:jsqlparser:|JSQLPARSER_VERSION|' + } - .. tab:: Gradle Snapshot +.. tab:: Gradle Snapshot - .. code-block:: groovy - :substitutions: + .. code-block:: groovy + :substitutions: - repositories { - maven { - url = uri('https://oss.sonatype.org/content/groups/public/') - } + repositories { + maven { + url = uri('https://oss.sonatype.org/content/groups/public/') } + } - dependencies { - implementation 'com.github.jsqlparser:jsqlparser:|JSQLPARSER_SNAPSHOT_VERSION|' - } + dependencies { + implementation 'com.github.jsqlparser:jsqlparser:|JSQLPARSER_SNAPSHOT_VERSION|' + } Parse a SQL Statement @@ -113,25 +108,24 @@ Parse the SQL Text into Java Objects: .. code-block:: java - String sqlStr="select 1 from dual where a=b"; + String sqlStr = "select 1 from dual where a=b"; - Statement statement = CCJSqlParserUtil.parse(sqlStr); - if (statement instanceof Select) { - Select select = (Select) statement; - PlainSelect plainSelect = (PlainSelect) select.getSelectBody(); + PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); - SelectExpressionItem selectExpressionItem = (SelectExpressionItem) plainSelect.getSelectItems().get(0); - Assertions.assertEquals( new LongValue(1), selectExpressionItem.getExpression()); + SelectItem selectItem = + select.getSelectItems().get(0); + Assertions.assertEquals( + new LongValue(1) + , selectItem.getExpression()); - Table table = (Table) plainSelect.getFromItem(); - Assertions.assertEquals("dual", table.getName()); + Table table = (Table) select.getFromItem(); + Assertions.assertEquals("dual", table.getName()); - EqualsTo equalsTo = (EqualsTo) plainSelect.getWhere(); - Column a = (Column) equalsTo.getLeftExpression(); - Column b = (Column) equalsTo.getRightExpression(); - Assertions.assertEquals("a", a.getColumnName()); - Assertions.assertEquals("b", b.getColumnName()); - } + EqualsTo equalsTo = (EqualsTo) select.getWhere(); + Column a = (Column) equalsTo.getLeftExpression(); + Column b = (Column) equalsTo.getRightExpression(); + Assertions.assertEquals("a", a.getColumnName()); + Assertions.assertEquals("b", b.getColumnName()); For guidance with the API, use `JSQLFormatter `_ to visualize the Traversable Tree of Java Objects: @@ -141,15 +135,13 @@ For guidance with the API, use `JSQLFormatter
         SQL Text
    -     └─Statements: net.sf.jsqlparser.statement.select.Select
    -        └─select: net.sf.jsqlparser.statement.select.PlainSelect
    -           ├─selectItems -> Collection<SelectExpressionItem>
    -           │  └─selectItems: net.sf.jsqlparser.statement.select.SelectExpressionItem
    -           │     └─LongValue: 1
    -           ├─Table: dual
    -           └─where: net.sf.jsqlparser.expression.operators.relational.EqualsTo
    -              ├─Column: a
    -              └─Column: b
    +          └─Statements: net.sf.jsqlparser.statement.select.Select
    +              ├─selectItems -> Collection
    +              │  └─LongValue: 1
    +              ├─Table: dual
    +              └─where: net.sf.jsqlparser.expression.operators.relational.EqualsTo
    +                 ├─Column: a
    +                 └─Column: b
        
    @@ -205,9 +197,6 @@ Build any SQL Statement from Java Code using a fluent API: String expectedSQLStr = "SELECT 1 FROM dual t WHERE a = b"; // Step 1: generate the Java Object Hierarchy for - SelectExpressionItem selectExpressionItem = - new SelectExpressionItem().withExpression(new LongValue().withValue(1)); - Table table = new Table().withName("dual").withAlias(new Alias("t", false)); Column columnA = new Column().withColumnName("a"); @@ -215,9 +204,8 @@ Build any SQL Statement from Java Code using a fluent API: Expression whereExpression = new EqualsTo().withLeftExpression(columnA).withRightExpression(columnB); - PlainSelect plainSelect = new PlainSelect().addSelectItems(selectExpressionItem) + PlainSelect select = new PlainSelect().addSelectItem(new LongValue(1)) .withFromItem(table).withWhere(whereExpression); - Select select = new Select().withSelectBody(plainSelect); // Step 2a: Print into a SQL Statement Assertions.assertEquals(expectedSQLStr, select.toString()); diff --git a/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java b/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java index 4f0fd5d6a..fa301142a 100644 --- a/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java @@ -45,11 +45,11 @@ public void testInExpressionProblem() throws JSQLParserException { public void visit(InExpression expr) { super.visit(expr); exprList.add(expr.getLeftExpression()); - exprList.add(expr.getRightItemsList()); + exprList.add(expr.getRightExpression()); } }); - assertTrue(exprList.get(0) instanceof Expression); + assertTrue(exprList.get(0) instanceof Column); assertTrue(exprList.get(1) instanceof ExpressionList); } @@ -69,7 +69,7 @@ public void visit(InExpression expr) { } }); - assertTrue(exprList.get(0) instanceof RowConstructor); + assertTrue(exprList.get(0) instanceof ExpressionList); assertTrue(exprList.get(1) instanceof Select); } diff --git a/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java b/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java new file mode 100644 index 000000000..28ce1d956 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java @@ -0,0 +1,41 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +class FunctionTest { + @Test + @Disabled + // @Todo: Implement the Prediction(... USING ...) functions + // https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/PREDICTION.html + void testNestedFunctions() throws JSQLParserException { + String sqlStr = + "select cust_gender, count(*) as cnt, round(avg(age)) as avg_age\n" + + " from mining_data_apply_v\n" + + " where prediction(dt_sh_clas_sample cost model\n" + + " using cust_marital_status, education, household_size) = 1\n" + + " group by cust_gender\n" + + " order by cust_gender"; + + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testCallFunction() throws JSQLParserException { + String sqlStr = + "call dbms_scheduler.auto_purge ( ) "; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + +} diff --git a/src/test/java/net/sf/jsqlparser/expression/JdbcNamedParameterTest.java b/src/test/java/net/sf/jsqlparser/expression/JdbcNamedParameterTest.java new file mode 100644 index 000000000..f2a4bfe70 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/JdbcNamedParameterTest.java @@ -0,0 +1,42 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +class JdbcNamedParameterTest { + @Test + void testDoubleColon() throws JSQLParserException { + String sqlStr = "select :test"; + PlainSelect select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + assertTrue(select.getSelectItems().get(0).getExpression() instanceof JdbcNamedParameter); + } + + @Test + void testAmpersand() throws JSQLParserException { + String sqlStr = "select &test, 'a & b', a & b"; + PlainSelect select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + assertTrue(select.getSelectItems().get(0).getExpression() instanceof JdbcNamedParameter); + assertTrue(select.getSelectItems().get(2).getExpression() instanceof BitwiseAnd); + } + + @Test + void testIssue1785() throws JSQLParserException { + String sqlStr = "select * from all_tables\n" + + "where owner = &myowner"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } +} diff --git a/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java new file mode 100644 index 000000000..860a69382 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java @@ -0,0 +1,111 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import org.junit.jupiter.api.Test; + +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; + +class JsonExpressionTest { + + @Test + void testIssue1792() throws JSQLParserException, InterruptedException { + String sqlStr = + "SELECT ''::JSON -> 'obj'::TEXT"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = + "SELECT ('{\"obj\":{\"field\": \"value\"}}'::JSON -> 'obj'::TEXT ->> 'field'::TEXT)"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = + "SELECT\n" + + " CASE\n" + + " WHEN true\n" + + " THEN (SELECT ((('{\"obj\":{\"field\": \"value\"}}'::JSON -> 'obj'::TEXT ->> 'field'::TEXT))))\n" + + " END"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testParenthesedJsonExpressionsIssue1792() throws JSQLParserException { + String sqlStr = + "SELECT table_a.b_e_t,\n" + + " CASE\n" + + " WHEN table_a.g_o_a_c IS NULL THEN 'a'\n" + + " ELSE table_a.g_o_a_c\n" + + " END AS e_cd,\n" + + " CASE\n" + + " WHEN table_a.a_f_t IS NULL THEN 'b'\n" + + " ELSE table_a.a_f_t\n" + + " END AS a_f_t,\n" + + " COUNT(1) AS count,\n" + + " ROUND(ABS(SUM(table_a.gb_eq))::NUMERIC, 2) AS total_x\n" + + "FROM (SELECT table_x.b_e_t,\n" + + " table_x.b_e_a,\n" + + " table_y.g_o_a_c,\n" + + " table_z.a_f_t,\n" + + " CASE\n" + + " WHEN table_x.b_e_a IS NOT NULL THEN table_x.b_e_a::DOUBLE PRECISION /\n" + + " schema_z.g_c_r(table_x.c_c,\n" + + " 'x'::CHARACTER VARYING,\n" + + " table_x.r_ts::DATE)\n" + + " ELSE\n" + + " CASE\n" + + " WHEN table_x.b_e_t::TEXT = 'p_e'::TEXT THEN (SELECT ((\n" + + " (table_x.pld::JSON -> 'p_d'::TEXT) ->>\n" + + " 's_a'::TEXT)::DOUBLE PRECISION) / schema_z.g_c_r(fba.s_c_c,\n" + + " 'x'::CHARACTER VARYING,\n" + + " table_x.r_ts::DATE)\n" + + " FROM schema_z.f_b_a fba\n" + + " JOIN schema_z.t_b_a_n_i table_y\n" + + " ON fba.b_a_i = table_y.f_b_a_id\n" + + " WHERE table_y.t_ngn_id =\n" + + " (((table_x.pld::JSON -> 'p_d'::TEXT) ->>\n" + + " 's_a_i'::TEXT)::BIGINT))\n" + + " WHEN table_x.b_e_t::TEXT = 'i_e'::TEXT\n" + + " THEN (SELECT (((table_x.pld::JSON -> 'i_d'::TEXT) ->> 'a'::TEXT)::DOUBLE PRECISION) /\n" + + " schema_z.g_c_r(fba.s_c_c, 'x'::CHARACTER VARYING,\n" + + " table_x.r_ts::DATE)\n" + + " FROM schema_z.f_b_a fba\n" + + " JOIN schema_z.t_b_a_n_i table_y\n" + + " ON fba.b_a_i = table_y.f_b_a_id\n" + + " WHERE table_y.t_ngn_id = (((table_x.pld::JSON -> 'i_d'::TEXT) ->>\n" + + " 's_a_i'::TEXT)::BIGINT))\n" + + " WHEN table_x.b_e_t::TEXT = 'i_e_2'::TEXT\n" + + " THEN (SELECT (((table_x.pld::JSON -> 'i_d'::TEXT) ->> 'a'::TEXT)::DOUBLE PRECISION) /\n" + + " schema_z.g_c_r(fba.s_c_c, 'x'::CHARACTER VARYING,\n" + + " table_x.r_ts::DATE)\n" + + " FROM schema_z.f_b_a fba\n" + + " JOIN schema_z.t_b_a_n_i table_y\n" + + " ON fba.b_a_i = table_y.f_b_a_id\n" + + " WHERE table_y.t_ngn_id = (((table_x.pld::JSON -> 'id'::TEXT) ->>\n" + + " 'd_i'::TEXT)::BIGINT))\n" + + " WHEN table_x.b_e_t::TEXT = 'm_e'::TEXT\n" + + " THEN (SELECT (((table_x.pld::JSON -> 'o'::TEXT) ->> 'eda'::TEXT)::DOUBLE PRECISION) /\n" + + " schema_z.g_c_r(\n" + + " ((table_x.pld::JSON -> 'o'::TEXT) ->> 'dc'::TEXT)::CHARACTER VARYING,\n" + + " 'x'::CHARACTER VARYING, table_x.r_ts::DATE))\n" + + " ELSE NULL::DOUBLE PRECISION\n" + + " END\n" + + " END AS gb_eq\n" + + " FROM schema_z.baz\n" + + " LEFT JOIN f_ctl.g_o_f_e_t_a_m table_y\n" + + " ON table_x.p_e_m LIKE table_y.f_e_m_p\n" + + " LEFT JOIN f_ctl.g_o_c_a_t table_z\n" + + " ON table_z.c_a_t_c = table_y.g_o_a_c\n" + + " WHERE table_x.p_st = 'E'\n" + + " ) table_a\n" + + "GROUP BY 1, 2, 3"; + + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } +} diff --git a/src/test/java/net/sf/jsqlparser/expression/RowConstructorTest.java b/src/test/java/net/sf/jsqlparser/expression/RowConstructorTest.java new file mode 100644 index 000000000..f7918becb --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/RowConstructorTest.java @@ -0,0 +1,22 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +class RowConstructorTest { + @Test + public void testRowConstructor() throws JSQLParserException { + TestUtils.assertExpressionCanBeParsedAndDeparsed("ROW(dataid, value, calcMark)", true); + } + +} diff --git a/src/test/java/net/sf/jsqlparser/expression/TranscodingFunctionTest.java b/src/test/java/net/sf/jsqlparser/expression/TranscodingFunctionTest.java new file mode 100644 index 000000000..62599c6e0 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/TranscodingFunctionTest.java @@ -0,0 +1,52 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import org.junit.jupiter.api.Test; + +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; +import static org.junit.jupiter.api.Assertions.*; + +class TranscodingFunctionTest { + + @Test + void testTranscoding() throws JSQLParserException { + String functionStr = "CONVERT( 'abc' USING utf8mb4 )"; + String sqlStr = "SELECT " + functionStr; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + TranscodingFunction transcodingFunction = new TranscodingFunction() + .withExpression(new StringValue("abc")) + .withTranscodingName("utf8mb4"); + assertEquals(functionStr, transcodingFunction.toString()); + } + + @Test + void testIssue644() throws JSQLParserException { + String sqlStr = "SELECT CONVERT(int, a) FROM A"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testIssue688() throws JSQLParserException { + String sqlStr = "select * from a order by convert(a.name using gbk) desc"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testIssue1257() throws JSQLParserException { + String sqlStr = "SELECT id,name,version,identity,type,desc,enable,content\n" + + "FROM tbl_template\n" + + "WHERE (name like ?)\n" + + "ORDER BY convert(name using GBK) ASC"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } +} diff --git a/src/test/java/net/sf/jsqlparser/expression/TrimFunctionTest.java b/src/test/java/net/sf/jsqlparser/expression/TrimFunctionTest.java new file mode 100644 index 000000000..aa07d7f0d --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/TrimFunctionTest.java @@ -0,0 +1,40 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import org.junit.jupiter.api.Test; + +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; +import static org.junit.jupiter.api.Assertions.*; + +class TrimFunctionTest { + + @Test + void testTrim() throws JSQLParserException { + String functionStr = "Trim( BOTH 'x' FROM 'xTomxx' )"; + String sqlStr = "select " + functionStr; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + TrimFunction trimFunction = new TrimFunction() + .withTrimSpecification(TrimFunction.TrimSpecification.BOTH) + .withExpression(new StringValue("x")) + .withUsingFromKeyword(true) + .withFromExpression(new StringValue("xTomxx")); + assertEquals(functionStr, trimFunction.toString()); + assertEquals( + functionStr.replace(" FROM", ","), + trimFunction.withUsingFromKeyword(false).toString()); + + sqlStr = "select trim(BOTH from unnest(string_to_array(initcap(bbbbb),';')))"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + +} diff --git a/src/test/java/net/sf/jsqlparser/expression/mysql/MySqlSqlCalcFoundRowsTest.java b/src/test/java/net/sf/jsqlparser/expression/mysql/MySqlSqlCalcFoundRowsTest.java index e363a9bac..abb816607 100644 --- a/src/test/java/net/sf/jsqlparser/expression/mysql/MySqlSqlCalcFoundRowsTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/mysql/MySqlSqlCalcFoundRowsTest.java @@ -20,8 +20,6 @@ import net.sf.jsqlparser.statement.select.SelectVisitorAdapter; import org.junit.jupiter.api.Test; -import java.util.Arrays; - import static net.sf.jsqlparser.test.TestUtils.assertDeparse; import static net.sf.jsqlparser.test.TestUtils.assertEqualsObjectTree; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; @@ -47,7 +45,7 @@ public void testPossibleParsingWithSqlCalcFoundRowsHint() throws JSQLParserExcep Statement parsed = assertSqlCanBeParsedAndDeparsed(sqlCalcFoundRowsContainingSql); assertSqlCanBeParsedAndDeparsed(generalSql); - Select created = new PlainSelect().addSelectItems(Arrays.asList(new AllColumns())) + Select created = new PlainSelect().addSelectItem(new AllColumns()) .withMySqlSqlCalcFoundRows(true).withFromItem(new Table("TABLE")); assertDeparse(created, sqlCalcFoundRowsContainingSql); assertEqualsObjectTree(parsed, created); diff --git a/src/test/java/net/sf/jsqlparser/expression/operators/relational/InExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/operators/relational/InExpressionTest.java new file mode 100644 index 000000000..ac1e2a0cf --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/operators/relational/InExpressionTest.java @@ -0,0 +1,33 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression.operators.relational; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class InExpressionTest { + + @Test + void testOracleInWithoutBrackets() throws JSQLParserException { + String sqlStr = "select 1 from dual where a in 1 "; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + + @Test + void testOracleInWithBrackets() throws JSQLParserException { + String sqlStr = "select 1 from dual where a in (1) "; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + +} diff --git a/src/test/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpressionTest.java new file mode 100644 index 000000000..07da800e1 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpressionTest.java @@ -0,0 +1,25 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression.operators.relational; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +class MemberOfExpressionTest { + @Test + void testMemberOf() throws JSQLParserException { + String sqlStr = "SELECT 17 MEMBER OF ( cxr_post_id->'$.value' ) "; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT 17 MEMBER OF ( '[23, \"abc\", 17, \"ab\", 10]' ) "; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } +} diff --git a/src/test/java/net/sf/jsqlparser/parser/CCJSqlParserTest.java b/src/test/java/net/sf/jsqlparser/parser/CCJSqlParserTest.java index d59fdb973..f0093e11f 100644 --- a/src/test/java/net/sf/jsqlparser/parser/CCJSqlParserTest.java +++ b/src/test/java/net/sf/jsqlparser/parser/CCJSqlParserTest.java @@ -1,3 +1,12 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ package net.sf.jsqlparser.parser; import static org.assertj.core.api.Assertions.assertThat; @@ -10,7 +19,7 @@ public class CCJSqlParserTest { @Test public void parserWithTimeout() throws Exception { CCJSqlParser parser = CCJSqlParserUtil.newParser("foo").withTimeOut(123L); - + Long timeOut = parser.getAsLong(Feature.timeOut); assertThat(timeOut).isEqualTo(123L); diff --git a/src/test/java/net/sf/jsqlparser/parser/CCJSqlParserUtilTest.java b/src/test/java/net/sf/jsqlparser/parser/CCJSqlParserUtilTest.java index 2c210e163..7e4cf78b1 100644 --- a/src/test/java/net/sf/jsqlparser/parser/CCJSqlParserUtilTest.java +++ b/src/test/java/net/sf/jsqlparser/parser/CCJSqlParserUtilTest.java @@ -14,7 +14,11 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.logging.Level; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Expression; @@ -25,16 +29,58 @@ import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.Statements; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Disabled; +import net.sf.jsqlparser.statement.UnsupportedStatement; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.test.MemoryLeakVerifier; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; public class CCJSqlParserUtilTest { + private final static String INVALID_SQL = "" + + "SELECT * FROM TABLE_1 t1\n" + + "WHERE\n" + + "(((t1.COL1 = 'VALUE2' )\n" + + "AND (t1.CAL2 = 'VALUE2' ))\n" + + "AND (((1 = 1 )\n" + + "AND ((((((t1.id IN (940550 ,940600 ,940650 ,940700 ,940750 ,940800 ,940850 ,940900 ,940950 ,941000 ,941050 ,941100 ,941150 ,941200 ,941250 ,941300 ,941350 ,941400 ,941450 ,941500 ,941550 ,941600 ,941650 ,941700 ,941750 ,941800 ,941850 ,941900 ,941950 ,942000 ,942050 ,942100 ,942150 ,942200 ,942250 ,942300 ,942350 ,942400 ,942450 ,942500 ,942550 ,942600 ,942650 ,942700 ,942750 ,942800 ,942850 ,942900 ,942950 ,943000 ,943050 ,943100 ,943150 ,943200 ,943250 ,943300 ,943350 ,943400 ,943450 ,943500 ,943550 ,943600 ,943650 ,943700 ,943750 ,943800 ,943850 ,943900 ,943950 ,944000 ,944050 ,944100 ,944150 ,944200 ,944250 ,944300 ,944350 ,944400 ,944450 ,944500 ,944550 ,944600 ,944650 ,944700 ,944750 ,944800 ,944850 ,944900 ,944950 ,945000 ,945050 ,945100 ,945150 ,945200 ,945250 ,945300 ))\n" + + "OR (t1.id IN (945350 ,945400 ,945450 ,945500 ,945550 ,945600 ,945650 ,945700 ,945750 ,945800 ,945850 ,945900 ,945950 ,946000 ,946050 ,946100 ,946150 ,946200 ,946250 ,946300 ,946350 ,946400 ,946450 ,946500 ,946550 ,946600 ,946650 ,946700 ,946750 ,946800 ,946850 ,946900 ,946950 ,947000 ,947050 ,947100 ,947150 ,947200 ,947250 ,947300 ,947350 ,947400 ,947450 ,947500 ,947550 ,947600 ,947650 ,947700 ,947750 ,947800 ,947850 ,947900 ,947950 ,948000 ,948050 ,948100 ,948150 ,948200 ,948250 ,948300 ,948350 ,948400 ,948450 ,948500 ,948550 ,948600 ,948650 ,948700 ,948750 ,948800 ,948850 ,948900 ,948950 ,949000 ,949050 ,949100 ,949150 ,949200 ,949250 ,949300 ,949350 ,949400 ,949450 ,949500 ,949550 ,949600 ,949650 ,949700 ,949750 ,949800 ,949850 ,949900 ,949950 ,950000 ,950050 ,950100 )))\n" + + "OR (t1.id IN (950150 ,950200 ,950250 ,950300 ,950350 ,950400 ,950450 ,950500 ,950550 ,950600 ,950650 ,950700 ,950750 ,950800 ,950850 ,950900 ,950950 ,951000 ,951050 ,951100 ,951150 ,951200 ,951250 ,951300 ,951350 ,951400 ,951450 ,951500 ,951550 ,951600 ,951650 ,951700 ,951750 ,951800 ,951850 ,951900 ,951950 ,952000 ,952050 ,952100 ,952150 ,952200 ,952250 ,952300 ,952350 ,952400 ,952450 ,952500 ,952550 ,952600 ,952650 ,952700 ,952750 ,952800 ,952850 ,952900 ,952950 ,953000 ,953050 ,953100 ,953150 ,953200 ,953250 ,953300 ,953350 ,953400 ,953450 ,953500 ,953550 ,953600 ,953650 ,953700 )))\n" + + "OR (t1.id IN (953750 ,953800 ,953850 ,953900 ,953950 ,954000 ,954050 ,954100 ,954150 ,954200 ,954250 ,954300 ,954350 ,954400 ,954450 ,954500 ,954550 ,954600 ,954650 ,954700 ,954750 ,954800 ,954850 ,954900 ,954950 ,955000 ,955050 ,955100 ,955150 ,955200 ,955250 ,955300 ,955350 ,955400 ,955450 ,955500 ,955550 ,955600 ,955650 ,955700 ,955750 ,955800 ,955850 ,955900 ,955950 ,956000 ,956050 ,956100 ,956150 ,956200 ,956250 ,956300 ,956350 ,956400 ,956450 ,956500 ,956550 ,956600 ,956650 ,956700 ,956750 ,956800 ,956850 ,956900 ,956950 ,957000 ,957050 ,957100 ,957150 ,957200 ,957250 ,957300 )))\n" + + "OR (t1.id IN (944100, 944150, 944200, 944250, 944300, 944350, 944400, 944450, 944500, 944550, 944600, 944650, 944700, 944750, 944800, 944850, 944900, 944950, 945000 )))\n" + + "OR (t1.id IN (957350 ,957400 ,957450 ,957500 ,957550 ,957600 ,957650 ,957700 ,957750 ,957800 ,957850 ,957900 ,957950 ,958000 ,958050 ,958100 ,958150 ,958200 ,958250 ,958300 ,958350 ,958400 ,958450 ,958500 ,958550 ,958600 ,958650 ,958700 ,958750 ,958800 ,958850 ,958900 ,958950 ,959000 ,959050 ,959100 ,959150 ,959200 ,959250 ,959300 ,959350 ,959400 ,959450 ,959500 ,959550 ,959600 ,959650 ,959700 ,959750 ,959800 ,959850 ,959900 ,959950 ,960000 ,960050 ,960100 ,960150 ,960200 ,960250 ,960300 ,960350 ,960400 ,960450 ,960500 ,960550 ,960600 ,960650 ,960700 ,960750 ,960800 ,960850 ,960900 ,960950 ,961000 ,961050 ,961100 ,961150 ,961200 ,961250 ,961300 ,961350 ,961400 ,961450 ,961500 ,961550 ,961600 ,961650 ,961700 ,961750 ,961800 ,961850 ,961900 ,961950 ,962000 ,962050 ,962100 ))))\n" + + "OR (t1.id IN (962150 ,962200 ,962250 ,962300 ,962350 ,962400 ,962450 ,962500 ,962550 ,962600 ,962650 ,962700 ,962750 ,962800 ,962850 ,962900 ,962950 ,963000 ,963050 ,963100 ,963150 ,963200 ,963250 ,963300 ,963350 ,963400 ,963450 ,963500 ,963550 ,963600 ,963650 ,963700 ,963750 ,963800 ,963850 ,963900 ,963950 ,964000 ,964050 ,964100 ,964150 ,964200 ,964250 ,964300 ,964350 ,964400 ,964450 ,964500 ,964550 ,964600 ,964650 ,964700 ,964750 ,964800 ,964850 ,964900 ,964950 ,965000 ,965050 ,965100 ,965150 ,965200 ,965250 ,965300 ,965350 ,965400 ,965450 ,965500 ))))\n" + + "AND t1.COL3 IN (\n" + + " SELECT\n" + + " t2.COL3\n" + + " FROM\n" + + " TABLE_6 t6,\n" + + " TABLE_1 t5,\n" + + " TABLE_4 t4,\n" + + " TABLE_3 t3,\n" + + " TABLE_1 t2\n" + + " WHERE\n" + + " (((((((t5.CAL3 = T6.id)\n" + + " AND (t5.CAL5 = t6.CAL5))\n" + + " AND (t5.CAL1 = t6.CAL1))\n" + + " AND (t3.CAL1 IN (108500)))\n" + + " AND (t5.id = t2.id))\n" + + " AND NOT ((t6.CAL6 IN ('VALUE'))))\n" + + " AND ((t2.id = t3.CAL2)\n" + + " AND (t4.id = t3.CAL3))))\n" + + // add two redundant unmatched brackets in order to make the Simple Parser fail + // and get the complex parser stuck + " )) \n" + + "ORDER BY\n" + + "t1.id ASC"; + @Test public void testParseExpression() throws Exception { Expression result = CCJSqlParserUtil.parseExpression("a+b"); @@ -57,7 +103,8 @@ public void testParseExpression2() throws Exception { @Test public void testParseExpressionNonPartial() throws Exception { - assertThrows(JSQLParserException.class, () -> CCJSqlParserUtil.parseExpression("a+", false)); + assertThrows(JSQLParserException.class, + () -> CCJSqlParserUtil.parseExpression("a+", false)); } @@ -68,7 +115,8 @@ public void testParseExpressionFromStringFail() throws Exception { @Test public void testParseExpressionFromRaderFail() throws Exception { - assertThrows(JSQLParserException.class, () -> CCJSqlParserUtil.parse(new StringReader("whatever$"))); + assertThrows(JSQLParserException.class, + () -> CCJSqlParserUtil.parse(new StringReader("whatever$"))); } @Test @@ -91,14 +139,17 @@ public void testParseCondExpressionFail() throws Exception { @Test public void testParseFromStreamFail() throws Exception { assertThrows(JSQLParserException.class, - () -> CCJSqlParserUtil.parse(new ByteArrayInputStream("BLA".getBytes(StandardCharsets.UTF_8)))); + () -> CCJSqlParserUtil + .parse(new ByteArrayInputStream("BLA".getBytes(StandardCharsets.UTF_8)))); } @Test public void testParseFromStreamWithEncodingFail() throws Exception { assertThrows(JSQLParserException.class, - () -> CCJSqlParserUtil.parse(new ByteArrayInputStream("BLA".getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8.name())); + () -> CCJSqlParserUtil.parse( + new ByteArrayInputStream("BLA".getBytes(StandardCharsets.UTF_8)), + StandardCharsets.UTF_8.name())); } @@ -110,7 +161,8 @@ public void testParseCondExpressionNonPartial() throws Exception { @Test public void testParseCondExpressionNonPartial2() throws Exception { - assertThrows(JSQLParserException.class, () -> CCJSqlParserUtil.parseCondExpression("x=92 lasd y=29", false)); + assertThrows(JSQLParserException.class, + () -> CCJSqlParserUtil.parseCondExpression("x=92 lasd y=29", false)); } @Test @@ -121,7 +173,8 @@ public void testParseCondExpressionPartial2() throws Exception { @Test public void testParseCondExpressionIssue471() throws Exception { - Expression result = CCJSqlParserUtil.parseCondExpression("(SSN,SSM) IN ('11111111111111', '22222222222222')"); + Expression result = CCJSqlParserUtil + .parseCondExpression("(SSN,SSM) IN ('11111111111111', '22222222222222')"); assertEquals("(SSN, SSM) IN ('11111111111111', '22222222222222')", result.toString()); } @@ -129,14 +182,14 @@ public void testParseCondExpressionIssue471() throws Exception { public void testParseStatementsIssue691() throws Exception { Statements result = CCJSqlParserUtil.parseStatements( "select * from dual;\n" - + "\n" - + "select\n" - + "*\n" - + "from\n" - + "dual;\n" - + "\n" - + "select *\n" - + "from dual;"); + + "\n" + + "select\n" + + "*\n" + + "from\n" + + "dual;\n" + + "\n" + + "select *\n" + + "from dual;"); assertEquals("SELECT * FROM dual;\n" + "SELECT * FROM dual;\n" + "SELECT * FROM dual;\n", result.toString()); @@ -165,23 +218,32 @@ public void accept(Statement statement) { } @Test - @Disabled public void testParseStatementsFail() throws Exception { - // This will not fail, but always return the Unsupported Statements - // Since we can't LOOKAHEAD in the Statements() production - assertThrows(JSQLParserException.class, () -> CCJSqlParserUtil.parseStatements("select * from dual;WHATEVER!!")); + String sqlStr = "select * from dual;WHATEVER!!"; + + // Won't fail but return Unsupported Statement instead + assertDoesNotThrow(new Executable() { + @Override + public void execute() throws Throwable { + final Statements statements = CCJSqlParserUtil.parseStatements(sqlStr); + assertEquals(2, statements.size()); + assertTrue(statements.get(0) instanceof PlainSelect); + assertTrue(statements.get(1) instanceof UnsupportedStatement); + } + }); } @Test public void testParseASTFail() throws Exception { - assertThrows(JSQLParserException.class, () -> CCJSqlParserUtil.parseAST("select * from dual;WHATEVER!!")); + assertThrows(JSQLParserException.class, + () -> CCJSqlParserUtil.parseAST("select * from dual;WHATEVER!!")); } @Test public void testParseStatementsIssue691_2() throws Exception { Statements result = CCJSqlParserUtil.parseStatements( "select * from dual;\n" - + "---test"); + + "---test"); assertEquals("SELECT * FROM dual;\n", result.toString()); } @@ -193,9 +255,11 @@ public void testParseStatementIssue742() throws Exception { + " PRIMARY KEY (`id`),\n" + " UNIQUE KEY `uk_another_column_id` (`another_column_id`)\n" + ")"); - assertEquals("CREATE TABLE `table_name` (`id` bigint (20) NOT NULL AUTO_INCREMENT, `another_column_id` " - + "bigint (20) NOT NULL COMMENT 'column id as sent by SYSTEM', PRIMARY KEY (`id`), UNIQUE KEY `uk_another_column_id` " - + "(`another_column_id`));\n", result.toString()); + assertEquals( + "CREATE TABLE `table_name` (`id` bigint (20) NOT NULL AUTO_INCREMENT, `another_column_id` " + + "bigint (20) NOT NULL COMMENT 'column id as sent by SYSTEM', PRIMARY KEY (`id`), UNIQUE KEY `uk_another_column_id` " + + "(`another_column_id`));\n", + result.toString()); } @Test @@ -232,7 +296,8 @@ public void testNestingDepth() throws Exception { + " , a.id_instrument_type\n" + " , b.id_portfolio\n" + " , c.attribute_value product_code\n" - + " , t.valid_date\n" + " , t.ccf\n" + + " , t.valid_date\n" + + " , t.ccf\n" + " FROM cfe.instrument a\n" + " INNER JOIN cfe.impairment b\n" + " ON a.id_instrument = b.id_instrument\n" @@ -258,58 +323,108 @@ public void testNestingDepth() throws Exception { @Test public void testParseStatementIssue1250() throws Exception { - Statement result = CCJSqlParserUtil.parse("Select test.* from (Select * from sch.PERSON_TABLE // root test\n) as test"); - assertEquals("SELECT test.* FROM (SELECT * FROM sch.PERSON_TABLE) AS test", result.toString()); + Statement result = CCJSqlParserUtil.parse( + "Select test.* from (Select * from sch.PERSON_TABLE // root test\n) as test"); + assertEquals("SELECT test.* FROM (SELECT * FROM sch.PERSON_TABLE) AS test", + result.toString()); } @Test public void testCondExpressionIssue1482() throws JSQLParserException { - Expression expr = CCJSqlParserUtil.parseCondExpression("test_table_enum.f1_enum IN ('TEST2'::test.test_enum)", false); + Expression expr = CCJSqlParserUtil + .parseCondExpression("test_table_enum.f1_enum IN ('TEST2'::test.test_enum)", false); assertEquals("test_table_enum.f1_enum IN ('TEST2'::test.test_enum)", expr.toString()); } @Test public void testCondExpressionIssue1482_2() throws JSQLParserException { - Expression expr = CCJSqlParserUtil.parseCondExpression("test_table_enum.f1_enum IN ('TEST2'::test.\"test_enum\")", false); + Expression expr = CCJSqlParserUtil.parseCondExpression( + "test_table_enum.f1_enum IN ('TEST2'::test.\"test_enum\")", false); assertEquals("test_table_enum.f1_enum IN ('TEST2'::test.\"test_enum\")", expr.toString()); } + /** + * The purpose of the test is to run into a timeout and to stop the parser when this happens. We + * provide an INVALID statement for this purpose, which will fail the SIMPLE parse and then hang + * with COMPLEX parsing until the timeout occurs. + *

    + * We repeat that test multiple times and want to see no stale references to the Parser after + * timeout. + */ + @Test + public void testParserInterruptedByTimeout() { + MemoryLeakVerifier verifier = new MemoryLeakVerifier(); + + int parallelThreads = Runtime.getRuntime().availableProcessors() + 1; + ExecutorService executorService = Executors.newFixedThreadPool(parallelThreads); + ExecutorService timeOutService = Executors.newSingleThreadExecutor(); + for (int i = 0; i < parallelThreads; i++) { + executorService.submit(new Runnable() { + @Override + public void run() { + + try { + CCJSqlParser parser = + CCJSqlParserUtil.newParser(INVALID_SQL) + .withAllowComplexParsing(true); + verifier.addObject(parser); + CCJSqlParserUtil.parseStatement(parser, timeOutService); + } catch (JSQLParserException ignore) { + // We expected that to happen. + } + } + }); + } + timeOutService.shutdownNow(); + executorService.shutdown(); + + // we should not run in any timeout here (because we expect that the Parser has timed out by + // itself) + assertDoesNotThrow(new Executable() { + @Override + public void execute() throws Throwable { + executorService.awaitTermination(10, TimeUnit.SECONDS); + } + }); + + // we should not have any Objects left in the weak reference map + verifier.assertGarbageCollected(); + } + @Test - public void testTimeOutIssue1582() throws InterruptedException { + public void testTimeOutIssue1582() { // This statement is INVALID on purpose - // There are crafted INTO keywords in order to make it fail but only after a long time (40 seconds plus) + // There are crafted INTO keywords in order to make it fail but only after a long time (40 + // seconds plus) String sqlStr = "" + "select\n" - + " t0.operatienr\n" - + " , case\n" - + " when\n" - + " case when (t0.vc_begintijd_operatie is null or lpad((extract('hours' into t0.vc_begintijd_operatie::timestamp))::text,2,'0') ||':'|| lpad(extract('minutes' from t0.vc_begintijd_operatie::timestamp)::text,2,'0') = '00:00') then null\n" - + " else (greatest(((extract('hours' into (t0.vc_eindtijd_operatie::timestamp-t0.vc_begintijd_operatie::timestamp))*60 + extract('minutes' from (t0.vc_eindtijd_operatie::timestamp-t0.vc_begintijd_operatie::timestamp)))/60)::numeric(12,2),0))*60\n" - + " end = 0 then null\n" - + " else '25. Meer dan 4 uur'\n" - + " end \n" - + " as snijtijd_interval"; + + " t0.operatienr\n" + + " , case\n" + + " when\n" + + " case when (t0.vc_begintijd_operatie is null or lpad((extract('hours' into t0.vc_begintijd_operatie::timestamp))::text,2,'0') ||':'|| lpad(extract('minutes' from t0.vc_begintijd_operatie::timestamp)::text,2,'0') = '00:00') then null\n" + + " else (greatest(((extract('hours' into (t0.vc_eindtijd_operatie::timestamp-t0.vc_begintijd_operatie::timestamp))*60 + extract('minutes' from (t0.vc_eindtijd_operatie::timestamp-t0.vc_begintijd_operatie::timestamp)))/60)::numeric(12,2),0))*60\n" + + " end = 0 then null\n" + + " else '25. Meer dan 4 uur'\n" + + " end\n" + + " as snijtijd_interval"; // With DEFAULT TIMEOUT 6 Seconds, we expect the statement to timeout normally // A TimeoutException wrapped into a Parser Exception should be thrown - assertThrows(TimeoutException.class, new Executable() { + assertThrows(JSQLParserException.class, new Executable() { @Override public void execute() throws Throwable { try { CCJSqlParserUtil.parse(sqlStr); } catch (JSQLParserException ex) { - Throwable cause = ((JSQLParserException) ex).getCause(); - if (cause != null) { - throw cause; - } else { - throw ex; - } + assertTrue(ex.getCause() instanceof TimeoutException); + throw ex; } } }); - // With custom TIMEOUT 60 Seconds, we expect the statement to not timeout but to fail instead + // With custom TIMEOUT 60 Seconds, we expect the statement to not timeout but to fail + // instead // No TimeoutException wrapped into a Parser Exception must be thrown // Instead we expect a Parser Exception only assertThrows(JSQLParserException.class, new Executable() { @@ -317,18 +432,63 @@ public void execute() throws Throwable { public void execute() throws Throwable { try { CCJSqlParserUtil.parse(sqlStr, parser -> { + parser.withTimeOut(60000); + parser.withAllowComplexParsing(false); + }); + } catch (JSQLParserException ex) { + assertFalse(ex.getCause() instanceof TimeoutException); + throw ex; + } + } + }); + } + + // Supposed to time out + @Test + void testComplexIssue1792() throws JSQLParserException { + ExecutorService executorService = Executors.newCachedThreadPool(); + CCJSqlParserUtil.LOGGER.setLevel(Level.ALL); + + // Expect to fail fast with SIMPLE Parsing only when COMPLEX is not allowed + // No TIMEOUT Exception shall be thrown + // CCJSqlParserUtil.LOGGER will report: + // 1) Allowed Complex Parsing: false + // 2) Trying SIMPLE parsing only + assertThrows(JSQLParserException.class, new Executable() { + @Override + public void execute() throws Throwable { + try { + CCJSqlParserUtil.parse(INVALID_SQL, executorService, parser -> { parser.withTimeOut(10000); parser.withAllowComplexParsing(false); }); } catch (JSQLParserException ex) { - Throwable cause = ((JSQLParserException) ex).getCause(); - if (cause instanceof TimeoutException) { - throw cause; - } else { - throw ex; - } + assertFalse(ex.getCause() instanceof TimeoutException); + throw ex; + } + } + }); + + // Expect to time-out with COMPLEX Parsing allowed + // CCJSqlParserUtil.LOGGER will report: + // 1) Allowed Complex Parsing: true + // 2) Trying SIMPLE parsing first + // 3) Trying COMPLEX parsing when SIMPLE parsing failed + assertThrows(JSQLParserException.class, new Executable() { + @Override + public void execute() throws Throwable { + try { + CCJSqlParserUtil.parse(INVALID_SQL, executorService, parser -> { + parser.withTimeOut(1000); + parser.withAllowComplexParsing(true); + }); + } catch (JSQLParserException ex) { + assertTrue(ex.getCause() instanceof TimeoutException); + throw ex; } } }); + executorService.shutdownNow(); + CCJSqlParserUtil.LOGGER.setLevel(Level.OFF); } } diff --git a/src/test/java/net/sf/jsqlparser/parser/feature/FeatureConfigurationTest.java b/src/test/java/net/sf/jsqlparser/parser/feature/FeatureConfigurationTest.java index bdb933c09..3879d1e57 100644 --- a/src/test/java/net/sf/jsqlparser/parser/feature/FeatureConfigurationTest.java +++ b/src/test/java/net/sf/jsqlparser/parser/feature/FeatureConfigurationTest.java @@ -1,9 +1,18 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ package net.sf.jsqlparser.parser.feature; -import static org.assertj.core.api.Assertions.assertThat; - import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + public class FeatureConfigurationTest { @Test public void getAsLong() { diff --git a/src/test/java/net/sf/jsqlparser/statement/ReferentialActionTest.java b/src/test/java/net/sf/jsqlparser/statement/ReferentialActionTest.java new file mode 100644 index 000000000..96f73c558 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/statement/ReferentialActionTest.java @@ -0,0 +1,30 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +class ReferentialActionTest { + + @Test + void testCaseSensitivity() throws JSQLParserException { + String sqlStr = "CREATE TABLE DATABASES\n" + + "(\n" + + "NAME VARCHAR(50) NOT NULL,\n" + + "OWNER VARCHAR(50) NOT NULL,\n" + + "PRIMARY KEY (NAME),\n" + + "FOREIGN KEY(OWNER) REFERENCES USERS (USERNAME) ON delete cascade\n" + + ")"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + +} diff --git a/src/test/java/net/sf/jsqlparser/statement/ReturningClauseTest.java b/src/test/java/net/sf/jsqlparser/statement/ReturningClauseTest.java new file mode 100644 index 000000000..331f7263b --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/statement/ReturningClauseTest.java @@ -0,0 +1,28 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +class ReturningClauseTest { + @Test + void returnIntoTest() throws JSQLParserException { + String sqlStr = " insert into emp\n" + + " (empno, ename)\n" + + " values\n" + + " (seq_emp.nextval, 'morgan')\n" + + " returning empno\n" + + " into x"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + +} diff --git a/src/test/java/net/sf/jsqlparser/statement/SetStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/SetStatementTest.java index 9fe5639d7..3089d3ef1 100644 --- a/src/test/java/net/sf/jsqlparser/statement/SetStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/SetStatementTest.java @@ -9,15 +9,15 @@ */ package net.sf.jsqlparser.statement; -import java.util.*; - import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.StringValue; -import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; -import static org.junit.jupiter.api.Assertions.*; - +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import org.junit.jupiter.api.Test; +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + /** * * @author toben @@ -67,14 +67,14 @@ public void testValueOnIssue927() throws JSQLParserException { @Test public void testObject() { SetStatement setStatement = new SetStatement(); - setStatement.add("standard_conforming_strings", - Collections.singletonList(new StringValue("ON")), false); + setStatement.add("standard_conforming_strings", new ExpressionList(new StringValue("ON")), + false); setStatement.withUseEqual(0, true).remove(0); assertEquals(0, setStatement.getCount()); setStatement.addKeyValuePairs( - new SetStatement.NameExpr("test", Arrays.asList(new StringValue("1")), false)); + new SetStatement.NameExpr("test", new ExpressionList(new StringValue("1")), false)); setStatement.getKeyValuePairs().get(0).setUseEqual(true); assertEquals("test", setStatement.getKeyValuePairs().get(0).getName()); @@ -93,4 +93,10 @@ public void testSettingUserVariable() throws JSQLParserException { sqlStr = "SET @@global.time_zone = '01:00'"; assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + public void testMultiPartVariables() throws JSQLParserException { + String sqlStr = "set a.b.c=false"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/ShowStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/ShowStatementTest.java index d8c4f9cf5..7f1033896 100644 --- a/src/test/java/net/sf/jsqlparser/statement/ShowStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/ShowStatementTest.java @@ -10,9 +10,11 @@ package net.sf.jsqlparser.statement; import net.sf.jsqlparser.JSQLParserException; -import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; + /** * * @author oshai @@ -28,4 +30,19 @@ public void testSimpleUse() throws JSQLParserException { public void testSimpleUse2() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("SHOW transaction_isolation"); } + + @Test + void testShowIndexesFromTable() throws JSQLParserException { + String sqlStr = + "show indexes from my_table"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testShowCreateTable() throws JSQLParserException { + String sqlStr = + "show create table my_table"; + Statement statement = assertSqlCanBeParsedAndDeparsed(sqlStr, true); + Assertions.assertTrue(statement instanceof UnsupportedStatement); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/UnsupportedStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/UnsupportedStatementTest.java index 9a5f515df..1a7238b6b 100644 --- a/src/test/java/net/sf/jsqlparser/statement/UnsupportedStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/UnsupportedStatementTest.java @@ -12,23 +12,26 @@ import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; -import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; public class UnsupportedStatementTest { @Test public void testSingleUnsupportedStatement() throws JSQLParserException { String sqlStr = "this is an unsupported statement"; - assertSqlCanBeParsedAndDeparsed(sqlStr, true, parser -> parser.withUnsupportedStatements(true) ); + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true, + parser -> parser.withUnsupportedStatements(true)); Assertions.assertThrowsExactly(JSQLParserException.class, new Executable() { @Override public void execute() throws Throwable { - CCJSqlParserUtil.parse(sqlStr, parser -> parser.withUnsupportedStatements(false) ); + CCJSqlParserUtil.parse(sqlStr, parser -> parser.withUnsupportedStatements(false)); } }); } @@ -37,7 +40,8 @@ public void execute() throws Throwable { public void testUnsupportedStatementsFirstInBlock() throws JSQLParserException { String sqlStr = "This is an unsupported statement; Select * from dual; Select * from dual;"; - Statements statements = CCJSqlParserUtil.parseStatements(sqlStr, parser -> parser.withUnsupportedStatements(true)); + Statements statements = CCJSqlParserUtil.parseStatements(sqlStr, + parser -> parser.withUnsupportedStatements(true)); Assertions.assertEquals(3, statements.getStatements().size()); Assertions.assertInstanceOf(UnsupportedStatement.class, statements.getStatements().get(0)); Assertions.assertInstanceOf(Select.class, statements.getStatements().get(1)); @@ -46,7 +50,8 @@ public void testUnsupportedStatementsFirstInBlock() throws JSQLParserException { Assertions.assertThrowsExactly(JSQLParserException.class, new Executable() { @Override public void execute() throws Throwable { - CCJSqlParserUtil.parseStatements(sqlStr, parser -> parser.withUnsupportedStatements(false) ); + CCJSqlParserUtil.parseStatements(sqlStr, + parser -> parser.withUnsupportedStatements(false)); } }); } @@ -55,21 +60,65 @@ public void execute() throws Throwable { public void testUnsupportedStatementsMiddleInBlock() throws JSQLParserException { String sqlStr = "Select * from dual; This is an unsupported statement; Select * from dual;"; - Statements statements = CCJSqlParserUtil.parseStatements(sqlStr, parser -> parser.withUnsupportedStatements(true)); + Statements statements = CCJSqlParserUtil.parseStatements(sqlStr, + parser -> parser.withUnsupportedStatements(true)); Assertions.assertEquals(3, statements.getStatements().size()); Assertions.assertInstanceOf(Select.class, statements.getStatements().get(0)); Assertions.assertInstanceOf(UnsupportedStatement.class, statements.getStatements().get(1)); Assertions.assertInstanceOf(Select.class, statements.getStatements().get(2)); -// This will not fail, but always return the Unsupported Statements -// Since we can't LOOKAHEAD in the Statements() production + // This will not fail, but always return the Unsupported Statements + // Since we can't LOOKAHEAD in the Statements() production -// Assertions.assertThrowsExactly(JSQLParserException.class, new Executable() { -// @Override -// public void execute() throws Throwable { -// CCJSqlParserUtil.parseStatements(sqlStr, parser -> parser.withUnsupportedStatements(false) ); -// } -// }); + // Assertions.assertThrowsExactly(JSQLParserException.class, new Executable() { + // @Override + // public void execute() throws Throwable { + // CCJSqlParserUtil.parseStatements(sqlStr, parser -> + // parser.withUnsupportedStatements(false) ); + // } + // }); + } + + @Test + void testAlter() throws JSQLParserException { + String sqlStr = + "ALTER INDEX idx_t_fa RENAME TO idx_t_fb"; + Statement statement = TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + assertTrue(statement instanceof UnsupportedStatement); + } + + @Test + void testCreate() throws JSQLParserException { + String sqlStr = + "create trigger stud_marks before INSERT on Student for each row set Student.total = Student.subj1 + Student.subj2, Student.per = Student.total * 60 / 100"; + Statement statement = TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + assertTrue(statement instanceof UnsupportedStatement); + + sqlStr = + "create domain TNOTIFICATION_ACTION as ENUM ('ADD', 'CHANGE', 'DEL')"; + statement = TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + assertTrue(statement instanceof UnsupportedStatement); + } + + @Test + void testFunctions() throws JSQLParserException { + String sqlStr = + "CREATE OR REPLACE FUNCTION func_example(foo integer)\n" + + "RETURNS integer AS $$\n" + + "BEGIN\n" + + " RETURN foo + 1;\n" + + "END\n" + + "$$ LANGUAGE plpgsql;\n" + + "\n" + + "CREATE OR REPLACE FUNCTION func_example2(IN foo integer, OUT bar integer)\n" + + "AS $$\n" + + "BEGIN\n" + + " SELECT foo + 1 INTO bar;\n" + + "END\n" + + "$$ LANGUAGE plpgsql;"; + + Statements statements = CCJSqlParserUtil.parseStatements(sqlStr); + assertEquals(2, statements.size()); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/builder/JSQLParserFluentModelTests.java b/src/test/java/net/sf/jsqlparser/statement/builder/JSQLParserFluentModelTests.java index 8b4a05bda..19257ff75 100644 --- a/src/test/java/net/sf/jsqlparser/statement/builder/JSQLParserFluentModelTests.java +++ b/src/test/java/net/sf/jsqlparser/statement/builder/JSQLParserFluentModelTests.java @@ -11,7 +11,6 @@ import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Alias; -import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.JdbcParameter; import net.sf.jsqlparser.expression.Parenthesis; import net.sf.jsqlparser.expression.StringValue; @@ -19,8 +18,8 @@ import net.sf.jsqlparser.expression.operators.conditional.OrExpression; import net.sf.jsqlparser.expression.operators.conditional.XorExpression; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.InExpression; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.Statement; @@ -30,8 +29,6 @@ import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Test; -import java.util.List; - import static net.sf.jsqlparser.test.TestUtils.asList; import static net.sf.jsqlparser.test.TestUtils.assertDeparse; import static net.sf.jsqlparser.test.TestUtils.assertEqualsObjectTree; @@ -60,7 +57,8 @@ public void testParseAndBuild() throws JSQLParserException { .withRightExpression( new InExpression() .withLeftExpression(new Column(asList("t1", "col3"))) - .withRightItemsList(new ExpressionList(new StringValue("A")))); + .withRightExpression( + new ParenthesedExpressionList(new StringValue("A")))); PlainSelect select = new PlainSelect().addSelectItems(new AllColumns()).withFromItem(t1) .addJoins(new Join().withRightItem(t2) @@ -69,13 +67,8 @@ public void testParseAndBuild() throws JSQLParserException { new Column(asList("t2", "id"))))) .withWhere(where); - ExpressionList list = select.getWhere(AndExpression.class) - .getRightExpression(InExpression.class).getRightItemsList(ExpressionList.class); - List elist = list.getExpressions(); - list.setExpressions(elist); assertDeparse(select, statement); - assertEqualsObjectTree(parsed, select); } @Test @@ -100,8 +93,9 @@ public void testParseAndBuildForXOR() throws JSQLParserException { .withRightExpression( new InExpression() .withLeftExpression(new Column(asList("t1", "col3"))) - .withRightItemsList(new ExpressionList(new StringValue("B"), - new StringValue("C"))))) + .withRightExpression( + new ParenthesedExpressionList(new StringValue("B"), + new StringValue("C"))))) .withRightExpression(new Column(asList("t2", "col4"))); PlainSelect select = new PlainSelect().addSelectItems(new AllColumns()).withFromItem(t1) @@ -111,15 +105,7 @@ public void testParseAndBuildForXOR() throws JSQLParserException { new Column(asList("t2", "id"))))) .withWhere(where); - ExpressionList list = select.getWhere(XorExpression.class) - .getLeftExpression(AndExpression.class) - .getRightExpression(InExpression.class) - .getRightItemsList(ExpressionList.class); - List elist = list.getExpressions(); - list.setExpressions(elist); - assertDeparse(select, statement); - assertEqualsObjectTree(parsed, select); } @Test diff --git a/src/test/java/net/sf/jsqlparser/statement/builder/ReflectionModelTest.java b/src/test/java/net/sf/jsqlparser/statement/builder/ReflectionModelTest.java index 265528767..55726a9f6 100644 --- a/src/test/java/net/sf/jsqlparser/statement/builder/ReflectionModelTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/builder/ReflectionModelTest.java @@ -15,9 +15,11 @@ import net.sf.jsqlparser.statement.ExplainStatement.OptionType; import net.sf.jsqlparser.statement.create.table.ColDataType; import net.sf.jsqlparser.statement.select.ParenthesedSelect; +import net.sf.jsqlparser.statement.update.UpdateSet; import net.sf.jsqlparser.util.ReflectionTestUtils; import org.junit.jupiter.api.Test; +import java.util.ArrayList; import java.util.List; import static net.sf.jsqlparser.test.TestUtils.asList; @@ -71,7 +73,7 @@ public class ReflectionModelTest { new net.sf.jsqlparser.expression.OrderByClause(), new net.sf.jsqlparser.expression.Parenthesis(), new net.sf.jsqlparser.expression.PartitionByClause(), - new net.sf.jsqlparser.expression.RowConstructor(), + // new net.sf.jsqlparser.expression.RowConstructor<>("ROW", new ExpressionList<>()), new net.sf.jsqlparser.expression.SQLServerHints(), new net.sf.jsqlparser.expression.SignedExpression(), new net.sf.jsqlparser.expression.StringValue(), @@ -79,7 +81,6 @@ public class ReflectionModelTest { new net.sf.jsqlparser.expression.TimeValue(), new net.sf.jsqlparser.expression.TimestampValue(), new net.sf.jsqlparser.expression.UserVariable(), - new net.sf.jsqlparser.expression.ValueListExpression(), new net.sf.jsqlparser.expression.WhenClause(), new net.sf.jsqlparser.expression.WindowElement(), new net.sf.jsqlparser.expression.WindowOffset(), @@ -102,7 +103,7 @@ public class ReflectionModelTest { new net.sf.jsqlparser.expression.operators.relational.Between(), new net.sf.jsqlparser.expression.operators.relational.EqualsTo(), new net.sf.jsqlparser.expression.operators.relational.ExistsExpression(), - new net.sf.jsqlparser.expression.operators.relational.ExpressionList(), + new net.sf.jsqlparser.expression.operators.relational.ExpressionList<>(), new net.sf.jsqlparser.expression.operators.relational.FullTextSearch(), new net.sf.jsqlparser.expression.operators.relational.GreaterThan(), new net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals(), @@ -114,8 +115,6 @@ public class ReflectionModelTest { new net.sf.jsqlparser.expression.operators.relational.Matches(), new net.sf.jsqlparser.expression.operators.relational.MinorThan(), new net.sf.jsqlparser.expression.operators.relational.MinorThanEquals(), - new net.sf.jsqlparser.expression.operators.relational.MultiExpressionList(), - new net.sf.jsqlparser.expression.operators.relational.NamedExpressionList(), new net.sf.jsqlparser.expression.operators.relational.NotEqualsTo(), new net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator( RegExpMatchOperatorType.MATCH_CASEINSENSITIVE), @@ -170,15 +169,13 @@ public class ReflectionModelTest { new net.sf.jsqlparser.statement.grant.Grant(), new net.sf.jsqlparser.statement.insert.Insert(), new net.sf.jsqlparser.statement.merge.Merge(), - new net.sf.jsqlparser.statement.merge.MergeUpdate(), + new net.sf.jsqlparser.statement.merge.MergeUpdate(new ArrayList()), new net.sf.jsqlparser.statement.select.AllColumns(), new net.sf.jsqlparser.statement.select.AllTableColumns(), new net.sf.jsqlparser.statement.select.Distinct(), new net.sf.jsqlparser.statement.select.ExceptOp(), - new net.sf.jsqlparser.statement.select.ExpressionListItem(), new net.sf.jsqlparser.statement.select.Fetch(), new net.sf.jsqlparser.statement.select.First(), - new net.sf.jsqlparser.statement.select.FunctionItem(), new net.sf.jsqlparser.statement.select.GroupByElement(), new net.sf.jsqlparser.statement.select.IntersectOp(), new net.sf.jsqlparser.statement.select.Join(), @@ -195,7 +192,7 @@ public class ReflectionModelTest { new net.sf.jsqlparser.statement.select.PivotXml(), // new net.sf.jsqlparser.statement.select.PlainSelect(), // new net.sf.jsqlparser.statement.select.Select(), - new net.sf.jsqlparser.statement.select.SelectExpressionItem(), + new net.sf.jsqlparser.statement.select.SelectItem(), // new net.sf.jsqlparser.statement.select.SetOperationList(), new net.sf.jsqlparser.statement.select.Skip(), // new net.sf.jsqlparser.statement.select.ParenthesedSelect(), diff --git a/src/test/java/net/sf/jsqlparser/statement/create/AlterViewTest.java b/src/test/java/net/sf/jsqlparser/statement/create/AlterViewTest.java index f2c21b83a..20aa4b4bf 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/AlterViewTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/AlterViewTest.java @@ -9,7 +9,6 @@ */ package net.sf.jsqlparser.statement.create; -import java.util.Collections; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; @@ -17,12 +16,14 @@ import net.sf.jsqlparser.statement.create.view.AlterView; import net.sf.jsqlparser.statement.select.AllColumns; import net.sf.jsqlparser.statement.select.PlainSelect; -import net.sf.jsqlparser.statement.select.SelectExpressionItem; +import org.junit.jupiter.api.Test; + +import java.util.Collections; + import static net.sf.jsqlparser.test.TestUtils.assertDeparse; import static net.sf.jsqlparser.test.TestUtils.assertEqualsObjectTree; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; public class AlterViewTest { @@ -32,7 +33,7 @@ public void testAlterView() throws JSQLParserException { Statement parsed = assertSqlCanBeParsedAndDeparsed(statement); AlterView created = new AlterView().withView(new Table("myview")) .withSelect(new PlainSelect() - .addSelectItems(Collections.singleton(new AllColumns())) + .addSelectItem(new AllColumns()) .withFromItem(new Table("mytab"))); assertDeparse(created, statement); assertEqualsObjectTree(parsed, created); @@ -46,8 +47,8 @@ public void testReplaceView() throws JSQLParserException { .addColumnNames(Collections.singleton("b")) .withView(new Table("myview")) .withSelect(new PlainSelect() - .addSelectItems(new SelectExpressionItem(new Column("a")), - new SelectExpressionItem(new Column("b"))) + .addSelectItems(new Column("a"), + new Column("b")) .withFromItem(new Table("mytab"))); assertTrue(alterView.getSelectBody(PlainSelect.class) instanceof PlainSelect); assertDeparse(alterView, statement); 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 5ee5f9dbe..fd5b8d3c0 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java @@ -9,14 +9,6 @@ */ package net.sf.jsqlparser.statement.create; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.StringTokenizer; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.operators.relational.GreaterThan; @@ -31,14 +23,24 @@ import net.sf.jsqlparser.statement.create.table.Index; import net.sf.jsqlparser.statement.create.table.RowMovementMode; import net.sf.jsqlparser.test.TestException; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.StringTokenizer; + import static net.sf.jsqlparser.test.TestUtils.assertDeparse; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; -import org.assertj.core.api.Assertions; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; public class CreateTableTest { @@ -71,16 +73,16 @@ public void testCreateTableAsSelect() @Test public void testCreateTableAsSelect2() throws JSQLParserException { - String statement - = "CREATE TABLE newtable AS WITH a AS (SELECT col1, col3 FROM testtable) SELECT col1, col2, col3 FROM b INNER JOIN a ON b.col1 = a.col1"; + String statement = + "CREATE TABLE newtable AS WITH a AS (SELECT col1, col3 FROM testtable) SELECT col1, col2, col3 FROM b INNER JOIN a ON b.col1 = a.col1"; assertSqlCanBeParsedAndDeparsed(statement); } @Test public void testCreateTable() throws JSQLParserException { - String statement - = "CREATE TABLE mytab (mycol a (10, 20) c nm g, mycol2 mypar1 mypar2 (23,323,3) asdf ('23','123') dasd, " - + "PRIMARY KEY (mycol2, mycol)) type = myisam"; + String statement = + "CREATE TABLE mytab (mycol a (10, 20) c nm g, mycol2 mypar1 mypar2 (23,323,3) asdf ('23','123') dasd, " + + "PRIMARY KEY (mycol2, mycol)) type = myisam"; CreateTable createTable = (CreateTable) parserManager.parse(new StringReader(statement)); assertEquals(2, createTable.getColumnDefinitions().size()); assertFalse(createTable.isUnlogged()); @@ -93,9 +95,9 @@ public void testCreateTable() throws JSQLParserException { @Test public void testCreateTableUnlogged() throws JSQLParserException { - String statement - = "CREATE UNLOGGED TABLE mytab (mycol a (10, 20) c nm g, mycol2 mypar1 mypar2 (23,323,3) asdf ('23','123') dasd, " - + "PRIMARY KEY (mycol2, mycol)) type = myisam"; + String statement = + "CREATE UNLOGGED TABLE mytab (mycol a (10, 20) c nm g, mycol2 mypar1 mypar2 (23,323,3) asdf ('23','123') dasd, " + + "PRIMARY KEY (mycol2, mycol)) type = myisam"; CreateTable createTable = (CreateTable) parserManager.parse(new StringReader(statement)); assertEquals(2, createTable.getColumnDefinitions().size()); assertTrue(createTable.isUnlogged()); @@ -108,43 +110,43 @@ public void testCreateTableUnlogged() throws JSQLParserException { @Test public void testCreateTableUnlogged2() throws JSQLParserException { - String statement - = "CREATE UNLOGGED TABLE mytab (mycol a (10, 20) c nm g, mycol2 mypar1 mypar2 (23,323,3) asdf ('23','123') dasd, PRIMARY KEY (mycol2, mycol))"; + String statement = + "CREATE UNLOGGED TABLE mytab (mycol a (10, 20) c nm g, mycol2 mypar1 mypar2 (23,323,3) asdf ('23','123') dasd, PRIMARY KEY (mycol2, mycol))"; assertSqlCanBeParsedAndDeparsed(statement); } @Test public void testCreateTableForeignKey() throws JSQLParserException { - String statement - = "CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, string VARCHAR (20), user_id INT UNSIGNED, PRIMARY KEY (id), FOREIGN KEY (user_id) REFERENCES ra_user(id))"; + String statement = + "CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, string VARCHAR (20), user_id INT UNSIGNED, PRIMARY KEY (id), FOREIGN KEY (user_id) REFERENCES ra_user(id))"; assertSqlCanBeParsedAndDeparsed(statement); } @Test public void testCreateTableForeignKey2() throws JSQLParserException { - String statement - = "CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, string VARCHAR (20), user_id INT UNSIGNED, PRIMARY KEY (id), CONSTRAINT fkIdx FOREIGN KEY (user_id) REFERENCES ra_user(id))"; + String statement = + "CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, string VARCHAR (20), user_id INT UNSIGNED, PRIMARY KEY (id), CONSTRAINT fkIdx FOREIGN KEY (user_id) REFERENCES ra_user(id))"; assertSqlCanBeParsedAndDeparsed(statement); } @Test public void testCreateTableForeignKey3() throws JSQLParserException { - String statement - = "CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, string VARCHAR (20), user_id INT UNSIGNED REFERENCES ra_user(id), PRIMARY KEY (id))"; + String statement = + "CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, string VARCHAR (20), user_id INT UNSIGNED REFERENCES ra_user(id), PRIMARY KEY (id))"; assertSqlCanBeParsedAndDeparsed(statement, true); } @Test public void testCreateTableForeignKey4() throws JSQLParserException { - String statement - = "CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, string VARCHAR (20), user_id INT UNSIGNED FOREIGN KEY REFERENCES ra_user(id), PRIMARY KEY (id))"; + String statement = + "CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, string VARCHAR (20), user_id INT UNSIGNED FOREIGN KEY REFERENCES ra_user(id), PRIMARY KEY (id))"; assertSqlCanBeParsedAndDeparsed(statement, true); } @Test public void testCreateTablePrimaryKey() throws JSQLParserException { - String statement - = "CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, string VARCHAR (20), user_id INT UNSIGNED, CONSTRAINT pk_name PRIMARY KEY (id))"; + String statement = + "CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, string VARCHAR (20), user_id INT UNSIGNED, CONSTRAINT pk_name PRIMARY KEY (id))"; assertSqlCanBeParsedAndDeparsed(statement); } @@ -162,20 +164,30 @@ public void testCreateTableParams2() throws JSQLParserException { @Test public void testCreateTableUniqueConstraint() throws JSQLParserException { - String sqlStr - = "CREATE TABLE Activities (_id INTEGER PRIMARY KEY AUTOINCREMENT,uuid VARCHAR(255),user_id INTEGER,sound_id INTEGER,sound_type INTEGER,comment_id INTEGER,type String,tags VARCHAR(255),created_at INTEGER,content_id INTEGER,sharing_note_text VARCHAR(255),sharing_note_created_at INTEGER,UNIQUE (created_at, type, content_id, sound_id, user_id))"; + String sqlStr = + "CREATE TABLE Activities (" + + "_id INTEGER PRIMARY KEY AUTOINCREMENT" + + ",uuid VARCHAR(255)" + + ",user_id INTEGER" + + ",sound_id INTEGER" + + ",sound_type INTEGER" + + ",comment_id INTEGER" + + ",type String,tags VARCHAR(255)" + + ",created_at INTEGER" + + ",content_id INTEGER" + + ",sharing_note_text VARCHAR(255)" + + ",sharing_note_created_at INTEGER" + + ",UNIQUE (created_at, type, content_id, sound_id, user_id)" + + ")"; assertSqlCanBeParsedAndDeparsed(sqlStr, true); - - CreateTable createTable - = (CreateTable) CCJSqlParserUtil.parseStatements(sqlStr).getStatements().get(0); - + assertTrue(CCJSqlParserUtil.parseStatements(sqlStr).getStatements() + .get(0) instanceof CreateTable); } @Test public void testCreateTableUniqueConstraintAfterPrimaryKey() throws JSQLParserException { - String sqlStr - = "-- UniqueConstraintAfterPrimaryKey\n" + String sqlStr = "-- UniqueConstraintAfterPrimaryKey\n" + "CREATE TABLE employees (\n" + " employee_number int NOT NULL\n" + " , employee_name char (50) NOT NULL\n" @@ -189,8 +201,8 @@ public void testCreateTableUniqueConstraintAfterPrimaryKey() throws JSQLParserEx assertSqlCanBeParsedAndDeparsed(sqlStr, true); - CreateTable createTable - = (CreateTable) CCJSqlParserUtil.parseStatements(sqlStr).getStatements().get(0); + CreateTable createTable = + (CreateTable) CCJSqlParserUtil.parseStatements(sqlStr).getStatements().get(0); assertEquals("PRIMARY KEY", createTable.getIndexes().get(0).getType()); assertEquals("UNIQUE", createTable.getIndexes().get(1).getType()); @@ -356,7 +368,8 @@ public void testCreateTableIssue270_1() throws JSQLParserException { @Test public void testCreateTempTableIssue293() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("CREATE GLOBAL TEMPORARY TABLE T1 (PROCESSID VARCHAR (32))"); + assertSqlCanBeParsedAndDeparsed( + "CREATE GLOBAL TEMPORARY TABLE T1 (PROCESSID VARCHAR (32))"); } @Test @@ -384,12 +397,14 @@ public void testColumnCheck() throws JSQLParserException { @Test public void testTableReferenceWithSchema() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("CREATE TABLE table1 (col1 INTEGER REFERENCES schema1.table1)"); + assertSqlCanBeParsedAndDeparsed( + "CREATE TABLE table1 (col1 INTEGER REFERENCES schema1.table1)"); } @Test public void testNamedColumnConstraint() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("CREATE TABLE foo (col1 integer CONSTRAINT no_null NOT NULL)"); + assertSqlCanBeParsedAndDeparsed( + "CREATE TABLE foo (col1 integer CONSTRAINT no_null NOT NULL)"); } @Test @@ -410,7 +425,8 @@ public void testExcludeWhereConstraint() throws JSQLParserException { new GreaterThan() .withLeftExpression(new Column("col1")) .withRightExpression(new LongValue(100)))) - .addColumnDefinitions(new ColumnDefinition("col1", new ColDataType("integer"))), + .addColumnDefinitions( + new ColumnDefinition("col1", new ColDataType("integer"))), statement); } @@ -423,7 +439,8 @@ public void testTimestampWithoutTimezone() throws JSQLParserException { .withTable(new Table(Arrays.asList("abc", "tabc"))) .addColumnDefinitions( new ColumnDefinition( - "transaction_date", new ColDataType("TIMESTAMP WITHOUT TIME ZONE"))), + "transaction_date", + new ColDataType("TIMESTAMP WITHOUT TIME ZONE"))), statement); } @@ -449,16 +466,17 @@ public void testCreateUnionIssue() throws JSQLParserException { public void testTimestampWithTimezone() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( "CREATE TABLE country_region (" - + "regionid BIGINT NOT NULL CONSTRAINT pk_auth_region PRIMARY KEY, " - + "region_name VARCHAR (100) NOT NULL, " - + "creation_date TIMESTAMP (0) WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP (0) NOT NULL, " - + "last_change_date TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP (0), " - + "CONSTRAINT region_name_unique UNIQUE (region_name))"); + + "regionid BIGINT NOT NULL CONSTRAINT pk_auth_region PRIMARY KEY, " + + "region_name VARCHAR (100) NOT NULL, " + + "creation_date TIMESTAMP (0) WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP (0) NOT NULL, " + + "last_change_date TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP (0), " + + "CONSTRAINT region_name_unique UNIQUE (region_name))"); } @Test public void testCreateTableAsSelect3() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("CREATE TABLE public.sales1 AS (SELECT * FROM public.sales)"); + assertSqlCanBeParsedAndDeparsed( + "CREATE TABLE public.sales1 AS (SELECT * FROM public.sales)"); } @Test @@ -506,10 +524,9 @@ public void testIssue770Using() throws JSQLParserException { @Test public void testRUBiSCreateList() throws Exception { - BufferedReader in - = new BufferedReader( - new InputStreamReader( - CreateTableTest.class.getResourceAsStream("/RUBiS-create-requests.txt"))); + BufferedReader in = new BufferedReader( + new InputStreamReader( + CreateTableTest.class.getResourceAsStream("/RUBiS-create-requests.txt"))); try { int numSt = 1; @@ -541,7 +558,8 @@ public void testRUBiSCreateList() throws Exception { String tableName = getLine(in); String cols = getLine(in); try { - CreateTable createTable = (CreateTable) parserManager.parse(new StringReader(query)); + CreateTable createTable = + (CreateTable) parserManager.parse(new StringReader(query)); String[] colsList = null; if ("null".equals(cols)) { colsList = new String[0]; @@ -557,7 +575,8 @@ public void testRUBiSCreateList() throws Exception { } List colsFound = new ArrayList<>(); if (createTable.getColumnDefinitions() != null) { - for (ColumnDefinition columnDefinition : createTable.getColumnDefinitions()) { + for (ColumnDefinition columnDefinition : createTable + .getColumnDefinitions()) { String colName = columnDefinition.getColumnName(); boolean unique = false; if (createTable.getIndexes() != null) { @@ -572,8 +591,9 @@ public void testRUBiSCreateList() throws Exception { if (!unique) { if (columnDefinition.getColumnSpecs() != null) { - for (Iterator iterator = columnDefinition.getColumnSpecs().iterator(); - iterator.hasNext();) { + for (Iterator iterator = + columnDefinition.getColumnSpecs().iterator(); iterator + .hasNext();) { String par = iterator.next(); if (par.equals("UNIQUE")) { unique = true; @@ -616,7 +636,8 @@ private String getLine(BufferedReader in) throws Exception { if (line != null) { if (line.length() != 0 && (line.length() < 2 - || line.length() >= 2 && !(line.charAt(0) == '/' && line.charAt(1) == '/'))) { + || line.length() >= 2 + && !(line.charAt(0) == '/' && line.charAt(1) == '/'))) { break; } } else { @@ -649,36 +670,36 @@ public void testCreateTableIssue798() throws JSQLParserException { public void testCreateTableIssue798_2() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( "CREATE TABLE parent (\n" - + "PARENT_ID int(11) NOT NULL AUTO_INCREMENT,\n" - + "PCN varchar(100) NOT NULL,\n" - + "IS_DELETED char(1) NOT NULL,\n" - + "STRUCTURE_ID int(11) NOT NULL,\n" - + "DIRTY_STATUS char(1) NOT NULL,\n" - + "BIOLOGICAL char(1) NOT NULL,\n" - + "STRUCTURE_TYPE int(11) NOT NULL,\n" - + "CST_ORIGINAL varchar(1000) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,\n" - + "MWT decimal(14,6) DEFAULT NULL,\n" - + "RESTRICTED int(11) NOT NULL,\n" - + "INIT_DATE datetime DEFAULT NULL,\n" - + "MOD_DATE datetime DEFAULT NULL,\n" - + "CREATED_BY varchar(255) NOT NULL,\n" - + "MODIFIED_BY varchar(255) NOT NULL,\n" - + "CHEMIST_ID varchar(255) NOT NULL,\n" - + "UNKNOWN_ID int(11) DEFAULT NULL,\n" - + "STEREOCHEMISTRY varchar(256) DEFAULT NULL,\n" - + "GEOMETRIC_ISOMERISM varchar(256) DEFAULT NULL,\n" - + "PRIMARY KEY (PARENT_ID),\n" - + "UNIQUE KEY PARENT_PCN_IDX (PCN),\n" - + "KEY PARENT_SID_IDX (STRUCTURE_ID),\n" - + "KEY PARENT_DIRTY_IDX (DIRTY_STATUS)\n" - + ") ENGINE=InnoDB AUTO_INCREMENT=2663 DEFAULT CHARSET=utf8", + + "PARENT_ID int(11) NOT NULL AUTO_INCREMENT,\n" + + "PCN varchar(100) NOT NULL,\n" + + "IS_DELETED char(1) NOT NULL,\n" + + "STRUCTURE_ID int(11) NOT NULL,\n" + + "DIRTY_STATUS char(1) NOT NULL,\n" + + "BIOLOGICAL char(1) NOT NULL,\n" + + "STRUCTURE_TYPE int(11) NOT NULL,\n" + + "CST_ORIGINAL varchar(1000) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,\n" + + "MWT decimal(14,6) DEFAULT NULL,\n" + + "RESTRICTED int(11) NOT NULL,\n" + + "INIT_DATE datetime DEFAULT NULL,\n" + + "MOD_DATE datetime DEFAULT NULL,\n" + + "CREATED_BY varchar(255) NOT NULL,\n" + + "MODIFIED_BY varchar(255) NOT NULL,\n" + + "CHEMIST_ID varchar(255) NOT NULL,\n" + + "UNKNOWN_ID int(11) DEFAULT NULL,\n" + + "STEREOCHEMISTRY varchar(256) DEFAULT NULL,\n" + + "GEOMETRIC_ISOMERISM varchar(256) DEFAULT NULL,\n" + + "PRIMARY KEY (PARENT_ID),\n" + + "UNIQUE KEY PARENT_PCN_IDX (PCN),\n" + + "KEY PARENT_SID_IDX (STRUCTURE_ID),\n" + + "KEY PARENT_DIRTY_IDX (DIRTY_STATUS)\n" + + ") ENGINE=InnoDB AUTO_INCREMENT=2663 DEFAULT CHARSET=utf8", true); } @Test public void testCreateTableIssue113() throws JSQLParserException { - String statement - = "CREATE TABLE foo (reason character varying (255) DEFAULT 'Test' :: character varying NOT NULL)"; + String statement = + "CREATE TABLE foo (reason character varying (255) DEFAULT 'Test' :: character varying NOT NULL)"; assertSqlCanBeParsedAndDeparsed(statement); assertDeparse( new CreateTable() @@ -690,8 +711,11 @@ public void testCreateTableIssue113() throws JSQLParserException { .withColDataType( new ColDataType() .withDataType("character varying") - .addArgumentsStringList(Arrays.asList("255"))) - .addColumnSpecs("DEFAULT 'Test' :: character varying", "NOT NULL"))), + .addArgumentsStringList( + Arrays.asList("255"))) + .addColumnSpecs( + "DEFAULT 'Test' :: character varying", + "NOT NULL"))), statement); } @@ -702,21 +726,21 @@ public void testCreateTableIssue830() throws JSQLParserException { @Test public void testCreateTableIssue830_2() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("CREATE TABLE testyesr (id int, yy year, mm month, dd day)"); + assertSqlCanBeParsedAndDeparsed( + "CREATE TABLE testyesr (id int, yy year, mm month, dd day)"); } @Test public void testSettingCharacterSetIssue829() throws JSQLParserException { - String sql - = "CREATE TABLE test (id int (11) NOT NULL, name varchar (64) CHARACTER SET GBK NOT NULL, age int (11) NOT NULL, score decimal (8, 2) DEFAULT NULL, description varchar (64) DEFAULT NULL, creationDate datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id)) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4"; + String sql = + "CREATE TABLE test (id int (11) NOT NULL, name varchar (64) CHARACTER SET GBK NOT NULL, age int (11) NOT NULL, score decimal (8, 2) DEFAULT NULL, description varchar (64) DEFAULT NULL, creationDate datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id)) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4"; assertSqlCanBeParsedAndDeparsed(sql); CreateTable stmt = (CreateTable) CCJSqlParserUtil.parse(sql); - ColumnDefinition colName - = stmt.getColumnDefinitions().stream() - .filter(col -> col.getColumnName().equals("name")) - .findFirst() - .orElse(null); + ColumnDefinition colName = stmt.getColumnDefinitions().stream() + .filter(col -> col.getColumnName().equals("name")) + .findFirst() + .orElse(null); assertNotNull(colName); @@ -745,7 +769,8 @@ public void testCreateTableIssue921() throws JSQLParserException { .addColumnDefinitions( new ColumnDefinition( "c1", - new ColDataType().withDataType("binary").addArgumentsStringList("10"), + new ColDataType().withDataType("binary") + .addArgumentsStringList("10"), null)), statement); } @@ -754,17 +779,17 @@ public void testCreateTableIssue921() throws JSQLParserException { public void testCreateTableWithComments() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( "CREATE TABLE IF NOT EXISTS `eai_applications`(\n" - + " `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'comment',\n" - + " `name` varchar(64) NOT NULL COMMENT 'comment',\n" - + " `logo` varchar(128) DEFAULT NULL COMMENT 'comment',\n" - + " `description` varchar(128) DEFAULT NULL COMMENT 'comment',\n" - + " `type` int(11) NOT NULL COMMENT 'comment',\n" - + " `status` tinyint(2) NOT NULL COMMENT 'comment',\n" - + " `creator_id` bigint(20) NOT NULL COMMENT 'comment',\n" - + " `created_at` datetime NOT NULL COMMENT 'comment',\n" - + " `updated_at` datetime NOT NULL COMMENT 'comment',\n" - + " PRIMARY KEY (`id`)\n" - + ") COMMENT='comment'", + + " `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'comment',\n" + + " `name` varchar(64) NOT NULL COMMENT 'comment',\n" + + " `logo` varchar(128) DEFAULT NULL COMMENT 'comment',\n" + + " `description` varchar(128) DEFAULT NULL COMMENT 'comment',\n" + + " `type` int(11) NOT NULL COMMENT 'comment',\n" + + " `status` tinyint(2) NOT NULL COMMENT 'comment',\n" + + " `creator_id` bigint(20) NOT NULL COMMENT 'comment',\n" + + " `created_at` datetime NOT NULL COMMENT 'comment',\n" + + " `updated_at` datetime NOT NULL COMMENT 'comment',\n" + + " PRIMARY KEY (`id`)\n" + + ") COMMENT='comment'", true); } @@ -772,10 +797,10 @@ public void testCreateTableWithComments() throws JSQLParserException { public void testCreateTableWithCommentIssue922() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( "CREATE TABLE index_with_comment_test (\n" - + "id int(11) NOT NULL,\n" - + "name varchar(60) DEFAULT NULL,\n" - + "KEY name_ind (name) COMMENT 'comment for the name index'\n" - + ") ENGINE=InnoDB DEFAULT CHARSET=utf8", + + "id int(11) NOT NULL,\n" + + "name varchar(60) DEFAULT NULL,\n" + + "KEY name_ind (name) COMMENT 'comment for the name index'\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8", true); } @@ -785,7 +810,8 @@ public void testEnableRowMovementOption() throws JSQLParserException { CreateTable createTable = (CreateTable) CCJSqlParserUtil.parse(sql); Assertions.assertThat(createTable.getRowMovement()).isNotNull(); - Assertions.assertThat(createTable.getRowMovement().getMode()).isEqualTo(RowMovementMode.ENABLE); + Assertions.assertThat(createTable.getRowMovement().getMode()) + .isEqualTo(RowMovementMode.ENABLE); assertSqlCanBeParsedAndDeparsed(sql); } @@ -804,7 +830,8 @@ public void testDisableRowMovementOption() throws JSQLParserException { @Test public void tableMovementWithAS() throws JSQLParserException { - String sql = "CREATE TABLE test (startdate DATE) DISABLE ROW MOVEMENT AS SELECT 1 FROM dual"; + String sql = + "CREATE TABLE test (startdate DATE) DISABLE ROW MOVEMENT AS SELECT 1 FROM dual"; assertSqlCanBeParsedAndDeparsed(sql); } @@ -859,7 +886,8 @@ public void testCreateUnionIssue1309() throws JSQLParserException { @Test public void testCreateTableBinaryIssue1518() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("CREATE TABLE `s` (`a` enum ('a', 'b', 'c') CHARACTER SET binary COLLATE binary)"); + assertSqlCanBeParsedAndDeparsed( + "CREATE TABLE `s` (`a` enum ('a', 'b', 'c') CHARACTER SET binary COLLATE binary)"); } @Test @@ -889,7 +917,8 @@ public void testCreateTableIssue1488() throws JSQLParserException { + "INDEX ucr_index_sim_id(sim_id) USING BTREE,\n" + "INDEX ucr_index_status(status) USING BTREE,\n" + "INDEX ucr_index_talk_time(talk_time) USING BTREE\n" - + ") ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic", true); + + ") ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic", + true); } @Test @@ -910,33 +939,108 @@ public void testCreateTableBinaryIssue1596() throws JSQLParserException { 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); + " 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); + } + + + @Test + void testCreateTableWithStartWithNumber() throws JSQLParserException { + String sqlStr = + "CREATE TABLE locations\n" + + " (\n" + + " location_id NUMBER GENERATED BY DEFAULT AS IDENTITY START WITH 24 \n" + + " PRIMARY KEY ,\n" + + " address VARCHAR2( 255 ) NOT NULL,\n" + + " postal_code VARCHAR2( 20 ) ,\n" + + " city VARCHAR2( 50 ) ,\n" + + " state VARCHAR2( 50 ) ,\n" + + " country_id CHAR( 2 ) , -- fk\n" + + " CONSTRAINT fk_locations_countries \n" + + " FOREIGN KEY( country_id )\n" + + " REFERENCES countries( country_id ) \n" + + " ON DELETE CASCADE\n" + + " )"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + @Test + void testCreateTableWithNextValueFor() throws JSQLParserException { + String sqlStr = + "CREATE TABLE public.actor (\n" + + " actor_id integer DEFAULT nextval('public.actor_actor_id_seq'::regclass) NOT NULL\n" + + ")"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = + " CREATE TABLE myschema.tableName (\n" + + " id bigint NOT NULL DEFAULT nextval('myschema.mysequence'::regclass), \n" + + " bool_col boolean NOT NULL DEFAULT false, \n" + + " int_col integer NOT NULL DEFAULT 0)"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = + " CREATE TABLE t1 (\n" + + " -- literal defaults\n" + + " i INT DEFAULT 0,\n" + + " c VARCHAR(10) DEFAULT '',\n" + + " -- expression defaults\n" + + " f FLOAT DEFAULT (RAND() * RAND()),\n" + + " b BINARY(16) DEFAULT (UUID_TO_BIN(UUID())),\n" + + " d DATE DEFAULT (CURRENT_DATE + INTERVAL 1 YEAR),\n" + + " p POINT DEFAULT (Point(0,0)),\n" + + " j JSON DEFAULT (JSON_ARRAY())\n" + + ")"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = + " CREATE TABLE pagila_dev.actor (\n" + + "actor_id integer DEFAULT nextval('pagila_dev.actor_actor_id_seq'::regclass) NOT NULL,\n" + + "first_name text NOT NULL,\n" + + "last_name text NOT NULL,\n" + + "last_update timestamp with time zone DEFAULT now() NOT NULL\n" + + ")"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = + "CREATE TABLE \"public\".\"device_bayonet_copy1\" ( " + + "\"id\" int8 NOT NULL" + + ", \"device_code\" varchar(128) COLLATE \"pg_catalog\".\"default\"" + + ", \"longitude_latitude\" varchar(128) COLLATE \"pg_catalog\".\"default\"" + + ", \"longitude_latitude_gis\" \"public\".\"geometry\"" + + ", \"direction\" varchar(128) COLLATE \"pg_catalog\".\"default\"" + + ", \"brand\" varchar(128) COLLATE \"pg_catalog\".\"default\"" + + ", \"test\" \"information_schema\".\"time_stamp\"" + + ", CONSTRAINT \"device_bayonet_copy1_pkey\" PRIMARY KEY (\"id\") " + + ")"; + + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java index ba41d8605..d789601b2 100644 --- a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java @@ -16,7 +16,7 @@ import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.StringValue; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; import net.sf.jsqlparser.parser.CCJSqlParserManager; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.schema.Column; @@ -24,14 +24,13 @@ import net.sf.jsqlparser.statement.select.AllColumns; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.update.UpdateSet; import net.sf.jsqlparser.statement.select.Values; +import net.sf.jsqlparser.statement.update.UpdateSet; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; import java.io.StringReader; -import java.util.Arrays; import static net.sf.jsqlparser.test.TestUtils.assertDeparse; import static net.sf.jsqlparser.test.TestUtils.assertOracleHintExists; @@ -40,7 +39,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrowsExactly; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -58,25 +57,23 @@ public void testRegularInsert() throws JSQLParserException { assertEquals("col1", insert.getColumns().get(0).getColumnName()); assertEquals("col2", insert.getColumns().get(1).getColumnName()); assertEquals("col3", insert.getColumns().get(2).getColumnName()); - assertEquals(3, ((ExpressionList) insert.getItemsList()).getExpressions().size()); - assertTrue(((ExpressionList) insert.getItemsList()).getExpressions() - .get(0) instanceof JdbcParameter); - assertEquals("sadfsd", - ((StringValue) ((ExpressionList) insert.getItemsList()).getExpressions().get(1)) - .getValue()); - assertEquals(234, - ((LongValue) ((ExpressionList) insert.getItemsList()).getExpressions().get(2)) - .getValue()); + + Values values = insert.getValues(); + assertEquals(3, values.getExpressions().size()); + assertTrue(values.getExpressions().get(0) instanceof JdbcParameter); + assertEquals("sadfsd", ((StringValue) values.getExpressions().get(1)).getValue()); + assertEquals(234, ((LongValue) values.getExpressions().get(2)).getValue()); assertEquals(statement, insert.toString()); - ExpressionList expressionList = new ExpressionList(new JdbcParameter(), + ExpressionList expressionList = new ParenthesedExpressionList(new JdbcParameter(), new StringValue("sadfsd"), new LongValue().withValue(234)); Select select = new Values().withExpressions(expressionList); Insert insert2 = new Insert().withTable(new Table("mytable")) .withColumns( - Arrays.asList(new Column("col1"), new Column("col2"), new Column("col3"))) + new ExpressionList<>(new Column("col1"), new Column("col2"), + new Column("col3"))) .withSelect(select); assertDeparse(insert2, statement); @@ -84,11 +81,10 @@ public void testRegularInsert() throws JSQLParserException { statement = "INSERT INTO myschema.mytable VALUES (?, ?, 2.3)"; insert = (Insert) parserManager.parse(new StringReader(statement)); assertEquals("myschema.mytable", insert.getTable().getFullyQualifiedName()); - assertEquals(3, insert.getItemsList(ExpressionList.class).getExpressions().size()); - assertTrue(((ExpressionList) insert.getItemsList()).getExpressions() - .get(0) instanceof JdbcParameter); + assertEquals(3, insert.getValues().getExpressions().size()); + assertTrue(insert.getValues().getExpressions().get(0) instanceof JdbcParameter); assertEquals(2.3, - ((DoubleValue) insert.getItemsList(ExpressionList.class).getExpressions().get(2)) + ((DoubleValue) insert.getValues().getExpressions().get(2)) .getValue(), 0.0); assertEquals(statement, "" + insert); @@ -103,7 +99,7 @@ public void testInsertWithKeywordValue() throws JSQLParserException { assertEquals(1, insert.getColumns().size()); assertEquals("col1", insert.getColumns().get(0).getColumnName()); assertEquals("('val1')", - (((ExpressionList) insert.getItemsList()).getExpressions().get(0)).toString()); + (insert.getValues().getExpressions().get(0)).toString()); assertEquals("INSERT INTO mytable (col1) VALUES ('val1')", insert.toString()); } @@ -117,11 +113,18 @@ public void testInsertFromSelect() throws JSQLParserException { assertEquals("col1", insert.getColumns().get(0).getColumnName()); assertEquals("col2", insert.getColumns().get(1).getColumnName()); assertEquals("col3", insert.getColumns().get(2).getColumnName()); - assertNull(insert.getItemsList()); + + // throw a NPE since its a PlainSelect statement + assertThrows(Exception.class, new Executable() { + @Override + public void execute() throws Throwable { + insert.getValues(); + } + }); + assertNotNull(insert.getSelect()); assertEquals("mytable2", - ((Table) ((PlainSelect) insert.getSelect()).getFromItem()) - .getName()); + ((Table) insert.getPlainSelect().getFromItem()).getName()); // toString uses brackets String statementToString = "INSERT INTO mytable (col1, col2, col3) SELECT * FROM mytable2"; @@ -139,12 +142,12 @@ public void testInsertFromSet() throws JSQLParserException { String statement = "INSERT INTO mytable SET col1 = 12, col2 = name1 * name2"; Insert insert = (Insert) parserManager.parse(new StringReader(statement)); assertEquals("mytable", insert.getTable().getName()); - assertEquals(2, insert.getSetColumns().size()); - assertEquals("col1", insert.getSetColumns().get(0).getColumnName()); - assertEquals("col2", insert.getSetColumns().get(1).getColumnName()); - assertEquals(2, insert.getSetExpressionList().size()); - assertEquals("12", insert.getSetExpressionList().get(0).toString()); - assertEquals("name1 * name2", insert.getSetExpressionList().get(1).toString()); + assertEquals(2, insert.getSetUpdateSets().size()); + assertEquals("col1", insert.getSetUpdateSets().get(0).getColumns().get(0).getColumnName()); + assertEquals("col2", insert.getSetUpdateSets().get(1).getColumns().get(0).getColumnName()); + assertEquals("12", insert.getSetUpdateSets().get(0).getValues().get(0).toString()); + assertEquals("name1 * name2", + insert.getSetUpdateSets().get(1).getValues().get(0).toString()); assertEquals(statement, "" + insert); } @@ -157,17 +160,18 @@ public void testInsertValuesWithDuplicateElimination() throws JSQLParserExceptio assertEquals(2, insert.getColumns().size()); assertEquals("ID", insert.getColumns().get(0).getColumnName()); assertEquals("COUNTER", insert.getColumns().get(1).getColumnName()); - assertEquals(2, ((ExpressionList) insert.getItemsList()).getExpressions().size()); + assertEquals(2, insert.getValues().getExpressions().size()); assertEquals(123, - ((LongValue) ((ExpressionList) insert.getItemsList()).getExpressions().get(0)) + ((LongValue) insert.getValues().getExpressions().get(0)) .getValue()); assertEquals(0, - ((LongValue) ((ExpressionList) insert.getItemsList()).getExpressions().get(1)) + ((LongValue) insert.getValues().getExpressions().get(1)) .getValue()); - assertEquals(1, insert.getDuplicateUpdateColumns().size()); - assertEquals("COUNTER", insert.getDuplicateUpdateColumns().get(0).getColumnName()); - assertEquals(1, insert.getDuplicateUpdateExpressionList().size()); - assertEquals("COUNTER + 1", insert.getDuplicateUpdateExpressionList().get(0).toString()); + assertEquals(1, insert.getDuplicateUpdateSets().size()); + assertEquals("COUNTER", + insert.getDuplicateUpdateSets().get(0).getColumns().get(0).getColumnName()); + assertEquals("COUNTER + 1", + insert.getDuplicateUpdateSets().get(0).getValues().get(0).toString()); assertFalse(insert.isUseSelectBrackets()); assertTrue(insert.isUseDuplicate()); assertEquals(statement, "" + insert); @@ -179,16 +183,18 @@ public void testInsertFromSetWithDuplicateElimination() throws JSQLParserExcepti + "ON DUPLICATE KEY UPDATE col2 = col2 + 1, col3 = 'saint'"; Insert insert = (Insert) parserManager.parse(new StringReader(statement)); assertEquals("mytable", insert.getTable().getName()); - assertEquals(1, insert.getSetColumns().size()); - assertEquals("col1", insert.getSetColumns().get(0).getColumnName()); - assertEquals(1, insert.getSetExpressionList().size()); - assertEquals("122", insert.getSetExpressionList().get(0).toString()); - assertEquals(2, insert.getDuplicateUpdateColumns().size()); - assertEquals("col2", insert.getDuplicateUpdateColumns().get(0).getColumnName()); - assertEquals("col3", insert.getDuplicateUpdateColumns().get(1).getColumnName()); - assertEquals(2, insert.getDuplicateUpdateExpressionList().size()); - assertEquals("col2 + 1", insert.getDuplicateUpdateExpressionList().get(0).toString()); - assertEquals("'saint'", insert.getDuplicateUpdateExpressionList().get(1).toString()); + assertEquals(1, insert.getSetUpdateSets().size()); + assertEquals("col1", insert.getSetUpdateSets().get(0).getColumns().get(0).getColumnName()); + assertEquals("122", insert.getSetUpdateSets().get(0).getValues().get(0).toString()); + assertEquals(2, insert.getDuplicateUpdateSets().size()); + assertEquals("col2", + insert.getDuplicateUpdateSets().get(0).getColumns().get(0).getColumnName()); + assertEquals("col3", + insert.getDuplicateUpdateSets().get(1).getColumns().get(0).getColumnName()); + assertEquals("col2 + 1", + insert.getDuplicateUpdateSets().get(0).getValues().get(0).toString()); + assertEquals("'saint'", + insert.getDuplicateUpdateSets().get(1).getValues().get(0).toString()); assertEquals(statement, "" + insert); } @@ -197,16 +203,16 @@ public void testInsertMultiRowValue() throws JSQLParserException { String statement = "INSERT INTO mytable (col1, col2) VALUES (a, b), (d, e)"; assertSqlCanBeParsedAndDeparsed(statement); - MultiExpressionList multiExpressionList = new MultiExpressionList() - .addExpressionLists(new ExpressionList().addExpressions(new Column("a")) - .addExpressions(new Column("b"))) - .addExpressionLists(new ExpressionList().addExpressions(new Column("d")) - .addExpressions(new Column("e"))); + ExpressionList multiExpressionList = new ExpressionList<>() + .addExpression( + new ParenthesedExpressionList(new Column("a"), new Column("b"))) + .addExpression( + new ParenthesedExpressionList(new Column("d"), new Column("e"))); Select select = new Values().withExpressions(multiExpressionList); Insert insert = new Insert().withTable(new Table("mytable")) - .withColumns(Arrays.asList(new Column("col1"), new Column("col2"))) + .withColumns(new ExpressionList<>(new Column("col1"), new Column("col2"))) .withSelect(select); assertDeparse(insert, statement); diff --git a/src/test/java/net/sf/jsqlparser/statement/replace/ReplaceTest.java b/src/test/java/net/sf/jsqlparser/statement/replace/ReplaceTest.java index 180bee0ff..cbe7aaea1 100644 --- a/src/test/java/net/sf/jsqlparser/statement/replace/ReplaceTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/replace/ReplaceTest.java @@ -13,7 +13,9 @@ import net.sf.jsqlparser.expression.JdbcParameter; import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.StringValue; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.statement.select.Values; import net.sf.jsqlparser.statement.upsert.Upsert; import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Test; @@ -28,14 +30,14 @@ public void testReplaceSyntax1() throws JSQLParserException { String statement = "REPLACE mytable SET col1='as', col2=?, col3=565"; Upsert upsert = (Upsert) TestUtils.assertSqlCanBeParsedAndDeparsed(statement, true); assertEquals("mytable", upsert.getTable().getName()); - assertEquals(3, upsert.getColumns().size()); - assertEquals("col1", ((Column) upsert.getColumns().get(0)).getColumnName()); - assertEquals("col2", ((Column) upsert.getColumns().get(1)).getColumnName()); - assertEquals("col3", ((Column) upsert.getColumns().get(2)).getColumnName()); - assertEquals("as", ((StringValue) upsert.getSetExpressions().get(0)).getValue()); - assertTrue( upsert.getSetExpressions().get(1) instanceof JdbcParameter); - assertEquals(565, ((LongValue) upsert.getSetExpressions().get(2)).getValue()); - assertEquals(statement, "" + upsert); + assertEquals(3, upsert.getUpdateSets().size()); + assertEquals("col1", upsert.getUpdateSets().get(0).getColumns().get(0).getColumnName()); + assertEquals("col2", upsert.getUpdateSets().get(1).getColumns().get(0).getColumnName()); + assertEquals("col3", upsert.getUpdateSets().get(2).getColumns().get(0).getColumnName()); + assertEquals("'as'", upsert.getUpdateSets().get(0).getValues().get(0).toString()); + assertTrue(upsert.getUpdateSets().get(1).getValues().get(0) instanceof JdbcParameter); + assertEquals(565L, + ((LongValue) upsert.getUpdateSets().get(2).getValues().get(0)).getValue()); } @Test @@ -47,10 +49,12 @@ public void testReplaceSyntax2() throws JSQLParserException { assertEquals("col1", ((Column) replace.getColumns().get(0)).getColumnName()); assertEquals("col2", ((Column) replace.getColumns().get(1)).getColumnName()); assertEquals("col3", ((Column) replace.getColumns().get(2)).getColumnName()); - assertEquals("as", ((StringValue) replace.getSetExpressions().get(0) ).getValue() ); - assertTrue( replace.getSetExpressions().get(1) instanceof JdbcParameter); - assertEquals(565, ((LongValue) replace.getSetExpressions().get(2)).getValue()); - assertEquals(statement, "" + replace); + + ExpressionList expressions = + (ExpressionList) ((Values) replace.getSelect()).getExpressions(); + assertEquals("as", ((StringValue) expressions.get(0)).getValue()); + assertTrue(expressions.get(1) instanceof JdbcParameter); + assertEquals(565, ((LongValue) expressions.get(2)).getValue()); } @Test @@ -67,19 +71,20 @@ public void testReplaceSyntax3() throws JSQLParserException { @Test public void testProblemReplaceParseDeparse() throws JSQLParserException { - TestUtils. - assertSqlCanBeParsedAndDeparsed("REPLACE a_table (ID, A, B) SELECT A_ID, A, B FROM b_table", false); + TestUtils.assertSqlCanBeParsedAndDeparsed( + "REPLACE a_table (ID, A, B) SELECT A_ID, A, B FROM b_table", true); } @Test public void testProblemMissingIntoIssue389() throws JSQLParserException { - TestUtils. - assertSqlCanBeParsedAndDeparsed("REPLACE INTO mytable (key, data) VALUES (1, \"aaa\")"); + TestUtils.assertSqlCanBeParsedAndDeparsed( + "REPLACE INTO mytable (key, data) VALUES (1, \"aaa\")", true); } @Test public void testMultipleValues() throws JSQLParserException { - TestUtils. - assertSqlCanBeParsedAndDeparsed("REPLACE INTO mytable (col1, col2, col3) VALUES (1, \"aaa\", now()), (2, \"bbb\", now())"); + TestUtils.assertSqlCanBeParsedAndDeparsed( + "REPLACE INTO mytable (col1, col2, col3) VALUES (1, \"aaa\", now()), (2, \"bbb\", now())", + true); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/ClickHouseTest.java b/src/test/java/net/sf/jsqlparser/statement/select/ClickHouseTest.java index fa52af6a9..69cd90e6e 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/ClickHouseTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/ClickHouseTest.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.statement.select; import net.sf.jsqlparser.JSQLParserException; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; @@ -34,4 +35,35 @@ public void testFunctionWithAttributesIssue1742() throws JSQLParserException { sql = "SELECT schemaName.f1(arguments).f2(arguments).f3.f4 from dual"; assertSqlCanBeParsedAndDeparsed(sql, true); } + + @Test + public void testSelectUsingFinal() throws JSQLParserException { + String sqlStr = "SELECT column FROM table_name AS tn FINAL"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + // check that FINAL is reserved keyword and won't be read as an Alias + sqlStr = "SELECT column FROM table_name FINAL"; + PlainSelect select = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + Assertions.assertTrue(select.isUsingFinal()); + Assertions.assertFalse(select.withUsingFinal(false).toString().contains("FINAL")); + } + + @Test + public void testLimitBy() throws JSQLParserException { + String sqlStr = "SELECT * FROM limit_by ORDER BY id, val LIMIT 1, 2 BY id"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT\n" + + " domainWithoutWWW(URL) AS domain,\n" + + " domainWithoutWWW(REFERRER_URL) AS referrer,\n" + + " device_type,\n" + + " count() cnt\n" + + "FROM hits\n" + + "GROUP BY domain, referrer, device_type\n" + + "ORDER BY cnt DESC\n" + + "LIMIT 5 BY domain, device_type\n" + + "LIMIT 100"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/HiveTest.java b/src/test/java/net/sf/jsqlparser/statement/select/HiveTest.java index d05753b4a..2b1b1bab1 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/HiveTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/HiveTest.java @@ -44,4 +44,14 @@ public void testGroupByGroupingSets() throws Exception { + "GROUP BY C1, C2, C3 GROUPING SETS ((C1, C2), (C1, C2, C3), ())"; assertSqlCanBeParsedAndDeparsed(sql, true); } + + @Test + public void testGroupSimplified() throws Exception { + String sql = "SELECT\n" + + " * \n" + + "FROM\n" + + " Sometable\n" + + "GROUP BY GROUPING SETS (())"; + assertSqlCanBeParsedAndDeparsed(sql, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java b/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java index d2582545b..6a85d65d2 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java @@ -104,10 +104,11 @@ public void testIssue496() throws JSQLParserException { } @Test + // @Todo Investigate performance deterioration since JSQLParser 5.0pre development public void testIssue856() throws JSQLParserException { String sql = "SELECT " + buildRecursiveBracketExpression( - "if(month(today()) = 3, sum(\"Table5\".\"Month 002\"), $1)", "0", 5) + "if(month(today()) = 3, sum(\"Table5\".\"Month 002\"), $1)", "0", 3) + " FROM mytbl"; assertSqlCanBeParsedAndDeparsed(sql); } @@ -123,11 +124,12 @@ public void testRecursiveBracketExpressionIssue1019() { } // maxDepth = 10 collides with the Parser Timeout = 6 seconds - // temporarily restrict it to maxDepth = 8 for the moment + // temporarily restrict it to maxDepth = 4 for the moment // @todo: implement methods to set the Parser Timeout explicitly and on demand + // @todo Investigate performance deterioration since JSQLParser 5.0pre development @Test public void testRecursiveBracketExpressionIssue1019_2() throws JSQLParserException { - doIncreaseOfParseTimeTesting("IF(1=1, $1, 2)", "1", 8); + doIncreaseOfParseTimeTesting("IF(1=1, $1, 2)", "1", 4); } @Test diff --git a/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java b/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java index 965332623..921435026 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java @@ -11,10 +11,16 @@ import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.JsonExpression; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.statement.Statements; +import net.sf.jsqlparser.statement.insert.Insert; import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.List; + import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; public class PostgresTest { @@ -32,14 +38,17 @@ public void testExtractFunction() throws JSQLParserException { @Test public void testExtractFunctionIssue1582() throws JSQLParserException { - String sqlStr = "" + "select\n" + " t0.operatienr\n" + " , case\n" - + " when\n" - + " case when (t0.vc_begintijd_operatie is null or lpad((extract('hours' from t0.vc_begintijd_operatie::timestamp))::text,2,'0') ||':'|| lpad(extract('minutes' from t0.vc_begintijd_operatie::timestamp)::text,2,'0') = '00:00') then null\n" - + " else (greatest(((extract('hours' from (t0.vc_eindtijd_operatie::timestamp-t0.vc_begintijd_operatie::timestamp))*60 + extract('minutes' from (t0.vc_eindtijd_operatie::timestamp-t0.vc_begintijd_operatie::timestamp)))/60)::numeric(12,2),0))*60\n" - + " end = 0 then null\n" - + " else '25. Meer dan 4 uur'\n" - + " end \n" - + " as snijtijd_interval"; + String sqlStr = "" + + "select\n" + + " t0.operatienr\n" + + " , case\n" + + " when\n" + + " case when (t0.vc_begintijd_operatie is null or lpad((extract('hours' from t0.vc_begintijd_operatie::timestamp))::text,2,'0') ||':'|| lpad(extract('minutes' from t0.vc_begintijd_operatie::timestamp)::text,2,'0') = '00:00') then null\n" + + " else (greatest(((extract('hours' from (t0.vc_eindtijd_operatie::timestamp-t0.vc_begintijd_operatie::timestamp))*60 + extract('minutes' from (t0.vc_eindtijd_operatie::timestamp-t0.vc_begintijd_operatie::timestamp)))/60)::numeric(12,2),0))*60\n" + + " end = 0 then null\n" + + " else '25. Meer dan 4 uur'\n" + + " end\n" + + " as snijtijd_interval"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } @@ -47,8 +56,8 @@ public void testExtractFunctionIssue1582() throws JSQLParserException { public void testJSonExpressionIssue1696() throws JSQLParserException { String sqlStr = "SELECT '{\"key\": \"value\"}'::json -> 'key' AS X"; PlainSelect plainSelect = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sqlStr, true); - SelectExpressionItem selectExpressionItem = - (SelectExpressionItem) plainSelect.getSelectItems().get(0); + SelectItem selectExpressionItem = + (SelectItem) plainSelect.getSelectItems().get(0); Assertions.assertEquals("'key'", selectExpressionItem.getExpression(JsonExpression.class).getIdents().get(0)); } @@ -59,4 +68,31 @@ public void testJSonOperatorIssue1571() throws JSQLParserException { "select visit_hour,json_array_elements(into_sex_json)->>'name',json_array_elements(into_sex_json)->>'value' from period_market"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + void testPostgresQuotingIssue1335() throws JSQLParserException { + String sqlStr = + "INSERT INTO \"table\"\"with\"\"quotes\" (\"column\"\"with\"\"quotes\")\n" + + "VALUES ('1'), ('2'), ('3');\n" + + "\n" + + "UPDATE \"table\"\"with\"\"quotes\" SET \"column\"\"with\"\"quotes\" = '1.0' \n" + + "WHERE \"column\"\"with\"\"quotes\" = '1';\n" + + "\n" + + "SELECT \"column\"\"with\"\"quotes\" FROM \"table\"\"with\"\"quotes\"\n" + + "WHERE \"column\"\"with\"\"quotes\" IS NOT NULL;"; + + Statements statements = CCJSqlParserUtil.parseStatements(sqlStr); + Assertions.assertEquals(3, statements.size()); + + Insert insert = statements.get(Insert.class, 0); + Assertions.assertEquals( + "\"table\"\"with\"\"quotes\"", insert.getTable().getFullyQualifiedName()); + + PlainSelect select = statements.get(PlainSelect.class, 2); + List> selectItems = select.getSelectItems(); + + Assertions.assertEquals( + "\"column\"\"with\"\"quotes\"", + selectItems.get(0).getExpression(Column.class).getColumnName()); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SelectASTTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SelectASTTest.java index 9b26e8555..2888ed72c 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectASTTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectASTTest.java @@ -37,7 +37,7 @@ public void testSelectASTColumn() throws JSQLParserException { StringBuilder b = new StringBuilder(sql); PlainSelect plainSelect = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sql, true); for (SelectItem item : plainSelect.getSelectItems()) { - SelectExpressionItem sei = (SelectExpressionItem) item; + SelectItem sei = (SelectItem) item; Column c = sei.getExpression(Column.class); SimpleNode astNode = c.getASTNode(); assertNotNull(astNode); @@ -93,9 +93,8 @@ public void testSelectASTColumnLF() throws JSQLParserException { String sql = "SELECT a, b FROM mytable \n order by b, c"; StringBuilder b = new StringBuilder(sql); PlainSelect plainSelect = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sql, true); - for (SelectItem item : plainSelect.getSelectItems()) { - SelectExpressionItem sei = (SelectExpressionItem) item; - Column c = sei.getExpression(Column.class); + for (SelectItem item : plainSelect.getSelectItems()) { + Column c = item.getExpression(Column.class); SimpleNode astNode = c.getASTNode(); assertNotNull(astNode); b.setCharAt(astNode.jjtGetFirstToken().absoluteBegin - 1, '*'); @@ -115,9 +114,8 @@ public void testSelectASTCommentLF() throws JSQLParserException { "SELECT /* testcomment */ \n a, b FROM -- testcomment2 \n mytable \n order by b, c"; StringBuilder b = new StringBuilder(sql); PlainSelect plainSelect = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sql, true); - for (SelectItem item : plainSelect.getSelectItems()) { - SelectExpressionItem sei = (SelectExpressionItem) item; - Column c = sei.getExpression(Column.class); + for (SelectItem item : plainSelect.getSelectItems()) { + Column c = item.getExpression(Column.class); SimpleNode astNode = c.getASTNode(); assertNotNull(astNode); b.setCharAt(astNode.jjtGetFirstToken().absoluteBegin - 1, '*'); @@ -139,9 +137,8 @@ public void testSelectASTCommentCRLF() throws JSQLParserException { "SELECT /* testcomment */ \r\n a, b FROM -- testcomment2 \r\n mytable \r\n order by b, c"; StringBuilder b = new StringBuilder(sql); PlainSelect plainSelect = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sql, true); - for (SelectItem item : plainSelect.getSelectItems()) { - SelectExpressionItem sei = (SelectExpressionItem) item; - Column c = sei.getExpression(Column.class); + for (SelectItem item : plainSelect.getSelectItems()) { + Column c = item.getExpression(Column.class); SimpleNode astNode = c.getASTNode(); assertNotNull(astNode); b.setCharAt(astNode.jjtGetFirstToken().absoluteBegin - 1, '*'); 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 e1767244c..0bea90afa 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -9,20 +9,23 @@ */ package net.sf.jsqlparser.statement.select; -import java.io.IOException; -import java.io.StringReader; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import net.sf.jsqlparser.parser.CCJSqlParser; import net.sf.jsqlparser.JSQLParserException; -import net.sf.jsqlparser.expression.*; +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.expression.AllValue; +import net.sf.jsqlparser.expression.BinaryExpression; +import net.sf.jsqlparser.expression.DoubleValue; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.Function; +import net.sf.jsqlparser.expression.IntervalExpression; +import net.sf.jsqlparser.expression.JdbcNamedParameter; +import net.sf.jsqlparser.expression.JdbcParameter; +import net.sf.jsqlparser.expression.LongValue; +import net.sf.jsqlparser.expression.NotExpression; +import net.sf.jsqlparser.expression.NullValue; +import net.sf.jsqlparser.expression.SignedExpression; +import net.sf.jsqlparser.expression.StringValue; +import net.sf.jsqlparser.expression.TimeValue; +import net.sf.jsqlparser.expression.TimestampValue; import net.sf.jsqlparser.expression.operators.arithmetic.Addition; import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication; import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction; @@ -31,8 +34,7 @@ import net.sf.jsqlparser.expression.operators.relational.GreaterThan; import net.sf.jsqlparser.expression.operators.relational.InExpression; import net.sf.jsqlparser.expression.operators.relational.LikeExpression; -import net.sf.jsqlparser.parser.CCJSqlParserManager; -import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.parser.*; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Database; import net.sf.jsqlparser.schema.Server; @@ -40,21 +42,9 @@ import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitorAdapter; import net.sf.jsqlparser.statement.Statements; -import static net.sf.jsqlparser.test.TestUtils.*; - -import net.sf.jsqlparser.test.MemoryLeakVerifier; import net.sf.jsqlparser.test.TestUtils; import org.apache.commons.io.IOUtils; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - +import org.apache.commons.lang3.SerializationUtils; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -65,6 +55,29 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import java.io.IOException; +import java.io.StringReader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +import static net.sf.jsqlparser.test.TestUtils.assertDeparse; +import static net.sf.jsqlparser.test.TestUtils.assertExpressionCanBeDeparsedAs; +import static net.sf.jsqlparser.test.TestUtils.assertExpressionCanBeParsedAndDeparsed; +import static net.sf.jsqlparser.test.TestUtils.assertOracleHintExists; +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; +import static net.sf.jsqlparser.test.TestUtils.assertStatementCanBeDeparsedAs; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + @Execution(ExecutionMode.CONCURRENT) public class SelectTest { @@ -79,8 +92,8 @@ public void testMultiPartTableNameWithServerNameAndDatabaseNameAndSchemaName() parser -> parser.withSquareBracketQuotation(true)); assertDeparse( new PlainSelect() - .addSelectItems( - new SelectExpressionItem(new Column().withColumnName("columnName"))) + .addSelectItem( + new Column().withColumnName("columnName")) .withFromItem(new Table() .withDatabase(new Database("databaseName") .withServer(new Server("[server-name\\server-instance]"))) @@ -96,7 +109,7 @@ public void testMultiPartTableNameWithServerNameAndDatabaseName() throws Excepti assertSqlCanBeParsedAndDeparsed(statement, false, parser -> parser.withSquareBracketQuotation(true)); assertDeparse(new PlainSelect() - .addSelectItems(new SelectExpressionItem(new Column().withColumnName("columnName"))) + .addSelectItem(new Column().withColumnName("columnName")) .withFromItem(new Table() .withDatabase(new Database("databaseName") .withServer(new Server("[server-name\\server-instance]"))) @@ -236,7 +249,7 @@ public void testMultiPartColumnName() throws Exception { } void checkMultipartIdentifier(Select select, String fullColumnName) { - final Expression expr = ((SelectExpressionItem) ((PlainSelect) select) + final Expression expr = (((PlainSelect) select) .getSelectItems().get(0)).getExpression(); assertTrue(expr instanceof Column); Column col = (Column) expr; @@ -251,7 +264,7 @@ public void testAllColumnsFromTable() throws Exception { assertStatementCanBeDeparsedAs(select, statement); assertTrue(select.getSelectItems() - .get(0) instanceof AllTableColumns); + .get(0).getExpression() instanceof AllTableColumns); Table t = new Table("tableName"); assertDeparse( @@ -704,7 +717,7 @@ public void testTopWithParenthesis() throws JSQLParserException { assertTrue(top.hasParenthesis()); assertTrue(top.isPercentage()); - final List selectItems = selectBody.getSelectItems(); + final List> selectItems = selectBody.getSelectItems(); assertEquals(2, selectItems.size()); assertEquals(firstColumnName, selectItems.get(0).toString()); assertEquals(secondColumnName, selectItems.get(1).toString()); @@ -769,7 +782,7 @@ public void testSkip() throws JSQLParserException { assertNull(skip.getJdbcParameter()); assertNull(skip.getVariable()); - final List selectItems = selectBody.getSelectItems(); + final List> selectItems = selectBody.getSelectItems(); assertEquals(2, selectItems.size()); assertEquals(firstColumnName, selectItems.get(0).toString()); assertEquals(secondColumnName, selectItems.get(1).toString()); @@ -786,7 +799,7 @@ public void testSkip() throws JSQLParserException { assertNull(skip2.getJdbcParameter()); assertEquals("skipVar", skip2.getVariable()); - final List selectItems2 = selectBody2.getSelectItems(); + final List> selectItems2 = selectBody2.getSelectItems(); assertEquals(2, selectItems2.size()); assertEquals("c1", selectItems2.get(0).toString()); assertEquals("c2", selectItems2.get(1).toString()); @@ -809,7 +822,7 @@ public void testFirst() throws JSQLParserException { assertNull(limit.getJdbcParameter()); assertEquals(First.Keyword.FIRST, limit.getKeyword()); - final List selectItems = selectBody.getSelectItems(); + final List> selectItems = selectBody.getSelectItems(); assertEquals(2, selectItems.size()); assertEquals(firstColumnName, selectItems.get(0).toString()); assertEquals(secondColumnName, selectItems.get(1).toString()); @@ -826,7 +839,7 @@ public void testFirst() throws JSQLParserException { assertNull(first2.getJdbcParameter()); assertEquals("firstVar", first2.getVariable()); - final List selectItems2 = selectBody2.getSelectItems(); + final List> selectItems2 = selectBody2.getSelectItems(); assertEquals(2, selectItems2.size()); assertEquals("c1", selectItems2.get(0).toString()); assertEquals("c2", selectItems2.get(1).toString()); @@ -851,7 +864,7 @@ public void testFirstWithKeywordLimit() throws JSQLParserException { assertFalse(limit.getJdbcParameter().isUseFixedIndex()); assertEquals(First.Keyword.LIMIT, limit.getKeyword()); - final List selectItems = selectBody.getSelectItems(); + final List> selectItems = selectBody.getSelectItems(); assertEquals(2, selectItems.size()); assertEquals(firstColumnName, selectItems.get(0).toString()); assertEquals(secondColumnName, selectItems.get(1).toString()); @@ -877,7 +890,7 @@ public void testSkipFirst() throws JSQLParserException { assertNull(first.getRowCount()); assertEquals("f1", first.getVariable()); - final List selectItems = selectBody.getSelectItems(); + final List> selectItems = selectBody.getSelectItems(); assertEquals(2, selectItems.size()); assertEquals("c1", selectItems.get(0).toString()); assertEquals("c2", selectItems.get(1).toString()); @@ -892,22 +905,26 @@ public void testSelectItems() throws JSQLParserException { Select select = (Select) parserManager.parse(new StringReader(statement)); PlainSelect plainSelect = (PlainSelect) select; - final List selectItems = plainSelect.getSelectItems(); - assertEquals("MYID", ((SelectExpressionItem) selectItems.get(0)).getAlias().getName()); - assertEquals("mycol", ((Column) ((SelectExpressionItem) selectItems.get(1)).getExpression()) + final List> selectItems = plainSelect.getSelectItems(); + assertEquals("MYID", selectItems.get(0).getAlias().getName()); + assertEquals("mycol", ((Column) (selectItems.get(1)).getExpression()) .getColumnName()); - assertEquals("tab", ((AllTableColumns) selectItems.get(2)).getTable().getName()); - assertEquals("schema", ((AllTableColumns) selectItems.get(3)).getTable().getSchemaName()); + assertEquals("tab", + ((AllTableColumns) selectItems.get(2).getExpression()).getTable().getName()); + assertEquals("schema", + ((AllTableColumns) selectItems.get(3).getExpression()).getTable().getSchemaName()); assertEquals("schema.tab", - ((AllTableColumns) selectItems.get(3)).getTable().getFullyQualifiedName()); + ((AllTableColumns) selectItems.get(3).getExpression()).getTable() + .getFullyQualifiedName()); assertEquals("mytab.mycol2", - ((Column) ((SelectExpressionItem) selectItems.get(4)).getExpression()) + ((Column) (selectItems.get(4)).getExpression()) .getFullyQualifiedName()); assertEquals("myschema.mytab.mycol", - ((Column) ((SelectExpressionItem) selectItems.get(5)).getExpression()) + ((Column) (selectItems.get(5)).getExpression()) .getFullyQualifiedName()); assertEquals("myschema.mytab", - ((AllTableColumns) selectItems.get(6)).getTable().getFullyQualifiedName()); + ((AllTableColumns) selectItems.get(6).getExpression()).getTable() + .getFullyQualifiedName()); assertStatementCanBeDeparsedAs(select, statement); statement = @@ -915,14 +932,14 @@ public void testSelectItems() throws JSQLParserException { select = (Select) parserManager.parse(new StringReader(statement)); plainSelect = (PlainSelect) select; assertEquals("myalias", - ((SelectExpressionItem) plainSelect.getSelectItems().get(1)).getAlias().getName()); + (plainSelect.getSelectItems().get(1)).getAlias().getName()); assertStatementCanBeDeparsedAs(select, statement); statement = "SELECT (myid + myid2) AS MYID FROM mytable WHERE mytable.col = 9"; select = (Select) parserManager.parse(new StringReader(statement)); plainSelect = (PlainSelect) select; assertEquals("MYID", - ((SelectExpressionItem) plainSelect.getSelectItems().get(0)).getAlias().getName()); + (plainSelect.getSelectItems().get(0)).getAlias().getName()); assertStatementCanBeDeparsedAs(select, statement); } @@ -1021,9 +1038,9 @@ public void testDistinct() throws JSQLParserException { Select select = (Select) TestUtils.assertSqlCanBeParsedAndDeparsed(statement, true); PlainSelect plainSelect = (PlainSelect) select; - assertEquals("myid", ((Column) ((SelectExpressionItem) plainSelect.getDistinct() + assertEquals("myid", ((Column) (plainSelect.getDistinct() .getOnSelectItems().get(0)).getExpression()).getColumnName()); - assertEquals("mycol", ((Column) ((SelectExpressionItem) plainSelect.getSelectItems().get(1)) + assertEquals("mycol", ((Column) (plainSelect.getSelectItems().get(1)) .getExpression()).getColumnName()); } @@ -1044,9 +1061,9 @@ public void testDistinctTop() throws JSQLParserException { String statement = "SELECT DISTINCT TOP 5 myid, mycol FROM mytable WHERE mytable.col = 9"; Select select = (Select) TestUtils.assertSqlCanBeParsedAndDeparsed(statement, true); PlainSelect plainSelect = (PlainSelect) select; - assertEquals("myid", ((Column) ((SelectExpressionItem) plainSelect.getSelectItems().get(0)) + assertEquals("myid", ((Column) (plainSelect.getSelectItems().get(0)) .getExpression()).getColumnName()); - assertEquals("mycol", ((Column) ((SelectExpressionItem) plainSelect.getSelectItems().get(1)) + assertEquals("mycol", ((Column) (plainSelect.getSelectItems().get(1)) .getExpression()).getColumnName()); assertNotNull(plainSelect.getTop()); } @@ -1161,56 +1178,56 @@ public void testFunctions() throws JSQLParserException { Select select = (Select) parserManager.parse(new StringReader(statement)); PlainSelect plainSelect = (PlainSelect) select; assertEquals("max", - ((SelectExpressionItem) plainSelect.getSelectItems().get(0)).getAlias().getName()); + (plainSelect.getSelectItems().get(0)).getAlias().getName()); assertStatementCanBeDeparsedAs(select, statement); statement = "SELECT substring(id, 2, 3), substring(id from 2 for 3), substring(id from 2), trim(BOTH ' ' from 'foo bar '), trim(LEADING ' ' from 'foo bar '), trim(TRAILING ' ' from 'foo bar '), trim(' ' from 'foo bar '), position('foo' in 'bar'), overlay('foo' placing 'bar' from 1), overlay('foo' placing 'bar' from 1 for 2) FROM my table"; select = (Select) parserManager.parse(new StringReader(statement)); - assertStatementCanBeDeparsedAs(select, statement); + assertStatementCanBeDeparsedAs(select, statement, true); statement = "SELECT MAX(id), AVG(pro) AS myavg FROM mytable WHERE mytable.col = 9 GROUP BY pro"; select = (Select) parserManager.parse(new StringReader(statement)); plainSelect = (PlainSelect) select; assertEquals("myavg", - ((SelectExpressionItem) plainSelect.getSelectItems().get(1)).getAlias().getName()); + (plainSelect.getSelectItems().get(1)).getAlias().getName()); assertStatementCanBeDeparsedAs(select, statement); statement = "SELECT MAX(a, b, c), COUNT(*), D FROM tab1 GROUP BY D"; select = (Select) parserManager.parse(new StringReader(statement)); plainSelect = (PlainSelect) select; - Function fun = (Function) ((SelectExpressionItem) plainSelect.getSelectItems().get(0)) + Function fun = (Function) (plainSelect.getSelectItems().get(0)) .getExpression(); assertEquals("MAX", fun.getName()); assertEquals("b", ((Column) fun.getParameters().getExpressions().get(1)).getFullyQualifiedName()); - assertTrue(((Function) ((SelectExpressionItem) plainSelect.getSelectItems().get(1)) + assertTrue(((Function) (plainSelect.getSelectItems().get(1)) .getExpression()).getParameters().getExpressions().get(0) instanceof AllColumns); assertStatementCanBeDeparsedAs(select, statement); statement = "SELECT {fn MAX(a, b, c)}, COUNT(*), D FROM tab1 GROUP BY D"; select = (Select) parserManager.parse(new StringReader(statement)); plainSelect = (PlainSelect) select; - fun = (Function) ((SelectExpressionItem) plainSelect.getSelectItems().get(0)) + fun = (Function) (plainSelect.getSelectItems().get(0)) .getExpression(); assertTrue(fun.isEscaped()); assertEquals("MAX", fun.getName()); assertEquals("b", ((Column) fun.getParameters().getExpressions().get(1)).getFullyQualifiedName()); - assertTrue(((Function) ((SelectExpressionItem) plainSelect.getSelectItems().get(1)) + assertTrue(((Function) (plainSelect.getSelectItems().get(1)) .getExpression()).getParameters().getExpressions().get(0) instanceof AllColumns); assertStatementCanBeDeparsedAs(select, statement); statement = "SELECT ab.MAX(a, b, c), cd.COUNT(*), D FROM tab1 GROUP BY D"; select = (Select) parserManager.parse(new StringReader(statement)); plainSelect = (PlainSelect) select; - fun = (Function) ((SelectExpressionItem) plainSelect.getSelectItems().get(0)) + fun = (Function) (plainSelect.getSelectItems().get(0)) .getExpression(); assertEquals("ab.MAX", fun.getName()); assertEquals("b", ((Column) fun.getParameters().getExpressions().get(1)).getFullyQualifiedName()); - fun = (Function) ((SelectExpressionItem) plainSelect.getSelectItems().get(1)) + fun = (Function) (plainSelect.getSelectItems().get(1)) .getExpression(); assertEquals("cd.COUNT", fun.getName()); assertTrue(fun.getParameters().getExpressions().get(0) instanceof AllColumns); @@ -1234,7 +1251,8 @@ public void testEscapedFunctionsIssue753() throws JSQLParserException { @Test public void testNamedParametersPR702() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( - "SELECT substring(id, 2, 3), substring(id from 2 for 3), substring(id from 2), trim(BOTH ' ' from 'foo bar '), trim(LEADING ' ' from 'foo bar '), trim(TRAILING ' ' from 'foo bar '), trim(' ' from 'foo bar '), position('foo' in 'bar'), overlay('foo' placing 'bar' from 1), overlay('foo' placing 'bar' from 1 for 2) FROM my table"); + "SELECT substring(id, 2, 3), substring(id from 2 for 3), substring(id from 2), trim(BOTH ' ' from 'foo bar '), trim(LEADING ' ' from 'foo bar '), trim(TRAILING ' ' from 'foo bar '), trim(' ' from 'foo bar '), position('foo' in 'bar'), overlay('foo' placing 'bar' from 1), overlay('foo' placing 'bar' from 1 for 2) FROM my table", + true); } @Test @@ -1252,41 +1270,42 @@ public void testQuotedCastExpression() throws JSQLParserException { @Test public void testWhere() throws JSQLParserException { + String whereToString = "(1 + 2) * (1+2) > ?"; + assertExpressionCanBeParsedAndDeparsed(whereToString, true); + final String statement = "SELECT * FROM tab1 WHERE"; - String whereToString = "(a + b + c / d + e * f) * (a / b * (a + b)) > ?"; - PlainSelect plainSelect = (PlainSelect) parserManager - .parse(new StringReader(statement + " " + whereToString)); + whereToString = "(a + b + c / d + e * f) * (a / b * (a + b)) > ?"; + assertExpressionCanBeParsedAndDeparsed(whereToString, true); + + PlainSelect plainSelect = + (PlainSelect) assertSqlCanBeParsedAndDeparsed(statement + " " + whereToString, + true); + assertTrue(plainSelect.getWhere() instanceof GreaterThan); assertTrue(((GreaterThan) plainSelect.getWhere()) .getLeftExpression() instanceof Multiplication); - assertEquals(statement + " " + whereToString, plainSelect.toString()); assertExpressionCanBeDeparsedAs(plainSelect.getWhere(), whereToString); whereToString = "(7 * s + 9 / 3) NOT BETWEEN 3 AND ?"; - plainSelect = (PlainSelect) parserManager - .parse(new StringReader(statement + " " + whereToString)); - + plainSelect = (PlainSelect) assertSqlCanBeParsedAndDeparsed(statement + " " + whereToString, + true); assertExpressionCanBeDeparsedAs(plainSelect.getWhere(), whereToString); - assertEquals(statement + " " + whereToString, plainSelect.toString()); whereToString = "a / b NOT IN (?, 's''adf', 234.2)"; - plainSelect = (PlainSelect) parserManager - .parse(new StringReader(statement + " " + whereToString)); - + plainSelect = (PlainSelect) assertSqlCanBeParsedAndDeparsed(statement + " " + whereToString, + true); assertExpressionCanBeDeparsedAs(plainSelect.getWhere(), whereToString); - assertEquals(statement + " " + whereToString, plainSelect.toString()); - whereToString = " NOT 0 = 0"; - parserManager - .parse(new StringReader(statement + whereToString)); - - whereToString = " NOT (0 = 0)"; - plainSelect = (PlainSelect) parserManager - .parse(new StringReader(statement + whereToString)); + whereToString = "NOT 0 = 0"; + plainSelect = (PlainSelect) assertSqlCanBeParsedAndDeparsed(statement + " " + whereToString, + true); + assertExpressionCanBeDeparsedAs(plainSelect.getWhere(), whereToString); - assertExpressionCanBeDeparsedAs(plainSelect.getWhere(), whereToString.trim()); - assertEquals(statement + whereToString, plainSelect.toString()); + whereToString = "NOT (0 = 0)"; + plainSelect = (PlainSelect) assertSqlCanBeParsedAndDeparsed(statement + " " + whereToString, + true); + assertExpressionCanBeDeparsedAs(plainSelect.getWhere(), whereToString); } @Test @@ -1529,7 +1548,7 @@ public void testReplaceAsFunction() throws JSQLParserException { assertEquals(1, plainSelect.getSelectItems().size()); Expression expression = - ((SelectExpressionItem) plainSelect.getSelectItems().get(0)).getExpression(); + (plainSelect.getSelectItems().get(0)).getExpression(); assertTrue(expression instanceof Function); Function func = (Function) expression; assertEquals("REPLACE", func.getName()); @@ -1604,10 +1623,8 @@ public void testDouble() throws JSQLParserException { String statement = "SELECT 1e2, * FROM mytable WHERE mytable.col = 9"; Select select = (Select) parserManager.parse(new StringReader(statement)); - assertEquals(1e2, - ((DoubleValue) ((SelectExpressionItem) ((PlainSelect) select) - .getSelectItems().get(0)).getExpression()).getValue(), - 0); + assertEquals(1e2, ((DoubleValue) ((PlainSelect) select) + .getSelectItems().get(0).getExpression()).getValue(), 0); assertStatementCanBeDeparsedAs(select, statement); statement = "SELECT * FROM mytable WHERE mytable.col = 1.e2"; @@ -1640,8 +1657,8 @@ public void testDouble2() throws JSQLParserException { Select select = (Select) parserManager.parse(new StringReader(statement)); assertEquals(1e22, - ((DoubleValue) ((SelectExpressionItem) ((PlainSelect) select) - .getSelectItems().get(0)).getExpression()).getValue(), + ((DoubleValue) ((PlainSelect) select) + .getSelectItems().get(0).getExpression()).getValue(), 0); } @@ -1651,7 +1668,7 @@ public void testDouble3() throws JSQLParserException { Select select = (Select) parserManager.parse(new StringReader(statement)); assertEquals(1.0, - ((DoubleValue) ((SelectExpressionItem) ((PlainSelect) select) + ((DoubleValue) (((PlainSelect) select) .getSelectItems().get(0)).getExpression()).getValue(), 0); } @@ -1662,7 +1679,7 @@ public void testDouble4() throws JSQLParserException { Select select = (Select) parserManager.parse(new StringReader(statement)); assertEquals(1.2e22, - ((DoubleValue) ((SelectExpressionItem) ((PlainSelect) select) + ((DoubleValue) (((PlainSelect) select) .getSelectItems().get(0)).getExpression()).getValue(), 0); } @@ -2404,8 +2421,7 @@ public void testProblemFunction() throws JSQLParserException { Statement parsed = CCJSqlParserUtil.parse(stmt); Select select = (Select) parsed; PlainSelect plainSelect = (PlainSelect) select; - SelectItem get = plainSelect.getSelectItems().get(0); - SelectExpressionItem item = (SelectExpressionItem) get; + SelectItem item = plainSelect.getSelectItems().get(0); assertTrue(item.getExpression() instanceof Function); assertEquals("test", ((Function) item.getExpression()).getName()); } @@ -2542,7 +2558,7 @@ public void testInterval2() throws JSQLParserException { PlainSelect plainSelect = (PlainSelect) select; assertEquals(1, plainSelect.getSelectItems().size()); - SelectExpressionItem item = (SelectExpressionItem) plainSelect.getSelectItems().get(0); + SelectItem item = (SelectItem) plainSelect.getSelectItems().get(0); Function function = (Function) item.getExpression(); assertEquals("to_timestamp", function.getName()); @@ -2591,7 +2607,7 @@ public void testMultiValueIn() throws JSQLParserException { public void testMultiValueIn2() throws JSQLParserException { String stmt = "SELECT * FROM mytable WHERE (trim(a), trim(b)) IN (SELECT a, b FROM mytable2)"; - assertSqlCanBeParsedAndDeparsed(stmt); + assertSqlCanBeParsedAndDeparsed(stmt, true); } @Test @@ -3332,7 +3348,7 @@ public void testTableFunctionWithNoParams() throws Exception { assertTrue(plainSelect.getFromItem() instanceof TableFunction); TableFunction fromItem = (TableFunction) plainSelect.getFromItem(); - Function function = fromItem.getFunction(); + Function function = fromItem.getExpression(); assertNotNull(function); assertEquals("SOME_FUNCTION", function.getName()); assertNull(function.getParameters()); @@ -3348,7 +3364,7 @@ public void testTableFunctionWithParams() throws Exception { assertTrue(plainSelect.getFromItem() instanceof TableFunction); TableFunction fromItem = (TableFunction) plainSelect.getFromItem(); - Function function = fromItem.getFunction(); + Function function = fromItem.getExpression(); assertNotNull(function); assertEquals("SOME_FUNCTION", function.getName()); @@ -3379,7 +3395,7 @@ public void testTableFunctionWithAlias() throws Exception { assertTrue(plainSelect.getFromItem() instanceof TableFunction); TableFunction fromItem = (TableFunction) plainSelect.getFromItem(); - Function function = fromItem.getFunction(); + Function function = fromItem.getExpression(); assertNotNull(function); assertEquals("SOME_FUNCTION", function.getName()); @@ -4339,8 +4355,8 @@ public void visit(PlainSelect plainSelect) { }); assertEquals(1, list.size()); - assertTrue(list.get(0) instanceof SelectExpressionItem); - SelectExpressionItem item = (SelectExpressionItem) list.get(0); + assertTrue(list.get(0) instanceof SelectItem); + SelectItem item = list.get(0); assertTrue(item.getExpression() instanceof Addition); Addition add = (Addition) item.getExpression(); @@ -4368,8 +4384,8 @@ public void visit(PlainSelect plainSelect) { }); assertEquals(1, list.size()); - assertTrue(list.get(0) instanceof SelectExpressionItem); - SelectExpressionItem item = (SelectExpressionItem) list.get(0); + assertTrue(list.get(0) instanceof SelectItem); + SelectItem item = list.get(0); assertTrue(item.getExpression() instanceof IntervalExpression); IntervalExpression interval = (IntervalExpression) item.getExpression(); assertEquals("INTERVAL 5 MONTH", interval.toString()); @@ -4388,8 +4404,8 @@ public void visit(Select select) { select.accept(new SelectVisitorAdapter() { @Override public void visit(PlainSelect plainSelect) { - SelectExpressionItem typedExpression = - (SelectExpressionItem) plainSelect.getSelectItems().get(0); + SelectItem typedExpression = + (SelectItem) plainSelect.getSelectItems().get(0); assertNotNull(typedExpression); assertNull(typedExpression.getAlias()); StringValue value = (StringValue) typedExpression.getExpression(); @@ -4404,7 +4420,8 @@ public void visit(PlainSelect plainSelect) { @Test public void testGroupingSets1() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( - "SELECT COL_1, COL_2, COL_3, COL_4, COL_5, COL_6 FROM TABLE_1 " + "GROUP BY " + "SELECT COL_1, COL_2, COL_3, COL_4, COL_5, COL_6 FROM TABLE_1 " + + "GROUP BY " + "GROUPING SETS ((COL_1, COL_2, COL_3, COL_4), (COL_5, COL_6))"); } @@ -4760,8 +4777,7 @@ public void testPreserveAndOperator() throws JSQLParserException { String statement = "SELECT * FROM mytable WHERE 1 = 2 && 2 = 3"; assertSqlCanBeParsedAndDeparsed(statement); assertDeparse( - - new PlainSelect().addSelectItems(Collections.singleton(new AllColumns())) + new PlainSelect().addSelectItem(new AllColumns()) .withFromItem(new Table("mytable")) .withWhere(new AndExpression().withUseOperator(true) .withLeftExpression( @@ -5084,7 +5100,7 @@ public void testGroupedByIssue1176() throws JSQLParserException { @Test public void testGroupedByWithExtraBracketsIssue1210() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("select a,b,c from table group by rollup(a,b,c)", true); + // assertSqlCanBeParsedAndDeparsed("select a,b,c from table group by rollup(a,b,c)", true); assertSqlCanBeParsedAndDeparsed("select a,b,c from table group by rollup((a,b,c))", true); } @@ -5320,17 +5336,59 @@ public void testCaseElseExpressionIssue1375() throws JSQLParserException { @Test public void testComplexInExpressionIssue905() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("select * " + "from table_a " + "where other_id in (" - + " (select id from table_b where name like '%aa%')" - + " , (select id from table_b where name like '%bb%')" + ")", true); + assertSqlCanBeParsedAndDeparsed( + "SELECT *\n" + + "FROM table_a\n" + + "WHERE other_id IN ( ( SELECT id\n" + + " FROM table_b\n" + + " WHERE name LIKE '%aa%' ), ( SELECT id\n" + + " FROM table_b\n" + + " WHERE name LIKE '%bb%' ) )\n", + true); + + assertSqlCanBeParsedAndDeparsed( + "SELECT *\n" + + "FROM v.e\n" + + "WHERE cid <> rid\n" + + " AND rid NOT IN ( ( SELECT DISTINCT\n" + + " rid\n" + + " FROM v.s )\n" + + " UNION (\n" + + " SELECT DISTINCT\n" + + " rid\n" + + " FROM v.p ) )\n" + + " AND \"timestamp\" <= 1298505600000\n", + true); + + assertSqlCanBeParsedAndDeparsed( + "SELECT *\n" + + "FROM table_a\n" + + "WHERE ( a, b, c ) IN ( ( 1, 2, 3 ), ( 3, 4, 5 ) )\n", + true); + } - assertSqlCanBeParsedAndDeparsed("select * from v.e\n" + "where\n" + "\tcid <> rid\n" - + "\tand rid not in\n" + "\t(\n" + "\t\t(select distinct rid from v.s )\n" - + "\t\tunion\n" + "\t\t(select distinct rid from v.p )\n" + "\t)\n" - + "\tand \"timestamp\" <= 1298505600000", true); + @Test + public void testComplexInExpressionSimplyfied() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "SELECT *\n" + + "FROM dual\n" + + "WHERE a IN ( ( SELECT id1), ( SELECT id2) )\n", + true); + + assertExpressionCanBeParsedAndDeparsed( + "a IN ( ( SELECT id1) UNION (SELECT id2) )\n", true); assertSqlCanBeParsedAndDeparsed( - "select * " + "from table_a " + "where (a, b, c) in ((1, 2, 3), (3, 4, 5))", true); + "SELECT *\n" + + "FROM e\n" + + "WHERE a IN ( ( SELECT id1) UNION (SELECT id2) )\n", + true); + + assertSqlCanBeParsedAndDeparsed( + "SELECT *\n" + + "FROM table_a\n" + + "WHERE ( a, b, c ) IN ( ( 1, 2, 3 ), ( 3, 4, 5 ) )\n", + true); } @Test @@ -5389,91 +5447,6 @@ public void testPerformanceIssue1397() throws Exception { assertSqlCanBeParsedAndDeparsed(sqlStr, true); } - /** - * The purpose of the test is to run into a timeout and to stop the parser when this happens. We - * provide an INVALID statement for this purpose, which will fail the SIMPLE parse and then hang - * with COMPLEX parsing until the timeout occurs. - *

    - * We repeat that test multiple times and want to see no stale references to the Parser after - * timeout. - * - * @throws JSQLParserException - */ - @Test - public void testParserInterruptedByTimeout() { - String sqlStr = "" + "SELECT \t* FROM TABLE_1 t1\n" + "WHERE\n" - + "\t(((t1.COL1 = 'VALUE2' )\n" + "\t\tAND (t1.CAL2 = 'VALUE2' ))\n" - + "\t\tAND (((1 = 1 )\n" - + "\t\t\tAND ((((((t1.id IN (940550 ,940600 ,940650 ,940700 ,940750 ,940800 ,940850 ,940900 ,940950 ,941000 ,941050 ,941100 ,941150 ,941200 ,941250 ,941300 ,941350 ,941400 ,941450 ,941500 ,941550 ,941600 ,941650 ,941700 ,941750 ,941800 ,941850 ,941900 ,941950 ,942000 ,942050 ,942100 ,942150 ,942200 ,942250 ,942300 ,942350 ,942400 ,942450 ,942500 ,942550 ,942600 ,942650 ,942700 ,942750 ,942800 ,942850 ,942900 ,942950 ,943000 ,943050 ,943100 ,943150 ,943200 ,943250 ,943300 ,943350 ,943400 ,943450 ,943500 ,943550 ,943600 ,943650 ,943700 ,943750 ,943800 ,943850 ,943900 ,943950 ,944000 ,944050 ,944100 ,944150 ,944200 ,944250 ,944300 ,944350 ,944400 ,944450 ,944500 ,944550 ,944600 ,944650 ,944700 ,944750 ,944800 ,944850 ,944900 ,944950 ,945000 ,945050 ,945100 ,945150 ,945200 ,945250 ,945300 ))\n" - + "\t\t\t\tOR (t1.id IN (945350 ,945400 ,945450 ,945500 ,945550 ,945600 ,945650 ,945700 ,945750 ,945800 ,945850 ,945900 ,945950 ,946000 ,946050 ,946100 ,946150 ,946200 ,946250 ,946300 ,946350 ,946400 ,946450 ,946500 ,946550 ,946600 ,946650 ,946700 ,946750 ,946800 ,946850 ,946900 ,946950 ,947000 ,947050 ,947100 ,947150 ,947200 ,947250 ,947300 ,947350 ,947400 ,947450 ,947500 ,947550 ,947600 ,947650 ,947700 ,947750 ,947800 ,947850 ,947900 ,947950 ,948000 ,948050 ,948100 ,948150 ,948200 ,948250 ,948300 ,948350 ,948400 ,948450 ,948500 ,948550 ,948600 ,948650 ,948700 ,948750 ,948800 ,948850 ,948900 ,948950 ,949000 ,949050 ,949100 ,949150 ,949200 ,949250 ,949300 ,949350 ,949400 ,949450 ,949500 ,949550 ,949600 ,949650 ,949700 ,949750 ,949800 ,949850 ,949900 ,949950 ,950000 ,950050 ,950100 )))\n" - + "\t\t\t\tOR (t1.id IN (950150 ,950200 ,950250 ,950300 ,950350 ,950400 ,950450 ,950500 ,950550 ,950600 ,950650 ,950700 ,950750 ,950800 ,950850 ,950900 ,950950 ,951000 ,951050 ,951100 ,951150 ,951200 ,951250 ,951300 ,951350 ,951400 ,951450 ,951500 ,951550 ,951600 ,951650 ,951700 ,951750 ,951800 ,951850 ,951900 ,951950 ,952000 ,952050 ,952100 ,952150 ,952200 ,952250 ,952300 ,952350 ,952400 ,952450 ,952500 ,952550 ,952600 ,952650 ,952700 ,952750 ,952800 ,952850 ,952900 ,952950 ,953000 ,953050 ,953100 ,953150 ,953200 ,953250 ,953300 ,953350 ,953400 ,953450 ,953500 ,953550 ,953600 ,953650 ,953700 )))\n" - + "\t\t\t\tOR (t1.id IN (953750 ,953800 ,953850 ,953900 ,953950 ,954000 ,954050 ,954100 ,954150 ,954200 ,954250 ,954300 ,954350 ,954400 ,954450 ,954500 ,954550 ,954600 ,954650 ,954700 ,954750 ,954800 ,954850 ,954900 ,954950 ,955000 ,955050 ,955100 ,955150 ,955200 ,955250 ,955300 ,955350 ,955400 ,955450 ,955500 ,955550 ,955600 ,955650 ,955700 ,955750 ,955800 ,955850 ,955900 ,955950 ,956000 ,956050 ,956100 ,956150 ,956200 ,956250 ,956300 ,956350 ,956400 ,956450 ,956500 ,956550 ,956600 ,956650 ,956700 ,956750 ,956800 ,956850 ,956900 ,956950 ,957000 ,957050 ,957100 ,957150 ,957200 ,957250 ,957300 )))\n" - + "\t\t\t\tOR (t1.id IN (944100, 944150, 944200, 944250, 944300, 944350, 944400, 944450, 944500, 944550, 944600, 944650, 944700, 944750, 944800, 944850, 944900, 944950, 945000 )))\n" - + "\t\t\t\tOR (t1.id IN (957350 ,957400 ,957450 ,957500 ,957550 ,957600 ,957650 ,957700 ,957750 ,957800 ,957850 ,957900 ,957950 ,958000 ,958050 ,958100 ,958150 ,958200 ,958250 ,958300 ,958350 ,958400 ,958450 ,958500 ,958550 ,958600 ,958650 ,958700 ,958750 ,958800 ,958850 ,958900 ,958950 ,959000 ,959050 ,959100 ,959150 ,959200 ,959250 ,959300 ,959350 ,959400 ,959450 ,959500 ,959550 ,959600 ,959650 ,959700 ,959750 ,959800 ,959850 ,959900 ,959950 ,960000 ,960050 ,960100 ,960150 ,960200 ,960250 ,960300 ,960350 ,960400 ,960450 ,960500 ,960550 ,960600 ,960650 ,960700 ,960750 ,960800 ,960850 ,960900 ,960950 ,961000 ,961050 ,961100 ,961150 ,961200 ,961250 ,961300 ,961350 ,961400 ,961450 ,961500 ,961550 ,961600 ,961650 ,961700 ,961750 ,961800 ,961850 ,961900 ,961950 ,962000 ,962050 ,962100 ))))\n" - + "\t\t\t\tOR (t1.id IN (962150 ,962200 ,962250 ,962300 ,962350 ,962400 ,962450 ,962500 ,962550 ,962600 ,962650 ,962700 ,962750 ,962800 ,962850 ,962900 ,962950 ,963000 ,963050 ,963100 ,963150 ,963200 ,963250 ,963300 ,963350 ,963400 ,963450 ,963500 ,963550 ,963600 ,963650 ,963700 ,963750 ,963800 ,963850 ,963900 ,963950 ,964000 ,964050 ,964100 ,964150 ,964200 ,964250 ,964300 ,964350 ,964400 ,964450 ,964500 ,964550 ,964600 ,964650 ,964700 ,964750 ,964800 ,964850 ,964900 ,964950 ,965000 ,965050 ,965100 ,965150 ,965200 ,965250 ,965300 ,965350 ,965400 ,965450 ,965500 ))))\n" - + "\tAND t1.COL3 IN (\n" + "\t SELECT\n" + "\t\t t2.COL3\n" + "\t FROM\n" - + "\t\t TABLE_6 t6,\n" + "\t\t TABLE_1 t5,\n" + "\t\t TABLE_4 t4,\n" - + "\t\t TABLE_3 t3,\n" + "\t\t TABLE_1 t2\n" + "\t WHERE\n" - + "\t\t (((((((t5.CAL3 = T6.id)\n" + "\t\t\t AND (t5.CAL5 = t6.CAL5))\n" - + "\t\t\t AND (t5.CAL1 = t6.CAL1))\n" + "\t\t\t AND (t3.CAL1 IN (108500)))\n" - + "\t\t\t AND (t5.id = t2.id))\n" - + "\t\t\t AND NOT ((t6.CAL6 IN ('VALUE'))))\n" - + "\t\t\t AND ((t2.id = t3.CAL2)\n" + "\t\t\t\t AND (t4.id = t3.CAL3))))\n" + // add - // two - // redundant - // unmatched - // brackets - // in - // order - // to - // make - // the - // Simple - // Parser - // fail - // and - // the - // complex - // parser - // stuck - " )) \n" + "ORDER BY\n" + "\tt1.id ASC"; - - MemoryLeakVerifier verifier = new MemoryLeakVerifier(); - - int parallelThreads = Runtime.getRuntime().availableProcessors() + 1; - ExecutorService executorService = Executors.newFixedThreadPool(parallelThreads); - - for (int i = 0; i < parallelThreads; i++) { - executorService.submit(new Runnable() { - @Override - public void run() { - try { - CCJSqlParser parser = - CCJSqlParserUtil.newParser(sqlStr).withAllowComplexParsing(true); - verifier.addObject(parser); - - Statement statement = CCJSqlParserUtil.parseStatement(parser); - } catch (JSQLParserException ignore) { - // We expected that to happen. - } - } - }); - } - executorService.shutdown(); - - // we should not run in any timeout here (because we expect that the Parser has timed out by - // itself) - Assertions.assertDoesNotThrow(new Executable() { - @Override - public void execute() throws Throwable { - executorService.awaitTermination(10, TimeUnit.SECONDS); - } - }); - - // we should not have any Objects left in the weak reference map - verifier.assertGarbageCollected(); - } - @Test public void testWithIsolation() throws JSQLParserException { String statement = "SELECT * FROM mytable WHERE mytable.col = 9 WITH ur"; @@ -5633,4 +5606,97 @@ void testSubSelectParsing() throws JSQLParserException { Assertions.assertEquals("id IN " + sqlStr, inExpression.toString()); } + + @Test + void testLateralView() throws JSQLParserException { + String sqlStr1 = + "SELECT * FROM person\n" + + " LATERAL VIEW EXPLODE(ARRAY(30, 60)) tableName AS c_age\n" + + " LATERAL VIEW EXPLODE(ARRAY(40, 80)) AS d_age"; + + PlainSelect select = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sqlStr1, true); + Assertions.assertEquals(2, select.getLateralViews().size()); + + String sqlStr2 = + "SELECT * FROM person\n" + + " LATERAL VIEW OUTER EXPLODE(ARRAY(30, 60)) AS c_age"; + + select = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sqlStr2, true); + Assertions.assertEquals(1, select.getLateralViews().size()); + + Function function = new Function() + .withName("Explode") + .withParameters(new Function() + .withName("Array") + .withParameters( + new LongValue(30), new LongValue(60))); + LateralView lateralView1 = new LateralView( + true, function, null, new Alias("c_age", true)); + + + select = new PlainSelect() + .addSelectItems(new AllColumns()) + .withFromItem(new Table("person")) + .addLateralView(lateralView1); + assertStatementCanBeDeparsedAs(select, sqlStr2, true); + + Function function2 = new Function() + .withName("Explode") + .withParameters(new Function() + .withName("Array") + .withParameters( + new LongValue(40), new LongValue(80))); + LateralView lateralView2 = SerializationUtils + .clone(lateralView1.withOuter(false).withTableAlias(new Alias("tableName"))) + .withOuter(false) + .withGeneratorFunction(function2) + .withTableAlias(null) + .withColumnAlias(new Alias("d_age", true)); + select.addLateralView(lateralView2); + assertStatementCanBeDeparsedAs(select, sqlStr1, true); + } + + @Test + void testOracleHavingBeforeGroupBy() throws JSQLParserException { + String sqlStr = "SELECT id from a having count(*) > 1 group by id"; + PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); + + Assertions.assertEquals("count(*) > 1", select.getHaving().toString()); + Assertions.assertEquals("GROUP BY id", select.getGroupBy().toString()); + } + + @Test + void testParameterMultiPartName() throws JSQLParserException { + String sqlStr = "SELECT 1 FROM dual WHERE a = :paramMap.aValue"; + PlainSelect select = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + assertTrue(select + .getWhere(EqualsTo.class) + .getRightExpression(JdbcNamedParameter.class) + .getName() + .equals("paramMap.aValue")); + } + + @Test + void testInnerJoin() throws JSQLParserException { + String sqlStr = "SELECT 1 from a inner join b on a.id=b.id"; + PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); + + Join join = select.getJoins().get(0); + + assertTrue(join.isInnerJoin()); + assertTrue(join.withInner(false).isInnerJoin()); + assertFalse(join.withLeft(true).isInnerJoin()); + assertFalse(join.withRight(true).isInnerJoin()); + assertFalse(join.withInner(true).isRight()); + } + + @Test + void testArrayColumnsIssue1757() throws JSQLParserException { + String sqlStr = "SELECT my_map['my_key'] FROM my_table WHERE id = 123"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT cast(my_map['my_key'] as int) FROM my_table WHERE id = 123"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SelectXMLSerializeTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SelectXMLSerializeTest.java index d58dcfe50..b4dfa7c41 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectXMLSerializeTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectXMLSerializeTest.java @@ -10,9 +10,10 @@ package net.sf.jsqlparser.statement.select; import net.sf.jsqlparser.JSQLParserException; -import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; import org.junit.jupiter.api.Test; +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; + /** * * @author tobens @@ -21,31 +22,38 @@ public class SelectXMLSerializeTest { @Test public void testXmlAgg1() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("SELECT xmlserialize(xmlagg(xmltext(COMMENT_LINE) ORDER BY COMMENT_SEQUENCE) AS varchar (1024)) FROM mytable GROUP BY COMMENT_NUMBER"); + assertSqlCanBeParsedAndDeparsed( + "SELECT xmlserialize(xmlagg(xmltext(COMMENT_LINE) ORDER BY COMMENT_SEQUENCE) AS varchar (1024)) FROM mytable GROUP BY COMMENT_NUMBER"); } @Test public void testXmlAgg2() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("SELECT xmlserialize(xmlagg(xmltext(COMMENT_LINE) ORDER BY COMMENT_SEQUENCE, COMMENT_LINE) AS varchar (1024)) FROM mytable GROUP BY COMMENT_NUMBER"); + assertSqlCanBeParsedAndDeparsed( + "SELECT xmlserialize(xmlagg(xmltext(COMMENT_LINE) ORDER BY COMMENT_SEQUENCE, COMMENT_LINE) AS varchar (1024)) FROM mytable GROUP BY COMMENT_NUMBER"); } @Test public void testXmlAgg3() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("SELECT xmlserialize(xmlagg(xmltext(COMMENT_LINE) ORDER BY COMMENT_SEQUENCE) AS varchar (1024))"); + assertSqlCanBeParsedAndDeparsed( + "SELECT xmlserialize(xmlagg(xmltext(COMMENT_LINE) ORDER BY COMMENT_SEQUENCE) AS varchar (1024))"); } @Test public void testXmlAgg4() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("SELECT xmlserialize(xmlagg(xmltext(COMMENT_LINE_PREFIX || COMMENT_LINE) ORDER BY COMMENT_SEQUENCE) AS varchar (1024))"); + assertSqlCanBeParsedAndDeparsed( + "SELECT xmlserialize(xmlagg(xmltext(COMMENT_LINE_PREFIX || COMMENT_LINE) ORDER BY COMMENT_SEQUENCE) AS varchar (1024))"); } @Test public void testXmlAgg5() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("SELECT xmlserialize(xmlagg(xmltext(CONCAT(', ', TRIM(SOME_COLUMN))) ORDER BY MY_SEQUENCE) AS varchar (1024))"); + assertSqlCanBeParsedAndDeparsed( + "SELECT xmlserialize(xmlagg(xmltext(CONCAT(', ', TRIM(SOME_COLUMN))) ORDER BY MY_SEQUENCE) AS varchar (1024))", + true); } @Test public void testXmlAgg6() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("SELECT xmlserialize(xmlagg(xmltext(COMMENT_LINE)) AS varchar (1024))"); + assertSqlCanBeParsedAndDeparsed( + "SELECT xmlserialize(xmlagg(xmltext(COMMENT_LINE)) AS varchar (1024))"); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java index 15b94009f..6d2b4a1a8 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java @@ -82,12 +82,15 @@ public class SpecialOracleTest { "datetime02.sql", "datetime04.sql", "datetime05.sql", "datetime06.sql", "dblink01.sql", "for_update01.sql", "for_update02.sql", "for_update03.sql", "function04.sql", "function05.sql", "for_update04.sql", "for_update05.sql", "for_update06.sql", - "for_update08.sql", "function01.sql", "function02.sql", "groupby01.sql", + "for_update08.sql", "function01.sql", "function02.sql", "function03.sql", + "function06.sql", + "groupby01.sql", "groupby02.sql", "groupby03.sql", "groupby04.sql", "groupby05.sql", "groupby06.sql", "groupby08.sql", "groupby09.sql", "groupby10.sql", "groupby11.sql", "groupby12.sql", "groupby13.sql", "groupby14.sql", "groupby15.sql", "groupby16.sql", "groupby17.sql", "groupby19.sql", "groupby20.sql", "groupby21.sql", "groupby22.sql", "groupby23.sql", - "insert02.sql", "interval02.sql", "interval04.sql", "interval05.sql", "join01.sql", + "insert02.sql", "insert11.sql", "insert12.sql", "interval02.sql", "interval04.sql", + "interval05.sql", "join01.sql", "join02.sql", "join03.sql", "join04.sql", "join06.sql", "join07.sql", "join08.sql", "join09.sql", "join10.sql", "join11.sql", "join12.sql", "join13.sql", "join14.sql", "join15.sql", "join16.sql", "join17.sql", "join18.sql", "join19.sql", "join20.sql", 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 fb830110d..bfebcdf37 100644 --- a/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java @@ -9,7 +9,6 @@ */ package net.sf.jsqlparser.statement.update; -import java.io.StringReader; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.DoubleValue; import net.sf.jsqlparser.expression.JdbcParameter; @@ -19,14 +18,17 @@ import net.sf.jsqlparser.parser.CCJSqlParserManager; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.schema.Column; -import static net.sf.jsqlparser.test.TestUtils.*; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; + +import static net.sf.jsqlparser.test.TestUtils.assertOracleHintExists; +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; - public class UpdateTest { private static final CCJSqlParserManager PARSER_MANAGER = new CCJSqlParserManager(); @@ -40,9 +42,11 @@ public void testUpdate() throws JSQLParserException { assertEquals("col1", update.getUpdateSets().get(0).getColumns().get(0).getColumnName()); assertEquals("col2", update.getUpdateSets().get(1).getColumns().get(0).getColumnName()); assertEquals("col3", update.getUpdateSets().get(2).getColumns().get(0).getColumnName()); - assertEquals("as", ((StringValue) update.getUpdateSets().get(0).getExpressions().get(0)).getValue()); - assertTrue(update.getUpdateSets().get(1).getExpressions().get(0) instanceof JdbcParameter); - assertEquals(565, ((LongValue) update.getUpdateSets().get(2).getExpressions().get(0)).getValue()); + assertEquals("as", + ((StringValue) update.getUpdateSets().get(0).getValues().get(0)).getValue()); + assertTrue(update.getUpdateSets().get(1).getValues().get(0) instanceof JdbcParameter); + assertEquals(565, + ((LongValue) update.getUpdateSets().get(2).getValues().get(0)).getValue()); assertTrue(update.getWhere() instanceof GreaterThanEquals); } @@ -55,38 +59,41 @@ public void testUpdateWAlias() throws JSQLParserException { @Test public void testUpdateWithDeparser() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("UPDATE table1 AS A SET A.columna = 'XXX' WHERE A.cod_table = 'YYY'"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE table1 AS A SET A.columna = 'XXX' WHERE A.cod_table = 'YYY'"); } @Test public void testUpdateWithFrom() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("UPDATE table1 SET columna = 5 FROM table1 LEFT JOIN table2 ON col1 = col2"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE table1 SET columna = 5 FROM table1 LEFT JOIN table2 ON col1 = col2"); } @Test public void testUpdateMultiTable() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("UPDATE T1, T2 SET T1.C2 = T2.C2, T2.C3 = 'UPDATED' WHERE T1.C1 = T2.C1 AND T1.C2 < 10"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE T1, T2 SET T1.C2 = T2.C2, T2.C3 = 'UPDATED' WHERE T1.C1 = T2.C1 AND T1.C2 < 10"); } @Test public void testUpdateWithSelect() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("UPDATE NATION SET (N_NATIONKEY) = (SELECT ? FROM SYSIBM.SYSDUMMY1)"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE NATION SET (N_NATIONKEY) = (SELECT ? FROM SYSIBM.SYSDUMMY1)"); } @Test public void testUpdateWithSelect2() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("UPDATE mytable SET (col1, col2, col3) = (SELECT a, b, c FROM mytable2)"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE mytable SET (col1, col2, col3) = (SELECT a, b, c FROM mytable2)"); } @Test public void testUpdateIssue167_SingleQuotes() throws JSQLParserException { - String sqlStr = "UPDATE tablename SET NAME = 'Customer 2', ADDRESS = 'Address \\' ddad2', AUTH_KEY = 'samplekey' WHERE ID = 2"; + String sqlStr = + "UPDATE tablename SET NAME = 'Customer 2', ADDRESS = 'Address \\' ddad2', AUTH_KEY = 'samplekey' WHERE ID = 2"; assertSqlCanBeParsedAndDeparsed( - sqlStr - , true - , parser -> parser.withBackslashEscapeCharacter(true) - ); + sqlStr, true, parser -> parser.withBackslashEscapeCharacter(true)); } @Test @@ -96,33 +103,44 @@ public void testUpdateWithLimit() throws JSQLParserException { @Test public void testUpdateWithOrderBy() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("UPDATE tablename SET col = 'thing' WHERE id = 1 ORDER BY col"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE tablename SET col = 'thing' WHERE id = 1 ORDER BY col"); } @Test public void testUpdateWithOrderByAndLimit() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("UPDATE tablename SET col = 'thing' WHERE id = 1 ORDER BY col LIMIT 10"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE tablename SET col = 'thing' WHERE id = 1 ORDER BY col LIMIT 10"); } @Test public void testUpdateWithReturningAll() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("UPDATE tablename SET col = 'thing' WHERE id = 1 ORDER BY col LIMIT 10 RETURNING *"); - assertSqlCanBeParsedAndDeparsed("UPDATE tablename SET col = 'thing' WHERE id = 1 RETURNING *"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE tablename SET col = 'thing' WHERE id = 1 ORDER BY col LIMIT 10 RETURNING *"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE tablename SET col = 'thing' WHERE id = 1 RETURNING *"); } @Test public void testUpdateWithReturningList() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("UPDATE tablename SET col = 'thing' WHERE id = 1 ORDER BY col LIMIT 10 RETURNING col_1, col_2, col_3"); - assertSqlCanBeParsedAndDeparsed("UPDATE tablename SET col = 'thing' WHERE id = 1 RETURNING col_1, col_2, col_3"); - assertSqlCanBeParsedAndDeparsed("UPDATE tablename SET col = 'thing' WHERE id = 1 ORDER BY col LIMIT 10 RETURNING col_1 AS Bar, col_2 AS Baz, col_3 AS Foo"); - assertSqlCanBeParsedAndDeparsed("UPDATE tablename SET col = 'thing' WHERE id = 1 RETURNING col_1 AS Bar, col_2 AS Baz, col_3 AS Foo"); - assertSqlCanBeParsedAndDeparsed("UPDATE tablename SET col = 'thing' WHERE id = 1 RETURNING ABS(col_1) AS Bar, ABS(col_2), col_3 AS Foo"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE tablename SET col = 'thing' WHERE id = 1 ORDER BY col LIMIT 10 RETURNING col_1, col_2, col_3"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE tablename SET col = 'thing' WHERE id = 1 RETURNING col_1, col_2, col_3"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE tablename SET col = 'thing' WHERE id = 1 ORDER BY col LIMIT 10 RETURNING col_1 AS Bar, col_2 AS Baz, col_3 AS Foo"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE tablename SET col = 'thing' WHERE id = 1 RETURNING col_1 AS Bar, col_2 AS Baz, col_3 AS Foo"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE tablename SET col = 'thing' WHERE id = 1 RETURNING ABS(col_1) AS Bar, ABS(col_2), col_3 AS Foo"); } @Test public void testUpdateDoesNotAllowLimitOffset() { - String statement = "UPDATE table1 A SET A.columna = 'XXX' WHERE A.cod_table = 'YYY' LIMIT 3,4"; - assertThrows(JSQLParserException.class, () -> PARSER_MANAGER.parse(new StringReader(statement))); + String statement = + "UPDATE table1 A SET A.columna = 'XXX' WHERE A.cod_table = 'YYY' LIMIT 3,4"; + assertThrows(JSQLParserException.class, + () -> PARSER_MANAGER.parse(new StringReader(statement))); } @Test @@ -163,31 +181,36 @@ public void testUpdateIssue826() throws JSQLParserException { @Test public void testUpdateIssue750() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("update a,(select * from c) b set a.id=b.id where a.id=b.id", true); + assertSqlCanBeParsedAndDeparsed( + "update a,(select * from c) b set a.id=b.id where a.id=b.id", true); } @Test public void testUpdateIssue962Validate() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("UPDATE tbl_user_card SET validate = '1', identityCodeFlag = 1 WHERE id = 9150000293816"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE tbl_user_card SET validate = '1', identityCodeFlag = 1 WHERE id = 9150000293816"); } @Test public void testUpdateVariableAssignment() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("UPDATE transaction_id SET latest_id_wallet = (@cur_id_wallet := latest_id_wallet) + 1"); + assertSqlCanBeParsedAndDeparsed( + "UPDATE transaction_id SET latest_id_wallet = (@cur_id_wallet := latest_id_wallet) + 1"); } @Test public void testOracleHint() throws JSQLParserException { - assertOracleHintExists("UPDATE /*+ SOMEHINT */ mytable set col1='as', col2=?, col3=565 Where o >= 3", true, "SOMEHINT"); + assertOracleHintExists( + "UPDATE /*+ SOMEHINT */ mytable set col1='as', col2=?, col3=565 Where o >= 3", true, + "SOMEHINT"); - //@todo: add a testcase supposed to not finding a misplaced hint - // assertOracleHintExists("UPDATE mytable /*+ SOMEHINT */ set col1='as', col2=?, col3=565 Where o >= 3", true, "SOMEHINT"); + // @todo: add a testcase supposed to not finding a misplaced hint + // assertOracleHintExists("UPDATE mytable /*+ SOMEHINT */ set col1='as', col2=?, col3=565 + // Where o >= 3", true, "SOMEHINT"); } @Test public void testWith() throws JSQLParserException { - String statement - = "" + String statement = "" + "WITH a\n" + " AS (SELECT 1 id_instrument_ref)\n" + " , b\n" @@ -202,34 +225,28 @@ public void testWith() throws JSQLParserException { @Test public void testUpdateSetsIssue1316() throws JSQLParserException { - String sqlStr - = "update test\n" + String sqlStr = "update test\n" + "set (a, b) = (select '1', '2')"; assertSqlCanBeParsedAndDeparsed(sqlStr, true); - sqlStr - = "update test\n" + sqlStr = "update test\n" + "set a = '1'" + " , b = '2'"; assertSqlCanBeParsedAndDeparsed(sqlStr, true); - sqlStr - = "update test\n" + sqlStr = "update test\n" + "set (a, b) = ('1', '2')"; assertSqlCanBeParsedAndDeparsed(sqlStr, true); - sqlStr - = "update test\n" + sqlStr = "update test\n" + "set (a, b) = (values ('1', '2'))"; assertSqlCanBeParsedAndDeparsed(sqlStr, true); - sqlStr - = "update test\n" + sqlStr = "update test\n" + "set (a, b) = (1, (select 2))"; assertSqlCanBeParsedAndDeparsed(sqlStr, true); - sqlStr - = "UPDATE prpjpaymentbill b\n" + sqlStr = "UPDATE prpjpaymentbill b\n" + "SET ( b.packagecode\n" + " , b.packageremark\n" + " , b.agentcode ) = ( SELECT p.payrefreason\n" @@ -247,13 +264,13 @@ public void testUpdateSetsIssue1316() throws JSQLParserException { assertEquals(3, update.getUpdateSets().size()); assertEquals(3, update.getUpdateSets().get(0).getColumns().size()); - assertEquals(1, update.getUpdateSets().get(0).getExpressions().size()); + assertEquals(1, update.getUpdateSets().get(0).getValues().size()); assertEquals(1, update.getUpdateSets().get(1).getColumns().size()); - assertEquals(1, update.getUpdateSets().get(1).getExpressions().size()); + assertEquals(1, update.getUpdateSets().get(1).getValues().size()); assertEquals(1, update.getUpdateSets().get(2).getColumns().size()); - assertEquals(1, update.getUpdateSets().get(2).getExpressions().size()); + assertEquals(1, update.getUpdateSets().get(2).getValues().size()); } @Test @@ -285,32 +302,30 @@ public void testUpdateMultipleModifiers() throws JSQLParserException { public void testUpdateOutputClause() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( "UPDATE /* TOP (10) */ HumanResources.Employee \n" - + "SET VacationHours = VacationHours * 1.25, \n" - + " ModifiedDate = GETDATE() \n" - + "OUTPUT inserted.BusinessEntityID, \n" - + " deleted.VacationHours, \n" - + " inserted.VacationHours, \n" - + " inserted.ModifiedDate \n" - + "INTO @MyTableVar", - true - ); + + "SET VacationHours = VacationHours * 1.25, \n" + + " ModifiedDate = GETDATE() \n" + + "OUTPUT inserted.BusinessEntityID, \n" + + " deleted.VacationHours, \n" + + " inserted.VacationHours, \n" + + " inserted.ModifiedDate \n" + + "INTO @MyTableVar", + true); assertSqlCanBeParsedAndDeparsed( "UPDATE Production.WorkOrder \n" - + "SET ScrapReasonID = 4 \n" - + "OUTPUT deleted.ScrapReasonID, \n" - + " inserted.ScrapReasonID, \n" - + " inserted.WorkOrderID, \n" - + " inserted.ProductID, \n" - + " p.Name \n" - + " INTO @MyTestVar \n" - + "FROM Production.WorkOrder AS wo \n" - + " INNER JOIN Production.Product AS p \n" - + " ON wo.ProductID = p.ProductID \n" - + " AND wo.ScrapReasonID= 16 \n" - + " AND p.ProductID = 733", - true - ); + + "SET ScrapReasonID = 4 \n" + + "OUTPUT deleted.ScrapReasonID, \n" + + " inserted.ScrapReasonID, \n" + + " inserted.WorkOrderID, \n" + + " inserted.ProductID, \n" + + " p.Name \n" + + " INTO @MyTestVar \n" + + "FROM Production.WorkOrder AS wo \n" + + " INNER JOIN Production.Product AS p \n" + + " ON wo.ProductID = p.ProductID \n" + + " AND wo.ScrapReasonID= 16 \n" + + " AND p.ProductID = 733", + true); } @Test @@ -319,9 +334,24 @@ public void testUpdateSetsIssue1590() throws JSQLParserException { assertEquals(1, update.getUpdateSets().size()); update.addColumns(new Column("y")); update.addExpressions(new DoubleValue("6")); - update.getUpdateSets().get(0).setUsingBracketsForColumns(true); - update.getUpdateSets().get(0).setUsingBracketsForValues(true); + + // update.getUpdateSets().get(0).add(new Column("y"), new DoubleValue("6")); assertEquals("UPDATE mytable SET (a, y) = (5, 6) WHERE b = 2", update.toString()); } + + @Test + void testArrayColumnsIssue1083() throws JSQLParserException { + String sqlStr = "SELECT listes[(SELECT cardinality(listes))]"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "update utilisateur set listes[0] = 1"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "update utilisateur set listes[(select cardinality(listes))] = 1"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "update utilisateur set listes[0:3] = (1,2,3,4)"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/upsert/UpsertTest.java b/src/test/java/net/sf/jsqlparser/statement/upsert/UpsertTest.java index 6b206dd24..508a2da03 100644 --- a/src/test/java/net/sf/jsqlparser/statement/upsert/UpsertTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/upsert/UpsertTest.java @@ -16,16 +16,15 @@ import net.sf.jsqlparser.parser.CCJSqlParserManager; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.select.PlainSelect; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.io.StringReader; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; public class UpsertTest { @@ -37,19 +36,15 @@ public void testUpsert() throws JSQLParserException { String statement = "UPSERT INTO TEST (NAME, ID) VALUES ('foo', 123)"; Upsert upsert = (Upsert) parserManager.parse(new StringReader(statement)); assertEquals("TEST", upsert.getTable().getName()); - assertTrue(upsert.isUseValues()); assertEquals(2, upsert.getColumns().size()); assertEquals("NAME", upsert.getColumns().get(0).getColumnName()); assertEquals("ID", upsert.getColumns().get(1).getColumnName()); - assertEquals(2, ((ExpressionList) upsert.getItemsList()).getExpressions().size()); - assertEquals("foo", - ((StringValue) upsert.getItemsList(ExpressionList.class).getExpressions().get(0)) - .getValue()); - assertEquals(123, - ((LongValue) upsert.getItemsList(ExpressionList.class).getExpressions().get(1)) - .getValue()); - assertFalse(upsert.isUseSelectBrackets()); - assertFalse(upsert.isUseDuplicate()); + + ExpressionList expressions = upsert.getValues().getExpressions(); + assertEquals(2, expressions.size()); + assertEquals("foo", ((StringValue) expressions.get(0)).getValue()); + assertEquals(123, ((LongValue) expressions.get(1)).getValue()); + assertNull(upsert.getDuplicateUpdateSets()); assertEquals(statement, "" + upsert); } @@ -60,22 +55,18 @@ public void testUpsertDuplicate() throws JSQLParserException { Upsert upsert = (Upsert) parserManager.parse(new StringReader(statement)); assertEquals("TEST", upsert.getTable().getName()); assertEquals(2, upsert.getColumns().size()); - assertTrue(upsert.isUseValues()); assertEquals("ID", upsert.getColumns().get(0).getColumnName()); assertEquals("COUNTER", upsert.getColumns().get(1).getColumnName()); - assertEquals(2, ((ExpressionList) upsert.getItemsList()).getExpressions().size()); - assertEquals(123, - ((LongValue) upsert.getItemsList(ExpressionList.class).getExpressions().get(0)) - .getValue()); - assertEquals(0, - ((LongValue) upsert.getItemsList(ExpressionList.class).getExpressions().get(1)) - .getValue()); - assertEquals(1, upsert.getDuplicateUpdateColumns().size()); - assertEquals("COUNTER", upsert.getDuplicateUpdateColumns().get(0).getColumnName()); - assertEquals(1, upsert.getDuplicateUpdateExpressionList().size()); - assertEquals("COUNTER + 1", upsert.getDuplicateUpdateExpressionList().get(0).toString()); - assertFalse(upsert.isUseSelectBrackets()); - assertTrue(upsert.isUseDuplicate()); + + ExpressionList expressions = upsert.getValues().getExpressions(); + assertEquals(2, expressions.size()); + assertEquals(123, ((LongValue) expressions.get(0)).getValue()); + assertEquals(0, ((LongValue) expressions.get(1)).getValue()); + assertEquals(1, upsert.getDuplicateUpdateSets().size()); + assertEquals("COUNTER", + upsert.getDuplicateUpdateSets().get(0).getColumns().get(0).getColumnName()); + assertEquals("COUNTER + 1", + upsert.getDuplicateUpdateSets().get(0).getValues().get(0).toString()); assertEquals(statement, "" + upsert); } @@ -86,14 +77,13 @@ public void testUpsertSelect() throws JSQLParserException { Upsert upsert = (Upsert) parserManager.parse(new StringReader(statement)); assertEquals("test.targetTable", upsert.getTable().getFullyQualifiedName()); assertEquals(2, upsert.getColumns().size()); - assertFalse(upsert.isUseValues()); assertEquals("col1", upsert.getColumns().get(0).getColumnName()); assertEquals("col2", upsert.getColumns().get(1).getColumnName()); - assertNull(upsert.getItemsList()); + assertNull(upsert.getExpressions()); assertNotNull(upsert.getSelect()); assertEquals("test.sourceTable", ((Table) ((PlainSelect) upsert.getSelect()).getFromItem()).getFullyQualifiedName()); - assertFalse(upsert.isUseDuplicate()); + assertNull(upsert.getDuplicateUpdateSets()); assertEquals(statement, "" + upsert); } @@ -102,28 +92,25 @@ public void testUpsertN() throws JSQLParserException { String statement = "UPSERT INTO TEST VALUES ('foo', 'bar', 3)"; Upsert upsert = (Upsert) parserManager.parse(new StringReader(statement)); assertEquals("TEST", upsert.getTable().getName()); - assertEquals(3, ((ExpressionList) upsert.getItemsList()).getExpressions().size()); - assertTrue(upsert.isUseValues()); - assertEquals("foo", - ((StringValue) upsert.getItemsList(ExpressionList.class).getExpressions().get(0)) - .getValue()); - assertEquals("bar", - ((StringValue) upsert.getItemsList(ExpressionList.class).getExpressions().get(1)) - .getValue()); - assertEquals(3, - ((LongValue) ((ExpressionList) upsert.getItemsList()).getExpressions().get(2)) - .getValue()); - assertFalse(upsert.isUseSelectBrackets()); - assertFalse(upsert.isUseDuplicate()); + + ExpressionList expressions = upsert.getValues().getExpressions(); + assertEquals(3, expressions.size()); + assertEquals("foo", ((StringValue) expressions.get(0)).getValue()); + assertEquals("bar", ((StringValue) expressions.get(1)).getValue()); + assertEquals(3, ((LongValue) expressions.get(2)).getValue()); + assertNull(upsert.getDuplicateUpdateSets()); assertEquals(statement, "" + upsert); } @Test public void testUpsertMultiRowValue() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("UPSERT INTO mytable (col1, col2) VALUES (a, b), (d, e)"); + assertSqlCanBeParsedAndDeparsed("UPSERT INTO mytable (col1, col2) VALUES (a, b), (d, e)", + true); } @Test + @Disabled + /* not the job of the parser to validate this, it even may be valid eventually */ public void testUpsertMultiRowValueDifferent() throws JSQLParserException { try { assertSqlCanBeParsedAndDeparsed( @@ -137,28 +124,31 @@ public void testUpsertMultiRowValueDifferent() throws JSQLParserException { @Test public void testSimpleUpsert() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( - "UPSERT INTO example (num, name, address, tel) VALUES (1, 'name', 'test ', '1234-1234')"); + "UPSERT INTO example (num, name, address, tel) VALUES (1, 'name', 'test ', '1234-1234')", + true); } @Test public void testUpsertHasSelect() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( - "UPSERT INTO mytable (mycolumn) SELECT mycolumn FROM mytable"); + "UPSERT INTO mytable (mycolumn) SELECT mycolumn FROM mytable", true); assertSqlCanBeParsedAndDeparsed( - "UPSERT INTO mytable (mycolumn) (SELECT mycolumn FROM mytable)"); + "UPSERT INTO mytable (mycolumn) (SELECT mycolumn FROM mytable)", true); } @Test public void testUpsertWithSelect() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( - "UPSERT INTO mytable (mycolumn) WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a"); + "UPSERT INTO mytable (mycolumn) WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a", + true); assertSqlCanBeParsedAndDeparsed( - "UPSERT INTO mytable (mycolumn) (WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a)"); + "UPSERT INTO mytable (mycolumn) (WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a)", + true); } @Test public void testUpsertWithKeywords() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("UPSERT INTO kvPair (value, key) VALUES (?, ?)"); + assertSqlCanBeParsedAndDeparsed("UPSERT INTO kvPair (value, key) VALUES (?, ?)", true); } @Test @@ -179,7 +169,8 @@ public void testHexValues3() throws JSQLParserException { @Test public void testDuplicateKey() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( - "UPSERT INTO Users0 (UserId, Key, Value) VALUES (51311, 'T_211', 18) ON DUPLICATE KEY UPDATE Value = 18"); + "UPSERT INTO Users0 (UserId, Key, Value) VALUES (51311, 'T_211', 18) ON DUPLICATE KEY UPDATE Value = 18", + true); } } 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 d2bdc807d..71718ad56 100644 --- a/src/test/java/net/sf/jsqlparser/statement/values/ValuesTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/values/ValuesTest.java @@ -23,24 +23,28 @@ public class ValuesTest { + @Test + public void testRowConstructor() throws JSQLParserException { + String sqlStr = "VALUES (1,2), (3,4)"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + @Test public void testDuplicateKey() throws JSQLParserException { String statement = "VALUES (1, 2, 'test')"; assertSqlCanBeParsedAndDeparsed(statement); - Values values = new Values().addExpressions(new LongValue(1), - new LongValue(2), new StringValue("test")); + Values values = new Values() + .addExpressions( + new LongValue(1), new LongValue(2), new StringValue("test")); assertDeparse(values, statement); - - // this test does not make much sense, since the Object Tree is not distinct - // there are several different ways to build the statement above - // assertEqualsObjectTree(parsed, created); } @Test 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 != ''"); + "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 != ''", + true); } @Test diff --git a/src/test/java/net/sf/jsqlparser/test/HowToUseSample.java b/src/test/java/net/sf/jsqlparser/test/HowToUseSample.java index 22d16df36..27de73ecb 100644 --- a/src/test/java/net/sf/jsqlparser/test/HowToUseSample.java +++ b/src/test/java/net/sf/jsqlparser/test/HowToUseSample.java @@ -10,7 +10,10 @@ package net.sf.jsqlparser.test; import net.sf.jsqlparser.JSQLParserException; -import net.sf.jsqlparser.expression.*; +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.ExpressionVisitorAdapter; +import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.schema.Column; @@ -19,9 +22,9 @@ import net.sf.jsqlparser.statement.StatementVisitorAdapter; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectExpressionItem; +import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.SelectVisitorAdapter; -import net.sf.jsqlparser.util.deparser.*; +import net.sf.jsqlparser.util.deparser.StatementDeParser; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -31,9 +34,8 @@ public class HowToUseSample { /* SQL Text └─Statements: net.sf.jsqlparser.statement.select.Select - ├─selectItems -> Collection - │ └─selectItems: net.sf.jsqlparser.statement.select.SelectExpressionItem - │ └─LongValue: 1 + ├─selectItems -> Collection + │ └─LongValue: 1 ├─Table: dual └─where: net.sf.jsqlparser.expression.operators.relational.EqualsTo ├─Column: a @@ -46,9 +48,6 @@ void writeSQL() { String expectedSQLStr = "SELECT 1 FROM dual t WHERE a = b"; // Step 1: generate the Java Object Hierarchy for - SelectExpressionItem selectExpressionItem = - new SelectExpressionItem().withExpression(new LongValue().withValue(1)); - Table table = new Table().withName("dual").withAlias(new Alias("t", false)); Column columnA = new Column().withColumnName("a"); @@ -56,7 +55,7 @@ void writeSQL() { Expression whereExpression = new EqualsTo().withLeftExpression(columnA).withRightExpression(columnB); - PlainSelect select = new PlainSelect().addSelectItems(selectExpressionItem) + PlainSelect select = new PlainSelect().addSelectItem(new LongValue(1)) .withFromItem(table).withWhere(whereExpression); // Step 2a: Print into a SQL Statement @@ -79,8 +78,8 @@ public void howToParseStatementDeprecated() throws JSQLParserException { Select select = (Select) statement; PlainSelect plainSelect = (PlainSelect) select.getSelectBody(); - SelectExpressionItem selectExpressionItem = - (SelectExpressionItem) plainSelect.getSelectItems().get(0); + SelectItem selectItem = + (SelectItem) plainSelect.getSelectItems().get(0); Table table = (Table) plainSelect.getFromItem(); @@ -94,23 +93,21 @@ public void howToParseStatementDeprecated() throws JSQLParserException { public void howToParseStatement() throws JSQLParserException { String sqlStr = "select 1 from dual where a=b"; - Statement statement = CCJSqlParserUtil.parse(sqlStr); - if (statement instanceof Select) { - PlainSelect plainSelect = (PlainSelect) statement; + PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); - SelectExpressionItem selectExpressionItem = - (SelectExpressionItem) plainSelect.getSelectItems().get(0); - Assertions.assertEquals(new LongValue(1), selectExpressionItem.getExpression()); + SelectItem selectItem = + select.getSelectItems().get(0); + Assertions.assertEquals( + new LongValue(1), selectItem.getExpression()); - Table table = (Table) plainSelect.getFromItem(); - Assertions.assertEquals("dual", table.getName()); + Table table = (Table) select.getFromItem(); + Assertions.assertEquals("dual", table.getName()); - EqualsTo equalsTo = (EqualsTo) plainSelect.getWhere(); - Column a = (Column) equalsTo.getLeftExpression(); - Column b = (Column) equalsTo.getRightExpression(); - Assertions.assertEquals("a", a.getColumnName()); - Assertions.assertEquals("b", b.getColumnName()); - } + EqualsTo equalsTo = (EqualsTo) select.getWhere(); + Column a = (Column) equalsTo.getLeftExpression(); + Column b = (Column) equalsTo.getRightExpression(); + Assertions.assertEquals("a", a.getColumnName()); + Assertions.assertEquals("b", b.getColumnName()); } @Test @@ -169,4 +166,13 @@ public void howToUseFeatures() throws JSQLParserException { Statement stmt2 = CCJSqlParserUtil.parse(sqlStr, parser -> parser .withSquareBracketQuotation(true).withAllowComplexParsing(true).withTimeOut(6000)); } + + @Test + public void showBracketHandling() throws JSQLParserException { + String sqlStr = " ( (values(1,2), (3,4)) UNION (values((1,2), (3,4))) )"; + Statement statement = CCJSqlParserUtil.parse(sqlStr); + final String reflectionString = TestUtils.toReflectionString(statement); + + System.out.println(reflectionString); + } } diff --git a/src/test/java/net/sf/jsqlparser/test/TestUtils.java b/src/test/java/net/sf/jsqlparser/test/TestUtils.java index c4745c91a..1554026ac 100644 --- a/src/test/java/net/sf/jsqlparser/test/TestUtils.java +++ b/src/test/java/net/sf/jsqlparser/test/TestUtils.java @@ -108,7 +108,8 @@ public static void assertStatementCanBeDeparsedAs(Statement parsed, String state String sanitizedInputSqlStr = buildSqlString(parsed.toString(), laxDeparsingCheck); String sanitizedStatementStr = buildSqlString(statement, laxDeparsingCheck); - assertEquals(sanitizedStatementStr, sanitizedInputSqlStr); + assertEquals(sanitizedStatementStr, sanitizedInputSqlStr, + "Output from toString() does not match."); // Export all the Test SQLs to /tmp/net/sf/jsqlparser boolean exportToFile = Boolean.parseBoolean(System.getenv("EXPORT_TEST_TO_FILE")); @@ -121,7 +122,8 @@ public static void assertStatementCanBeDeparsedAs(Statement parsed, String state String sanitizedDeparsedStr = buildSqlString(builder.toString(), laxDeparsingCheck); - assertEquals(sanitizedStatementStr, sanitizedDeparsedStr); + assertEquals(sanitizedStatementStr, sanitizedDeparsedStr, + "Output from Deparser does not match."); } private static void writeTestToFile(String sanitizedInputSqlStr) { diff --git a/src/test/java/net/sf/jsqlparser/util/APISanitationTest.java b/src/test/java/net/sf/jsqlparser/util/APISanitationTest.java new file mode 100644 index 000000000..89efa2651 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/util/APISanitationTest.java @@ -0,0 +1,400 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.util; + +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.Function; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; +import net.sf.jsqlparser.schema.Column; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.File; +import java.io.FileReader; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.TreeSet; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +interface Visitor { + /** + * @return {@code true} if the algorithm should visit more results, {@code false} if it should + * terminate now. + */ + boolean visit(T t); +} + + +public class APISanitationTest { + private final static TreeSet> CLASSES = new TreeSet<>(new Comparator>() { + @Override + public int compare(Class o1, Class o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + + private final static Logger LOGGER = Logger.getLogger(APISanitationTest.class.getName()); + private final static Class[] EXPRESSION_CLASSES = + new Class[] {Expression.class, Column.class, Function.class}; + + public static void findClasses(Visitor visitor) { + String classpath = System.getProperty("java.class.path"); + String[] paths = classpath.split(System.getProperty("path.separator")); + for (String path : paths) { + File file = new File(path); + if (file.exists()) { + findClasses(file, file, visitor); + } + } + } + + private static boolean findClasses(File root, File file, Visitor visitor) { + if (file.isDirectory()) { + for (File child : Objects.requireNonNull(file.listFiles())) { + if (!findClasses(root, child, visitor)) { + return false; + } + } + } else if (file.getName().toLowerCase().endsWith(".class")) { + return visitor.visit(createClassName(root, file)); + } + + return true; + } + + private static String createClassName(File root, File file) { + StringBuilder sb = new StringBuilder(); + String fileName = file.getName(); + sb.append(fileName, 0, fileName.lastIndexOf(".class")); + File file1 = file.getParentFile(); + while (file1 != null && !file1.equals(root)) { + sb.insert(0, '.').insert(0, file1.getName()); + file1 = file1.getParentFile(); + } + return sb.toString(); + } + + /** + * find all classes belonging to JSQLParser + * + */ + + @BeforeAll + static void findRelevantClasses() { + findClasses(new Visitor() { + @Override + public boolean visit(String clazz) { + if (clazz.startsWith("net.sf.jsqlparser.statement") + || clazz.startsWith("net.sf.jsqlparser.expression") + || clazz.startsWith("net.sf.jsqlparser.schema")) { + + int lastDotIndex = clazz.lastIndexOf("."); + int last$Index = clazz.lastIndexOf("$"); + + String className = last$Index > 0 + ? clazz.substring(lastDotIndex, last$Index) + : clazz.substring(lastDotIndex); + + if (!(className.toLowerCase().startsWith("test") + || className.toLowerCase().endsWith("test"))) { + try { + CLASSES.add(Class.forName(clazz)); + } catch (ClassNotFoundException e) { + LOGGER.log(Level.SEVERE, "Class not found", e); + } + } + } + return true; // return false if you don't want to see any more classes + } + }); + } + + /** + * find all field declarations for the classes belonging to JSQLParser + * + * @return the stream of fields + */ + + private static Stream fields() { + TreeSet fields = new TreeSet<>(new Comparator() { + @Override + public int compare(Field o1, Field o2) { + return o1.toString().compareTo(o2.toString()); + } + }); + + for (Class clazz : CLASSES) { + // no enums + if (!clazz.isEnum()) { + for (Field field : clazz.getDeclaredFields()) { + // no final fields + if ((field.getModifiers() & Modifier.FINAL) != Modifier.FINAL) { + fields.add(field); + } + } + } + } + + return fields.stream(); + } + + /** + * Checks, if a field has Getters and Setters and Fluent Setter matching the naming conventions + * + * @param field the field to verify + * @throws MethodNamingException a qualified exception pointing on the failing field + */ + + @ParameterizedTest(name = "{index} Field {0}") + @MethodSource("fields") + @Disabled + void testFieldAccess(Field field) throws MethodNamingException { + Class clazz = field.getDeclaringClass(); + String fieldName = field.getName(); + + if (!fieldName.equalsIgnoreCase("$jacocoData")) { + + boolean foundGetter = false; + boolean foundSetter = false; + boolean foundFluentSetter = false; + + for (Method method : clazz.getMethods()) { + String methodName = method.getName(); + Class typeClass = field.getType(); + boolean isBooleanType = + typeClass.equals(Boolean.class) || typeClass.equals(boolean.class); + + foundGetter |= ("get" + fieldName).equalsIgnoreCase(methodName) + | (isBooleanType && ("is" + fieldName).equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("is") + && fieldName.equalsIgnoreCase(methodName)) + | (isBooleanType && ("has" + fieldName).equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("has") + && fieldName.equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("use") + && ("isUsing" + fieldName.substring("use".length())) + .equalsIgnoreCase(methodName)); + + foundSetter |= ("set" + fieldName).equalsIgnoreCase(methodName) + | (isBooleanType && fieldName.startsWith("is") + && ("set" + fieldName.substring("is".length())) + .equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("has") + && ("set" + fieldName.substring("has".length())) + .equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("has") + && ("setHas" + fieldName.substring("has".length())) + .equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("has") + && ("setHaving" + fieldName.substring("has".length())) + .equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("use") + && ("set" + fieldName.substring("use".length())) + .equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("use") + && ("setUse" + fieldName.substring("use".length())) + .equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("use") + && ("setUsing" + fieldName.substring("use".length())) + .equalsIgnoreCase(methodName)); + + foundFluentSetter |= ("with" + fieldName).equalsIgnoreCase(methodName) + | (isBooleanType && fieldName.startsWith("is") + && ("with" + fieldName.substring("is".length())) + .equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("has") + && ("with" + fieldName.substring("has".length())) + .equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("has") + && ("withHas" + fieldName.substring("has".length())) + .equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("has") + && ("withHaving" + fieldName.substring("has".length())) + .equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("use") + && ("with" + fieldName.substring("use".length())) + .equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("use") + && ("withUse" + fieldName.substring("use".length())) + .equalsIgnoreCase(methodName)) + | (isBooleanType && fieldName.startsWith("use") + && ("withUsing" + fieldName.substring("use".length())) + .equalsIgnoreCase(methodName)); + } + + if (!(foundGetter && foundSetter && foundFluentSetter)) { + String message = fieldName + " " + + (!foundGetter ? "[Getter] " : "") + + (!foundSetter ? "[Setter] " : "") + + (!foundFluentSetter ? "[Fluent Setter] " : "") + + "missing"; + throwException(field, clazz, message); + } + } + } + + /** + * Test if a field declaration extends a certain class. + * + * @param field the declared field + * @param boundClass the class, which the declaration extends + * @return whether the field extends the class + */ + + boolean testGenericType(Field field, Class boundClass) { + Type listType = field.getGenericType(); + if (listType instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) listType; + for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) { + if (actualTypeArgument instanceof Class) { + Class elementClass = (Class) actualTypeArgument; + if (elementClass.isAssignableFrom(boundClass)) { + return true; + } + } + } + } + + Type superclassType = field.getType().getGenericSuperclass(); + ParameterizedType parameterizedType = (ParameterizedType) superclassType; + if (parameterizedType != null) { + for (final Type actualTypeArgument : parameterizedType.getActualTypeArguments()) { + if (actualTypeArgument instanceof TypeVariable) { + final TypeVariable typeVariable = + (TypeVariable) actualTypeArgument; + for (Type type : typeVariable.getBounds()) { + if (type.getTypeName().equals(boundClass.getTypeName())) { + return true; + } + } + } + } + } + return false; + } + + /** + * Scan for any occurrence of List and throw an Exception. + * + * @param field the field to test for List + * @throws MethodNamingException the Exception pointing on the Class and location of the field + */ + + @ParameterizedTest(name = "{index} Field {0}") + @MethodSource("fields") + @SuppressWarnings({"PMD.NPath"}) + void testExpressionList(final Field field) throws MethodNamingException { + Class clazz = field.getType(); + String fieldName = field.getName(); + + if (!fieldName.equalsIgnoreCase("$jacocoData")) { + boolean isExpressionList = false; + for (Class boundClass : EXPRESSION_CLASSES) { + if (Collection.class.isAssignableFrom(clazz) + && !ExpressionList.class.isAssignableFrom(clazz)) { + isExpressionList |= testGenericType(field, boundClass); + } + } + + if (isExpressionList) { + String message = fieldName + " is an Expression List"; + throwException(field, clazz, message); + } + } + } + + /** + * Find the declaration of the offending field and throws a qualified exception. + * + * @param field the offending field + * @param clazz the offending class declaring the field + * @param message the information about the offense + * @throws MethodNamingException the qualified exception pointing on the location + */ + + private static void throwException(Field field, Class clazz, String message) + throws MethodNamingException { + String fieldName = field.getName(); + String pureFieldName = fieldName.lastIndexOf("$") > 0 + ? fieldName.substring(fieldName.lastIndexOf("$")) + : fieldName; + Class declaringClazz = field.getDeclaringClass(); + while (declaringClazz.getDeclaringClass() != null) { + declaringClazz = declaringClazz.getDeclaringClass(); + } + String pureDeclaringClassName = declaringClazz.getCanonicalName(); + + File file = new File( + "src/main/java/" + + pureDeclaringClassName.replace(".", "/") + .concat(".java")); + + int position = 1; + Pattern pattern = Pattern.compile( + "\\s" + field.getType().getSimpleName() + "(<\\w*>)?(\\s*\\w*,?)*\\s*\\W", + Pattern.MULTILINE); + try (FileReader reader = new FileReader(file)) { + List lines = IOUtils.readLines(reader); + StringBuilder builder = new StringBuilder(); + for (String s : lines) { + builder.append(s).append("\n"); + } + final Matcher matcher = pattern.matcher(builder); + while (matcher.find()) { + String group0 = matcher.group(0); + if (group0.contains(pureFieldName) + && (group0.endsWith("=") || group0.endsWith(";"))) { + int pos = matcher.start(0); + int readCharacters = 0; + for (String line : lines) { + readCharacters += line.length() + 1; + if (readCharacters >= pos) { + break; + } + position++; + } + break; + } + } + } catch (Exception ex) { + LOGGER.warning( + "Could not find the field " + fieldName + " for " + clazz.getName()); + } + + StackTraceElement stackTraceElement = new StackTraceElement( + field.getDeclaringClass().getName(), fieldName, + file.toURI().normalize().toASCIIString(), + position); + + throw new MethodNamingException(message, stackTraceElement); + } + + public static class MethodNamingException extends Exception { + public MethodNamingException(String message, StackTraceElement stackTrace) { + super(message); + super.setStackTrace(new StackTraceElement[] {stackTrace}); + } + } +} diff --git a/src/test/java/net/sf/jsqlparser/util/SelectUtilsTest.java b/src/test/java/net/sf/jsqlparser/util/SelectUtilsTest.java index 64cff137f..f0e34605e 100644 --- a/src/test/java/net/sf/jsqlparser/util/SelectUtilsTest.java +++ b/src/test/java/net/sf/jsqlparser/util/SelectUtilsTest.java @@ -21,7 +21,6 @@ import net.sf.jsqlparser.statement.select.Join; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectExpressionItem; import org.junit.jupiter.api.Test; import java.util.Arrays; @@ -79,8 +78,7 @@ public void testBuildSelectFromTableAndParsedExpression() throws JSQLParserExcep .buildSelectFromTableAndExpressions(new Table("mytable"), "a+b", "test"); assertEquals("SELECT a + b, test FROM mytable", select.toString()); - assertTrue(((SelectExpressionItem) select - .getSelectItems().get(0)).getExpression() instanceof Addition); + assertTrue(select.getSelectItems().get(0).getExpression() instanceof Addition); } @Test diff --git a/src/test/java/net/sf/jsqlparser/util/deparser/ExecuteDeParserTest.java b/src/test/java/net/sf/jsqlparser/util/deparser/ExecuteDeParserTest.java index 4996ea923..83ef5b102 100644 --- a/src/test/java/net/sf/jsqlparser/util/deparser/ExecuteDeParserTest.java +++ b/src/test/java/net/sf/jsqlparser/util/deparser/ExecuteDeParserTest.java @@ -9,16 +9,19 @@ */ package net.sf.jsqlparser.util.deparser; -import java.util.ArrayList; -import java.util.List; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.JdbcParameter; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; import net.sf.jsqlparser.statement.execute.Execute; import net.sf.jsqlparser.statement.execute.Execute.ExecType; -import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.mock; @@ -42,13 +45,13 @@ public void shouldDeParseExecute() { Execute execute = new Execute(); String name = "name"; - List expressions = new ArrayList<>(); + ParenthesedExpressionList expressions = new ParenthesedExpressionList(); expressions.add(new JdbcParameter()); expressions.add(new JdbcParameter()); execute.withName(name) - .withExecType(ExecType.EXECUTE).withParenthesis(true) - .withExprList(new ExpressionList().withExpressions(expressions)); + .withExecType(ExecType.EXECUTE) + .withExprList(expressions); executeDeParser.deParse(execute); diff --git a/src/test/java/net/sf/jsqlparser/util/deparser/ExpressionDeParserTest.java b/src/test/java/net/sf/jsqlparser/util/deparser/ExpressionDeParserTest.java index 7796782b4..15c74e520 100644 --- a/src/test/java/net/sf/jsqlparser/util/deparser/ExpressionDeParserTest.java +++ b/src/test/java/net/sf/jsqlparser/util/deparser/ExpressionDeParserTest.java @@ -9,8 +9,6 @@ */ package net.sf.jsqlparser.util.deparser; -import java.util.ArrayList; -import java.util.List; import net.sf.jsqlparser.expression.AnalyticExpression; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.KeepExpression; @@ -18,18 +16,22 @@ import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.SelectVisitor; -import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.will; import org.mockito.Mock; -import static org.mockito.Mockito.mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.stubbing.Answer; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.will; +import static org.mockito.Mockito.mock; + @ExtendWith(MockitoExtension.class) public class ExpressionDeParserTest { @@ -142,22 +144,23 @@ public void shouldDeParseComplexAnalyticExpressionWithKeep() { public void shouldDeParseComplexAnalyticExpressionWithPartitionExpressionList() { AnalyticExpression analyticExpression = new AnalyticExpression(); ExpressionList partitionExpressionList = new ExpressionList(); - List partitionExpressions = new ArrayList(); Expression partitionExpression1 = mock(Expression.class); Expression partitionExpression2 = mock(Expression.class); analyticExpression.setName("name"); analyticExpression.setPartitionExpressionList(partitionExpressionList); - partitionExpressionList.setExpressions(partitionExpressions); - partitionExpressions.add(partitionExpression1); - partitionExpressions.add(partitionExpression2); + partitionExpressionList.add(partitionExpression1); + partitionExpressionList.add(partitionExpression2); - will(appendToBuffer("partition expression 1")).given(partitionExpression1).accept(expressionDeParser); - will(appendToBuffer("partition expression 2")).given(partitionExpression2).accept(expressionDeParser); + will(appendToBuffer("partition expression 1")).given(partitionExpression1) + .accept(expressionDeParser); + will(appendToBuffer("partition expression 2")).given(partitionExpression2) + .accept(expressionDeParser); expressionDeParser.visit(analyticExpression); - assertEquals("name() OVER (PARTITION BY partition expression 1, partition expression 2 )", buffer.toString()); + assertEquals("name() OVER (PARTITION BY partition expression 1, partition expression 2 )", + buffer.toString()); } @Test @@ -172,12 +175,15 @@ public void shouldDeParseAnalyticExpressionWithOrderByElements() { orderByElements.add(orderByElement1); orderByElements.add(orderByElement2); - will(appendToBuffer("order by element 1")).given(orderByDeParser).deParseElement(orderByElement1); - will(appendToBuffer("order by element 2")).given(orderByDeParser).deParseElement(orderByElement2); + will(appendToBuffer("order by element 1")).given(orderByDeParser) + .deParseElement(orderByElement1); + will(appendToBuffer("order by element 2")).given(orderByDeParser) + .deParseElement(orderByElement2); expressionDeParser.visit(analyticExpression); - assertEquals("name() OVER (ORDER BY order by element 1, order by element 2)", buffer.toString()); + assertEquals("name() OVER (ORDER BY order by element 1, order by element 2)", + buffer.toString()); } @Test @@ -194,13 +200,16 @@ public void shouldDeParseAnalyticExpressionWithWindowElement() { orderByElements.add(orderByElement1); orderByElements.add(orderByElement2); - will(appendToBuffer("order by element 1")).given(orderByDeParser).deParseElement(orderByElement1); - will(appendToBuffer("order by element 2")).given(orderByDeParser).deParseElement(orderByElement2); + will(appendToBuffer("order by element 1")).given(orderByDeParser) + .deParseElement(orderByElement1); + will(appendToBuffer("order by element 2")).given(orderByDeParser) + .deParseElement(orderByElement2); given(windowElement.toString()).willReturn("window element"); expressionDeParser.visit(analyticExpression); - assertEquals("name() OVER (ORDER BY order by element 1, order by element 2 window element)", buffer.toString()); + assertEquals("name() OVER (ORDER BY order by element 1, order by element 2 window element)", + buffer.toString()); } private Answer appendToBuffer(final String string) { 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 1d83be12a..e0f2d0b97 100644 --- a/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java +++ b/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java @@ -22,7 +22,6 @@ import net.sf.jsqlparser.statement.delete.Delete; import net.sf.jsqlparser.statement.execute.Execute; import net.sf.jsqlparser.statement.insert.Insert; -import net.sf.jsqlparser.statement.replace.Replace; import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.ParenthesedSelect; import net.sf.jsqlparser.statement.select.PlainSelect; @@ -39,6 +38,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static org.mockito.BDDMockito.then; @@ -94,12 +94,15 @@ public void shouldUseProvidedDeparsersWhenDeParsingDelete() { public void shouldUseProvidedDeparsersWhenDeParsingInsert() { Insert insert = new Insert(); Table table = new Table(); - List duplicateUpdateColumns = new ArrayList(); - List duplicateUpdateExpressionList = new ArrayList(); + List duplicateUpdateSets = new ArrayList<>(); Column duplicateUpdateColumn1 = new Column(); - Column duplicateUpdateColumn2 = new Column(); Expression duplicateUpdateExpression1 = mock(Expression.class); + duplicateUpdateSets.add(new UpdateSet(duplicateUpdateColumn1, duplicateUpdateExpression1)); + + Column duplicateUpdateColumn2 = new Column(); Expression duplicateUpdateExpression2 = mock(Expression.class); + duplicateUpdateSets.add(new UpdateSet(duplicateUpdateColumn2, duplicateUpdateExpression2)); + PlainSelect select = mock(PlainSelect.class); List withItemsList = new ArrayList(); WithItem withItem1 = spy(new WithItem()); @@ -110,14 +113,7 @@ public void shouldUseProvidedDeparsersWhenDeParsingInsert() { insert.setSelect(select); insert.setTable(table); - insert.setUseDuplicate(true); - insert.setDuplicateUpdateColumns(duplicateUpdateColumns); - insert.setDuplicateUpdateExpressionList(duplicateUpdateExpressionList); - duplicateUpdateColumns.add(duplicateUpdateColumn1); - duplicateUpdateColumns.add(duplicateUpdateColumn2); - duplicateUpdateExpressionList.add(duplicateUpdateExpression1); - duplicateUpdateExpressionList.add(duplicateUpdateExpression2); - insert.setDuplicateUpdateExpressionList(duplicateUpdateExpressionList); + insert.withDuplicateUpdateSets(duplicateUpdateSets); withItemsList.add(withItem1); withItemsList.add(withItem2); withItem1.setSelect(withItem1SubSelect); @@ -132,47 +128,6 @@ public void shouldUseProvidedDeparsersWhenDeParsingInsert() { then(duplicateUpdateExpression1).should().accept(expressionDeParser); } - @Test - @SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") - public void shouldUseProvidedDeParsersWhenDeParsingReplaceWithoutItemsList() { - Replace replace = new Replace(); - Table table = new Table(); - List columns = new ArrayList(); - List expressions = new ArrayList(); - Column column1 = new Column(); - Column column2 = new Column(); - Expression expression1 = mock(Expression.class); - Expression expression2 = mock(Expression.class); - - replace.setTable(table); - replace.setColumns(columns); - replace.setExpressions(expressions); - columns.add(column1); - columns.add(column2); - expressions.add(expression1); - expressions.add(expression2); - - statementDeParser.visit(replace); - - then(expression1).should().accept(expressionDeParser); - then(expression2).should().accept(expressionDeParser); - } - - // @Test - // @SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") - // public void shouldUseProvidedDeParsersWhenDeParsingReplaceWithItemsList() { - // Replace replace = new Replace(); - // Table table = new Table(); - // ItemsList itemsList = mock(ItemsList.class); - // - // replace.setTable(table); - // replace.setItemsList(itemsList); - // - // statementDeParser.visit(replace); - // - // then(itemsList).should().accept(argThat(is(replaceDeParserWithDeParsers(equalTo(expressionDeParser), - // equalTo(selectDeParser))))); - // } @Test @SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") public void shouldUseProvidedDeParsersWhenDeParsingSelect() { @@ -273,13 +228,11 @@ public void shouldUseProvidedDeParsersWhenDeParsingUpdateUsingSelect() { @SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") public void shouldUseProvidedDeParserWhenDeParsingExecute() { Execute execute = new Execute(); - ExpressionList exprList = new ExpressionList(); - List expressions = new ArrayList(); + ExpressionList expressions = new ExpressionList(); Expression expression1 = mock(Expression.class); Expression expression2 = mock(Expression.class); - execute.setExprList(exprList); - exprList.setExpressions(expressions); + execute.setExprList(expressions); expressions.add(expression1); expressions.add(expression2); @@ -294,7 +247,7 @@ public void shouldUseProvidedDeParserWhenDeParsingExecute() { public void shouldUseProvidedDeParserWhenDeParsingSetStatement() { String name = "name"; Expression expression = mock(Expression.class); - ArrayList expressions = new ArrayList<>(); + ExpressionList expressions = new ExpressionList(); expressions.add(expression); SetStatement setStatement = new SetStatement(name, expressions); @@ -341,14 +294,10 @@ public void shouldUseProvidedDeparsersWhenDeParsingUpsertWithExpressionList() { upsert.setSelect(select); upsert.setTable(table); - upsert.setUseDuplicate(true); - upsert.setDuplicateUpdateColumns(duplicateUpdateColumns); - upsert.setDuplicateUpdateExpressionList(duplicateUpdateExpressionList); - duplicateUpdateColumns.add(duplicateUpdateColumn1); - duplicateUpdateColumns.add(duplicateUpdateColumn2); - duplicateUpdateExpressionList.add(duplicateUpdateExpression1); - duplicateUpdateExpressionList.add(duplicateUpdateExpression2); - upsert.setDuplicateUpdateExpressionList(duplicateUpdateExpressionList); + upsert.setDuplicateUpdateSets( + Arrays.asList( + new UpdateSet(duplicateUpdateColumn1, duplicateUpdateExpression1), + new UpdateSet(duplicateUpdateColumn2, duplicateUpdateExpression2))); withItemsList.add(withItem1); withItemsList.add(withItem2); withItem1.setSelect(withItem1SubSelect); diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/ReplaceValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/ReplaceValidatorTest.java index 25f25c7d1..569afd1e8 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/ReplaceValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/ReplaceValidatorTest.java @@ -34,7 +34,9 @@ public void testValidateReplaceNotAllowed() throws JSQLParserException { for (String sql : Arrays.asList("REPLACE mytable SET col1='as', col2=?, col3=565", "REPLACE mytable (col1, col2, col3) VALUES ('as', ?, 565)", "REPLACE mytable (col1, col2, col3) SELECT * FROM mytable3")) { - validateNotAllowed(sql, 1, 1, FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC), Feature.upsert); + validateNotAllowed(sql, 1, 1, + FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC).add(Feature.values), + Feature.upsert); } } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/UpsertValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/UpsertValidatorTest.java index 2e5c3b5f7..ff3b9e466 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/UpsertValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/UpsertValidatorTest.java @@ -37,7 +37,7 @@ public void testValidationExecuteNotSupported() throws Exception { public void testValidationExecuteNotAllowed() throws Exception { for (String sql : Arrays.asList("UPSERT INTO TEST (NAME, ID) VALUES ('foo', 123)", "UPSERT INTO TEST (ID, COUNTER) VALUES (123, 0) ON DUPLICATE KEY UPDATE COUNTER = COUNTER + 1")) { - validateNotAllowed(sql, 1, 1, FeaturesAllowed.DDL, Feature.upsert); + validateNotAllowed(sql, 1, 1, FeaturesAllowed.DDL, Feature.upsert, Feature.values); } } diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/compound_statements03.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/compound_statements03.sql index d75c5a304..b4f2d87e5 100644 --- a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/compound_statements03.sql +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/compound_statements03.sql @@ -15,4 +15,5 @@ BEGIN END --@FAILURE: Encountered unexpected token: "BEGIN" "BEGIN" recorded first on May 27, 2022, 10:29:48 PM ---@FAILURE: Encountered unexpected token: ":" ":" recorded first on 9 Dec 2022, 14:03:29 \ No newline at end of file +--@FAILURE: Encountered unexpected token: ":" ":" recorded first on 9 Dec 2022, 14:03:29 +--@FAILURE: Encountered unexpected token: "INTO" "INTO" recorded first on 4 May 2023, 18:47:18 \ No newline at end of file diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/function03.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/function03.sql index 418386948..0cc752ec1 100644 --- a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/function03.sql +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/function03.sql @@ -12,4 +12,5 @@ from dual ---@FAILURE: Encountered unexpected token: "(" "(" recorded first on Aug 3, 2021, 7:20:08 AM \ No newline at end of file +--@FAILURE: Encountered unexpected token: "(" "(" recorded first on Aug 3, 2021, 7:20:08 AM +--@SUCCESSFULLY_PARSED_AND_DEPARSED first on 30 Apr 2023, 17:27:33 \ No newline at end of file diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/function06.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/function06.sql index d43b91559..546b9439f 100644 --- a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/function06.sql +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/function06.sql @@ -9,4 +9,5 @@ --- call dbms_scheduler.auto_purge ( ) ---@FAILURE: Encountered unexpected token: ")" ")" recorded first on Aug 3, 2021, 7:20:08 AM \ No newline at end of file +--@FAILURE: Encountered unexpected token: ")" ")" recorded first on Aug 3, 2021, 7:20:08 AM +--@SUCCESSFULLY_PARSED_AND_DEPARSED first on 3 May 2023, 20:10:15 \ No newline at end of file diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/groupby07.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/groupby07.sql index 222f54544..e8373727e 100644 --- a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/groupby07.sql +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/groupby07.sql @@ -16,4 +16,5 @@ where tt='500' group by tn, ui, (tt || tc) order by 1 ---@FAILURE: Encountered unexpected token: "group" "GROUP" recorded first on Aug 3, 2021, 7:20:08 AM \ No newline at end of file +--@FAILURE: Encountered unexpected token: "group" "GROUP" recorded first on Aug 3, 2021, 7:20:08 AM +--@FAILURE: select decode((tt||tc),'56',count(distinct cn),'57',sum(nu))as q from t where tt='500' and tc in('6','7')and to_char(c,'mm')='03' group by tn,ui,(tt||tc)having sum(nu)>0 order by 1 recorded first on 29 Apr 2023, 20:32:34 \ No newline at end of file diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert11.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert11.sql index 34b8d4df2..4bc74d6fb 100644 --- a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert11.sql +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert11.sql @@ -15,4 +15,5 @@ into x --@FAILURE: Encountered unexpected token: "into" "INTO" recorded first on Aug 3, 2021, 7:20:08 AM ---@FAILURE: Encountered unexpected token: "x" recorded first on 24 Oct 2021, 16:56:39 \ No newline at end of file +--@FAILURE: Encountered unexpected token: "x" recorded first on 24 Oct 2021, 16:56:39 +--@SUCCESSFULLY_PARSED_AND_DEPARSED first on 16 May 2023, 20:12:52 \ No newline at end of file diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert12.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert12.sql index 8c5c511c3..ebb68fdfd 100644 --- a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert12.sql +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert12.sql @@ -15,4 +15,5 @@ into r --@FAILURE: Encountered unexpected token: "into" "INTO" recorded first on Aug 3, 2021, 7:20:08 AM ---@FAILURE: Encountered unexpected token: "r" recorded first on 24 Oct 2021, 16:56:39 \ No newline at end of file +--@FAILURE: Encountered unexpected token: "r" recorded first on 24 Oct 2021, 16:56:39 +--@SUCCESSFULLY_PARSED_AND_DEPARSED first on 16 May 2023, 20:12:52 \ No newline at end of file