diff --git a/.codacy.yml b/.codacy.yml
new file mode 100644
index 000000000..d98077f4f
--- /dev/null
+++ b/.codacy.yml
@@ -0,0 +1,3 @@
+---
+exclude_paths:
+ - "site/**"
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 52464bf36..e79696ec8 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -1,25 +1,41 @@
---
-name: Bug report
+name: @ SQL Parser Error
about: Create a report to help us improve
-title: ''
-labels: ''
+title: '[BUG] JSQLParser Version : RDBMS : failing feature description'
+labels: 'Parser Error', 'Feature Request', 'Documentation', 'Java API', 'RDBMS support'
assignees: ''
---
-**Describe the bug**
-A clear and concise description of what the bug is.
+
-**To Reproduce**
-Steps to reproduce the behavior:
-1. Example SQL
-2. Parsing this SQL using JSqlParser with this statements
-3. Exception
+### Failing SQL Feature:
+
-**Expected behavior**
-A clear and concise description of what you expected to happen.
+### SQL Example:
+
-**System**
- - Database you are using
-- Java Version
+### Software Information:
+
+
+### Tips:
+
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 000000000..9003b51e1
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,31 @@
+---
+name: Feature request
+about: Suggest an unsupported Statement or Expression
+title: "[FEATURE] missing feature description"
+labels: ''
+assignees: ''
+
+---
+
+### Grammar or Syntax Description
+- Brief description of the failing SQL feature and the EBNF
+- Example: `WITH ROLLUP` clause is not supported yet
+
+### SQL Example
+- Simplified Query Example, focusing on the failing feature
+ ```sql
+ -- Replace with your ACTUAL example
+ select 1
+ from dual
+ ```
+- Please don't send screen shots
+
+### Additional context
+The used JSQLParser Version (please test the latest SNAPSHOT version before submitting).
+State the applicable RDBMS and version
+Links to the reference documentation
+
+### Tips:
+
diff --git a/.github/ISSUE_TEMPLATE/sql-parser-error.md b/.github/ISSUE_TEMPLATE/sql-parser-error.md
new file mode 100644
index 000000000..2a5eaf28f
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/sql-parser-error.md
@@ -0,0 +1,31 @@
+---
+name: SQL Parser Error
+about: Report a Parser Error
+title: "[BUG] JSQLParser Version : RDBMS : failing feature description"
+labels: ''
+assignees: ''
+
+---
+
+Always check against the **Latest SNAPSHOT of JSQLParser** and the [Syntax Diagram](https://jsqlparser.github.io/JSqlParser/syntax_snapshot.html)
+
+### Failing SQL Feature:
+- Brief description of the failing SQL feature
+- Example: `WITH ROLLUP` can't be parsed
+
+### SQL Example:
+- Simplified Query Example, focusing on the failing feature
+ ```sql
+ -- Replace with your ACTUAL example
+ select 1
+ from dual
+ ```
+
+### Software Information:
+- JSqlParser version
+- Database (e. g. Oracle, MS SQL Server, H2, PostgreSQL, IBM DB2 )
+
+### Tips:
+Please write in English and avoid Screenshots (as we can't copy and paste content from it).
+[Try your example online with the latest JSQLParser](http://jsqlformatter.manticore-projects.com) and share the link in the error report.
+Do provide Links or References to the specific Grammar and Syntax you are trying to use.
diff --git a/.github/release.yml b/.github/release.yml
new file mode 100644
index 000000000..b9134ea9a
--- /dev/null
+++ b/.github/release.yml
@@ -0,0 +1,8 @@
+changelog:
+ categories:
+ - title: Bugs solved
+ labels:
+ - "bug"
+ - title: Changes and new Features
+ labels:
+ - "*"
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 000000000..a3108f35b
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,104 @@
+name: CI Pipeline
+
+on:
+ push:
+ branches: [ "**" ] # Run on every commit to any branch
+ pull_request:
+ branches: [ "**" ] # Run for PRs from any branch
+ workflow_dispatch:
+
+permissions: write-all
+
+jobs:
+ gradle_check:
+ name: Gradle Check
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ ubuntu-latest, windows-latest, macos-latest ]
+ steps:
+ - uses: actions/checkout@main
+ with:
+ fetch-depth: 0
+
+ - name: Set up JDK 17
+ uses: actions/setup-java@main
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+
+ - name: Set up Gradle
+ uses: gradle/actions/setup-gradle@main
+
+ - name: Run Gradle Check
+ run: ./gradlew check
+
+ maven_verify:
+ name: Maven Verify
+ needs: gradle_check # ✅ Run only after Gradle check succeeds
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+# os: [ ubuntu-latest, windows-latest, macos-latest ]
+ os: [ ubuntu-latest, macos-latest ]
+ steps:
+ - uses: actions/checkout@main
+ with:
+ fetch-depth: 0
+
+ - name: Set up JDK 17
+ uses: actions/setup-java@main
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+
+ - name: Run Maven Verify
+ run: mvn --batch-mode verify
+
+ gradle_publish:
+ name: Gradle Publish
+ needs: [ gradle_check, maven_verify ] # ✅ Run only after both succeed
+ if: github.ref == 'refs/heads/master' && github.repository == 'JSQLParser/JSqlParser' # ✅ Only for master branch of main repo
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@main
+ with:
+ fetch-depth: 0
+
+ - name: Set up JDK 17
+ uses: actions/setup-java@main
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+
+ - name: Build with Gradle
+ uses: gradle/actions/setup-gradle@main
+
+ - name: Publish with Gradle
+ run: ./gradlew publish
+ env:
+ ossrhUsername: ${{ secrets.OSSRHUSERNAME }}
+ ossrhPassword: ${{ secrets.OSSRHPASSWORD }}
+
+ - uses: actions/setup-python@main
+
+ - name: Install XSLT Processor
+ run: sudo apt-get install -y xsltproc sphinx-common
+
+ - name: Install Python dependencies
+ run: pip install manticore_sphinx_theme sphinx_javadoc_xml myst_parser sphinx_substitution_extensions sphinx_issues sphinx_inline_tabs pygments
+
+ - name: Build Sphinx documentation with Gradle
+ run: FLOATING_TOC=false ./gradlew -DFLOATING_TOC=false gitChangelogTask renderRR xslt xmldoc sphinx
+
+ - name: Configure GitHub Pages
+ uses: actions/configure-pages@main
+
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@main
+ with:
+ path: 'build/sphinx'
+
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@main
diff --git a/.gitignore b/.gitignore
old mode 100755
new mode 100644
index 54f477598..955e7bf2d
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,17 @@
# Generated by maven
/target
/build
+/out
+
+# Sphinx Theme related stuff, which shall be downloaded separately
+/src/site/sphinx/_themes
+
+# Exclude the Auto-generated Changelog
+/src/site/sphinx/changelog.rst
+/src/site/sphinx/syntax_stable.rst
+/src/site/sphinx/syntax_snapshot.rst
+/src/site/sphinx/javadoc_stable.xml
+/src/site/sphinx/javadoc_snapshot.xml
# Generated by javacc-maven-plugin
/bin
@@ -21,3 +32,6 @@
/nbproject/
/.gradle
+
+# Mac
+.DS_Store
diff --git a/README.md b/README.md
index b87c9d609..c310ef545 100644
--- a/README.md
+++ b/README.md
@@ -1,136 +1,209 @@
-# JSqlParser
-
-[](https://travis-ci.com/JSQLParser/JSqlParser) [](https://coveralls.io/r/JSQLParser/JSqlParser?branch=master)
-[](https://www.codacy.com/gh/JSQLParser/JSqlParser/dashboard?utm_source=github.com&utm_medium=referral&utm_content=JSQLParser/JSqlParser&utm_campaign=Badge_Grade)
-[](http://maven-badges.herokuapp.com/maven-central/com.github.jsqlparser/jsqlparser)
+
+
+
+
+
+Turn any SQL statement into a traversable tree of Java objects -- and back again.
+An RDBMS-agnostic SQL parser for the JVM: one grammar, twelve dialects, no native extensions.
+
+
+
+
+
+
+
+
+[](https://github.com/JSQLParser/JSqlParser/actions/workflows/ci.yml)
+[](https://coveralls.io/r/JSQLParser/JSqlParser?branch=master)
+[](https://www.codacy.com/gh/JSQLParser/JSqlParser/dashboard)
+[](https://central.sonatype.com/artifact/com.manticore-projects.jsqlformatter/jsqlparser)
+[](https://central.sonatype.com/artifact/com.github.jsqlparser/jsqlparser)
[](https://www.javadoc.io/doc/com.github.jsqlparser/jsqlparser)
+[](https://github.com/JSQLParser/JSqlParser/stargazers)
+[](https://gitter.im/JSQLParser/JSqlParser)
-[](https://gitter.im/JSQLParser/JSqlParser?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
-[](https://lgtm.com/projects/g/JSQLParser/JSqlParser/context:java)
-[](https://lgtm.com/projects/g/JSQLParser/JSqlParser/alerts)
+**[Website](https://jsqlparser.github.io/JSqlParser)** · **[Samples](https://jsqlparser.github.io/JSqlParser/usage.html#parse-a-sql-statements)** · **[Syntax](https://jsqlparser.github.io/JSqlParser/syntax.html)** · **[Change Log](https://jsqlparser.github.io/JSqlParser/changelog.html#latest-changes-since-jsqlparser-version)** · **[Contributing](https://jsqlparser.github.io/JSqlParser/contribution.html)**
-Look here for more information and examples: https://github.com/JSQLParser/JSqlParser/wiki.
-
-## License
+
-JSqlParser is dual licensed under **LGPL V2.1** or **Apache Software License, Version 2.0**.
+---
-## Discussion
+## What it does
-Please provide feedback on:
+Give it SQL. Get an AST you can walk, rewrite, and print back out.
-* API changes: extend visitor with return values (https://github.com/JSQLParser/JSqlParser/issues/901)
+```sql
+SELECT 1 FROM dual WHERE a = b
+```
-## News
-* Released version **4.2** of JSqlParser
-* Released version **4.1** of JSqlParser
-* Released version **4.0** of JSqlParser
-* The array parsing is the default behaviour. Square bracket quotation has to be enabled using
- a parser flag (**CCJSqlParser.withSquareBracketQuotation**).
-* due to an API change the version will be 3.0
-* JSqlParser uses now Java 8 at the minimum
+```text
+SQL Text
+ └─Statements: statement.select.PlainSelect
+ ├─selectItems: statement.select.SelectItem
+ │ └─LongValue: 1
+ ├─Table: dual
+ └─where: expression.operators.relational.EqualsTo
+ ├─Column: a
+ └─Column: b
+```
-More news can be found here: https://github.com/JSQLParser/JSqlParser/wiki/News.
+```java
+String sqlStr = "select 1 from dual where a=b";
-## Alternatives to JSqlParser?
-[**General SQL Parser**](http://www.sqlparser.com/features/introduce.php?utm_source=github-jsqlparser&utm_medium=text-general) looks pretty good, with extended SQL syntax (like PL/SQL and T-SQL) and java + .NET APIs. The tool is commercial (license available online), with a free download option.
+PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr);
-## JSqlParser
+SelectItem selectItem = select.getSelectItems().get(0);
+Assertions.assertEquals(new LongValue(1), selectItem.getExpression());
-JSqlParser is a SQL statement parser. It translates SQLs in a traversable hierarchy of Java classes. JSqlParser is not limited to one database but provides support for a lot of specials of Oracle, SqlServer, MySQL, PostgreSQL ... To name some, it has support for Oracles join syntax using (+), PostgreSQLs cast syntax using ::, relational operators like != and so on.
+Table table = (Table) select.getFromItem();
+Assertions.assertEquals("dual", table.getName());
-## Support
-If you need help using JSqlParser feel free to file an issue or contact me.
+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());
+```
-## Contributions
-To help JSqlParser's development you are encouraged to provide
-* feedback
-* bugreports
-* pull requests for new features
-* improvement requests
-* fund new features or sponsor JSqlParser ([**Sponsor**](https://www.paypal.me/wumpz))
+The tree is traversable with the Visitor pattern, and the same object model works in reverse:
+build statements from Java with a [fluent API](https://jsqlparser.github.io/JSqlParser/usage.html#build-a-sql-statements)
+and render them as SQL text.
-**Please write in English, since it's the language most of the dev team knows.**
+## Install
-Also I would like to know about needed examples or documentation stuff.
+Use the stable **Manticore builds**. They are released continuously from the current development
+line and carry all of the performance and grammar work described below. The upstream
+`com.github.jsqlparser` release on Maven Central is considerably older.
-## Extensions in the latest SNAPSHOT version 4.3
+```xml
+
+ com.manticore-projects.jsqlformatter
+ jsqlparser
+ [5.3.218,)
+
+```
-Additionally, we have fixed many errors and improved the code quality and the test coverage.
+```gradle
+implementation("com.manticore-projects.jsqlformatter:jsqlparser:+")
+```
-## Extensions of JSqlParser releases
+
+Upstream release and snapshots
-* [Release Notes](https://github.com/JSQLParser/JSqlParser/releases)
-* Modifications before GitHub's release tagging are listed in the [Older Releases](https://github.com/JSQLParser/JSqlParser/wiki/Older-Releases) page.
+```xml
+
+ com.github.jsqlparser
+ jsqlparser
+ 5.3
+
+```
+Snapshot coordinates and repository setup are on the
+[build dependencies page](https://jsqlparser.github.io/JSqlParser/usage.html#build-dependencies).
-## Building from the sources
+
-As the project is a Maven project, building is rather simple by running:
-```shell
-mvn package
-```
+## Performance
+
+**11× faster than 5.3**, and the fastest parser on real-world SQL of any of the parsers
+tested, in any language — 19× ahead of `sqlglot[c]` on JSqlParser's own `SELECT` test suite.
-Since 4.2, alternatively Gradle can be used
-```shell
-gradle build
+
+
+```text
+Benchmark (version) Mode Cnt Score Error Units
+JSQLParserBenchmark.parseSQLStatements latest avgt 15 7.602 ± 0.135 ms/op
+JSQLParserBenchmark.parseSQLStatements 5.3 avgt 15 84.687 ± 3.321 ms/op
```
-
-The project requires the following to build:
-- Maven (or Gradle)
-- JDK 8 or later. The jar will target JDK 8, but the version of the maven-compiler-plugin that JsqlParser uses requires JDK 8+
-This will produce the jsqlparser-VERSION.jar file in the `target/` directory (`build/libs/jsqlparser-VERSION.jar` in case of Gradle).
+Methodology and the full cross-parser comparison against SQLGlot, `sqlglot[c]` and
+polyglot-sql: **[jsqlparser-bench](https://github.com/manticore-projects/jsqlparser-bench)**.
-**To build this project without using Maven or Gradle, one has to build the parser by JavaCC using the CLI options it provides.**
+## What it parses
-## Debugging through problems
+JSqlParser targets the SQL standard plus all major RDBMS. One grammar covers all of them,
+and missing syntax gets added on demand — [open an issue](https://github.com/JSQLParser/JSqlParser/issues).
-Refer to the [Visualize Parsing](https://github.com/JSQLParser/JSqlParser/wiki/Examples-of-SQL-parsing#visualize-parsing) section to learn how to run the parser in debug mode.
+
-## Source Code conventions
+`BigQuery` · `Snowflake` · `DuckDB` · `Redshift` · `Oracle` · `MS SQL Server` · `Sybase`
+`PostgreSQL` · `MySQL` · `MariaDB` · `DB2` · `H2` · `HSQLDB` · `Derby` · `SQLite`
-Recently a checkstyle process was integrated into the build process. JSqlParser follows the sun java format convention. There are no TABs allowed. Use spaces.
+
-```java
-public void setUsingSelect(SubSelect usingSelect) {
- this.usingSelect = usingSelect;
- if (this.usingSelect != null) {
- this.usingSelect.setUseBrackets(false);
- }
-}
-```
+| | Statements |
+|---|---|
+| **Queries** | `SELECT` · `WITH …` · Piped SQL |
+| **DML** | `INSERT` · `UPDATE` · `UPSERT` · `MERGE` · `DELETE` · `TRUNCATE TABLE` |
+| **DDL** | `CREATE …` · `ALTER …` · `DROP …` |
+| **PostgreSQL RLS** | `CREATE POLICY` · `ALTER TABLE … ENABLE`/`DISABLE`/`FORCE`/`NO FORCE ROW LEVEL SECURITY` |
+| **Salesforce SOQL** | `INCLUDES` · `EXCLUDES` |
-This is a valid piece of source code:
-* blocks without braces are not allowed
-* after control statements (if, while, for) a whitespace is expected
-* the opening brace should be in the same line as the control statement
+Beyond statement shapes, the grammar handles nested sub-selects, bind parameters (`?`,
+`:name`), window and analytic functions, Oracle hints, and the T-SQL square-bracket versus
+array-literal ambiguity. The complete reference is on the
+[syntax page](https://jsqlparser.github.io/JSqlParser/syntax.html).
-## Maven Repository
+## Piped SQL
-JSQLParser is deployed at sonatypes open source maven repository.
-Starting from now I will deploy there. The first snapshot version there will be 0.8.5-SNAPSHOT.
-To use it this is the repository configuration:
+Support is progressing for Piped SQL, which writes queries in the order they actually
+execute rather than the order SQL historically demanded.
-```xml
-
-
- jsqlparser-snapshots
-
- true
-
- https://oss.sonatype.org/content/groups/public/
-
-
+```sql
+FROM Produce
+|> WHERE
+ item != 'bananas'
+ AND category IN ('fruit', 'nut')
+|> AGGREGATE COUNT(*) AS num_items, SUM(sales) AS total_sales
+ GROUP BY item
+|> ORDER BY item DESC;
```
-This repositories releases will be synched to maven central. Snapshots remain at sonatype.
-And this is the dependency declaration in your pom:
-```xml
-
- com.github.jsqlparser
- jsqlparser
- 4.2
-
-```
+Background reading: the [Google research paper](https://storage.googleapis.com/gweb-research2023-media/pubtools/1004848.pdf),
+[BigQuery pipe syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/pipe-syntax)
+and [DuckDB FROM-first syntax](https://duckdb.org/docs/sql/query_syntax/from.html#from-first-syntax).
+
+## Java version
+
+| JSqlParser | Runtime | Notes |
+|------------|---------|-------|
+| 4.9 | JDK 8 | last JDK 8 compatible release |
+| 5.0 and later | JDK 11 | breaking changes to the AST Visitors, see the Migration Guide |
+| 5.1 and later | JDK 11 | building requires a **JDK 17 toolchain** (plugin requirement) |
+| 5.4 and later | JDK 11 | parser generated with **JavaCC 8** |
+
+## Sister projects
+
+- **[JSQLFormatter](https://manticore-projects.com/JSQLFormatter/index.html)** — pretty-printing and formatting of SQL text
+- **[JSQLTranspiler](https://manticore-projects.com/JSQLTranspiler/index.html)** — dialect-specific rewriting, column resolution and lineage, by [Starlake.ai](https://starlake.ai/)
+
+## Alternatives
+
+The dual-licensed [JOOQ](https://www.jooq.org/doc/latest/manual/sql-building/sql-parser/)
+ships a hand-written parser with broad RDBMS support, cross-dialect translation, SQL
+transformation, and a JDBC proxy mode. Worth a look if translation between dialects is your
+primary need rather than AST access.
+
+## Sponsor
+
+A huge thank you to **[Starlake.ai](https://starlake.ai/)**, who simplify data ingestion,
+transformation and orchestration for faster delivery of high-quality data. Starlake has been
+instrumental in providing Piped SQL support and a large number of test cases for BigQuery,
+Redshift, Databricks and DuckDB. If JSqlParser is useful to you, visit
+[Starlake.ai](https://starlake.ai/) and give them a star.
+
+## Documentation
+
+1. [Samples](https://jsqlparser.github.io/JSqlParser/usage.html#parse-a-sql-statements)
+2. [Build instructions](https://jsqlparser.github.io/JSqlParser/usage.html) and [Maven artifact](https://jsqlparser.github.io/JSqlParser/usage.html#build-dependencies)
+3. [Contribution guide](https://jsqlparser.github.io/JSqlParser/contribution.html)
+4. [Change log](https://jsqlparser.github.io/JSqlParser/changelog.html#latest-changes-since-jsqlparser-version)
+5. [Issues](https://github.com/JSQLParser/JSqlParser/issues)
+
+## License
+Dual licensed under **LGPL 2.1** or the **Apache License, Version 2.0**. Take your pick.
diff --git a/build.gradle b/build.gradle
index 0a41353ef..319cbdcbb 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,63 +1,287 @@
+import se.bjurr.gitchangelog.plugin.gradle.GitChangelogTask
+import com.nwalsh.gradle.saxon.SaxonXsltTask
+
+import java.time.Instant
+
+buildscript {
+ dependencies {
+ classpath group: 'net.sf.saxon', name: 'Saxon-HE', version: 'latest.release'
+ }
+}
+
plugins {
id 'java'
+ id "com.vanniktech.maven.publish" version "latest.release"
id 'maven-publish'
- id "ca.coglinc2.javacc" version "3.0.0"
+ id 'signing'
+
+ id "org.javacc.javacc" version "latest.release"
id 'jacoco'
- id "com.github.spotbugs" version "4.7.2"
+ id 'com.github.kt3k.coveralls' version "latest.release"
+ id "com.github.spotbugs" version "latest.release"
+ id "com.diffplug.spotless" version "latest.release"
id 'pmd'
id 'checkstyle'
-
+ id 'eclipse'
+
// download the RR tools which have no Maven Repository
- id "de.undercouch.download" version "4.1.2"
+ id "de.undercouch.download" version "latest.release"
+ 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 "latest.release"
+ id 'biz.aQute.bnd.builder' version "latest.release"
}
+def getVersion = { boolean considerSnapshot ->
+ Integer major = 0
+ Integer minor = 0
+ Integer patch = null
+ Integer build = null
+ String commit = null
+ String snapshot = ""
+
+ def versionStr = providers.exec {
+ commandLine "git", "--no-pager", "-C", project.projectDir, "describe", "--tags", "--always", "--dirty=-SNAPSHOT"
+ }.standardOutput.asText.get().trim()
+
+ def pattern = /jsqlparser-(?\d*)\.(?\d*)(\.(?\d*))?(-(?\d*)-(?[a-zA-Z\d]*))?/
+ def matcher = versionStr =~ pattern
+
+ if (matcher.find()) {
+ major = matcher.group('major') as Integer ?: 0
+ minor = matcher.group('minor') as Integer ?: 0
+ patch = matcher.group('patch') as Integer ?: null
+ build = matcher.group('build') as Integer ?: null
+ commit = matcher.group('commit') ?: null
+ }
+
+ if (considerSnapshot && (versionStr.endsWith('SNAPSHOT') || build != null)) {
+ minor++
+ if (patch != null) patch = 0
+ snapshot = "-SNAPSHOT"
+ }
+
+ return "${major}.${minor}" +
+ (patch != null ? ".${patch}" : "") +
+ (build != null ? ".${build}" : "") +
+ snapshot
+}
+
+
+// for publishing a release, call Gradle with Environment Variable RELEASE:
+// RELEASE=true gradle JSQLParser:publish
+version = getVersion( !System.getenv("RELEASE") )
group = 'com.github.jsqlparser'
-version = '4.3-SNAPSHOT'
description = 'JSQLParser library'
-java.sourceCompatibility = JavaVersion.VERSION_1_8
-repositories {
- gradlePluginPortal()
- mavenLocal()
- maven {
- url = uri('https://repo.maven.apache.org/maven2/')
+tasks.register('generateBuildInfo') {
+ outputs.dir layout.buildDirectory.file("resources/main")
+ doLast {
+ def outputDir = new File( layout.buildDirectory.file("generated/sources/buildinfo/java/main").get().asFile, "net/sf/jsqlparser")
+ outputDir.mkdirs()
+
+ def gitVersionStr = providers.exec {
+ commandLine "git", "--no-pager", "-C", project.projectDir, "describe", "--tags", "--always", "--dirty=-SNAPSHOT"
+ }.standardOutput.asText.get().trim()
+
+ def gitCommitStr = providers.exec {
+ commandLine "git", "--no-pager", "-C", project.projectDir, "rev-parse", "--short", "HEAD"
+ }.standardOutput.asText.get().trim()
+
+ def buildTime = Instant.now().toString()
+
+ def content = """\
+ |package net.sf.jsqlparser;
+ |
+ |public final class BuildInfo {
+ | public static final String NAME = "${project.name}";
+ | public static final String VERSION = "${gitVersionStr}";
+ | public static final String GIT_COMMIT = "${gitCommitStr ?: 'unknown'}";
+ | public static final String BUILD_TIME = "${buildTime}";
+ |}
+ """.stripMargin()
+
+ new File(outputDir, "BuildInfo.java").text = content
+ }
+}
+
+// Make sure the file is included in the compiled sources
+sourceSets {
+ main {
+ java {
+ srcDir layout.buildDirectory.file("generated/sources/buildinfo/java/main").get().asFile
+ }
}
}
+tasks.withType(JavaCompile).configureEach {
+ mustRunAfter("generateBuildInfo")
+}
+
+tasks.withType(Pmd).configureEach {
+ mustRunAfter("generateBuildInfo")
+}
+
+tasks.withType(Checkstyle).configureEach {
+ exclude '**/module-info.java', '**/package-info.java'
+
+ mustRunAfter("generateBuildInfo")
+}
+
+repositories {
+ mavenCentral()
+ maven { url "https://dev.saxonica.com/maven" }
+}
+
+configurations {
+ xmlDoclet
+}
+
dependencies {
- testImplementation 'commons-io:commons-io:2.6'
- testImplementation 'junit:junit:4.13.1'
- testImplementation 'org.mockito:mockito-core:2.28.2'
- testImplementation 'org.assertj:assertj-core:3.16.1'
- testImplementation 'org.apache.commons:commons-lang3:3.10'
- testImplementation 'com.h2database:h2:1.4.200'
-
+ testImplementation 'commons-io:commons-io:2.+'
+ testImplementation 'org.apache.commons:commons-text:+'
+ testImplementation 'org.mockito:mockito-core:+'
+ testImplementation 'org.assertj:assertj-core:+'
+ testImplementation 'org.hamcrest:hamcrest-core:+'
+ testImplementation 'org.apache.commons:commons-lang3:+'
+ testImplementation 'com.h2database:h2:+'
+
// for JaCoCo Reports
- testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.1'
- testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
-
+ testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.+'
+ testImplementation 'org.junit.jupiter:junit-jupiter-api:5.+'
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.+'
+ testImplementation 'org.junit.jupiter:junit-jupiter-params:5+'
+
+ // https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter
+ testImplementation 'org.mockito:mockito-junit-jupiter:5.+'
+
+ // 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:+'){ changing = true }
+
+ // enforce latest version of JavaCC
+ testImplementation('com.manticore-projects.jsqlformatter:javacc-core:+')
+ testImplementation('com.manticore-projects.jsqlformatter:javacc-java:+')
+
+ jmh 'org.openjdk.jmh:jmh-core:+'
+ jmh 'org.openjdk.jmh:jmh-generator-annprocess:+'
+ javacc('com.manticore-projects.jsqlformatter:javacc-core:+')
+ javacc('com.manticore-projects.jsqlformatter:javacc-java:+')
}
compileJavacc {
- arguments = [grammar_encoding: 'UTF-8', static: 'false', java_template_type: 'modern']
+ arguments = [
+ grammar_encoding: 'UTF-8',
+ static: 'false',
+ java_template_type: 'modern',
+ // Comment this in to build the parser with tracing.
+ DEBUG_PARSER: 'false',
+ DEBUG_LOOKAHEAD: 'false',
+ LEGACY_EXCEPTION_HANDLING: 'false'
+ ]
}
java {
withSourcesJar()
- withJavadocJar()
+ // withJavadocJar()
+
+ sourceCompatibility = '11'
+ targetCompatibility = '11'
- spotbugs
- pmd
+ // needed for XML-Doclet to work (since Doclet changed again with Java 13)
+ toolchain {
+ languageVersion.set(JavaLanguageVersion.of(17))
+ }
+}
+javadoc {
+ include("build/generated/javacc/net/sf/jsqlparser/parser/*.java" )
+ if(JavaVersion.current().isJava9Compatible()) {
+ options.addBooleanOption('html5', true)
+ }
+ options.addBooleanOption("Xdoclint:none", true)
}
-jacoco {
- toolVersion = "0.8.7"
+jar {
+ manifest {
+ attributes (
+ "Automatic-Module-Name": "net.sf.jsqlparser"
+ )
+ }
+
+ bundle {
+ properties.empty()
+ bnd(
+ "Created-By": System.properties.get('user.name'),
+ "Bundle-SymbolicName": "net.sf.jsqlparser",
+ "Import-Package": "*",
+ "Export-Package": "net.sf.jsqlparser.*",
+ "Automatic-Module-Name": "net.sf.jsqlparser"
+ )
+ }
+
+ dependsOn(generateBuildInfo)
+}
+
+tasks.register('xmldoc', Javadoc) {
+ dependsOn(compileJavacc)
+
+ def outFile = reporting.file(
+ version.endsWith("-SNAPSHOT")
+ ? "xmlDoclet/javadoc_snapshot.xml"
+ : "xmlDoclet/javadoc_stable.xml"
+ )
+
+ source = sourceSets.main.allJava
+ // add any generated Java sources
+ source += fileTree(layout.buildDirectory.dir("generated/javacc").get().asFile) {
+ include '**/*.java'
+ }
+ source += fileTree(layout.buildDirectory.dir("generated/jjtree").get().asFile) {
+ include '**/*.java'
+ }
+
+ classpath = sourceSets.main.runtimeClasspath
+
+ destinationDir = reporting.file("xmlDoclet")
+ options.docletpath = configurations.xmlDoclet.files as List
+ options.doclet = "com.manticore.tools.xmldoclet.XmlDoclet"
+ title = "API $version"
+
+ options.addStringOption("basePackage", "net.sf.jsqlparser")
+ options.addStringOption("filename", outFile.getName())
+
+ doLast {
+ copy {
+ from outFile
+ into layout.projectDirectory.dir("src/site/sphinx/").asFile
+ }
+ }
}
test {
- finalizedBy jacocoTestReport // report is always generated after tests run
- finalizedBy jacocoTestCoverageVerification
+ environment = [ 'EXPORT_TEST_TO_FILE': 'False' ]
+ useJUnitPlatform()
+
+ // set heap size for the test JVM(s)
+ minHeapSize = "1G"
+ maxHeapSize = "4G"
+
+ // set JVM stack size
+ jvmArgs = ['-Xss4m', '--add-opens=java.base/java.lang=ALL-UNNAMED']
+
+ jacoco {
+ excludes = ['net/sf/jsqlparser/parser/CCJSqlParserTokenManager']
+ }
+}
+
+coveralls {
+ jacocoReportPath 'build/reports/jacoco/test/jacocoTestReport.xml'
}
jacocoTestReport {
@@ -69,123 +293,439 @@ jacocoTestReport {
}
}
jacocoTestCoverageVerification {
+ // Jacoco can't handle the TokenManager class
+ afterEvaluate {
+ classDirectories.setFrom(files(classDirectories.files.collect {
+ fileTree(dir: it, exclude: [
+ "**CCJSqlParserTokenManager**"
+ ])
+ }))
+ }
violationRules {
rule {
+ //element = 'CLASS'
limit {
- minimum = JavaVersion.current().isJava8() // for any reason, different results
- ? 0.83 // depending on the Java Version
- : 0.842
+ //@todo: temporarily reduced it 80%, we need to bring that back to 84% accepting the Keywords PR
+ minimum = 0.50
}
+ excludes = [
+ 'net.sf.jsqlparser.util.validation.*',
+ 'net.sf.jsqlparser.**.*Adapter',
+ 'net.sf.jsqlparser.parser.**'
+ ]
}
+ rule {
+ //element = 'CLASS'
+ limit {
+ counter = 'LINE'
+ value = 'MISSEDCOUNT'
+
+ //@todo: temporarily increased to 7000, we need to bring that down to 5500 after accepting the Keywords PR
+ maximum = 20000
+ }
+ excludes = [
+ 'net.sf.jsqlparser.util.validation.*',
+ 'net.sf.jsqlparser.**.*Adapter',
+ 'net.sf.jsqlparser.parser.**'
+ ]
+ }
+// rule {
+// element = 'CLASS'
+// limit {
+// counter = 'LINE'
+// value = 'MISSEDRATIO'
+// maximum = 0.3
+// }
+// excludes = [
+// 'net.sf.jsqlparser.util.validation.*',
+// 'net.sf.jsqlparser.**.*Adapter',
+// 'net.sf.jsqlparser.parser.**'
+// ]
+// }
}
}
spotbugsMain {
reports {
- html {
- enabled = true
- destination = file("build/reports/spotbugs/main/spotbugs.html")
- stylesheet = 'fancy-hist.xsl'
- }
+ html.required.set(true)
+ html.outputLocation.set( layout.buildDirectory.file("reports/spotbugs/main/spotbugs.html").get().asFile )
+ html.stylesheet="fancy-hist.xsl"
}
}
+
spotbugs {
// fail only on P1 and without the net.sf.jsqlparser.parser.*
- excludeFilter = file("spotBugsExcludeFilter.xml")
-
- // do not run over the test, although we should do that eventually
- spotbugsTest.enabled = false
+ excludeFilter = file("config/spotbugs/spotBugsExcludeFilter.xml")
+}
+
+// do not run over the test, although we should do that eventually
+tasks.named('spotbugsTest').configure {
+ enabled = false
}
pmd {
- consoleOutput = false
- toolVersion = "6.36.0"
-
+ // later versions throw NPE
+ toolVersion = '7.17.0'
+
+ consoleOutput = true
sourceSets = [sourceSets.main]
-
+
// clear the ruleset in order to use configured rules only
ruleSets = []
-
- //rulesMinimumPriority = 1
-
- ruleSetFiles = files("ruleset.xml")
-
- pmdMain {
- excludes = [
- "build/generated/*"
- ]
- }
+ rulesMinimumPriority = 2
+ ruleSetFiles = files("config/pmd/ruleset.xml")
+}
+
+tasks.named('pmdMain').configure {
+ excludes = [
+ "build/generated/*"
+ , "**/net/sf/jsqlparser/parser/SimpleCharStream.java"
+ ]
}
checkstyle {
- toolVersion "8.45.1"
sourceSets = [sourceSets.main, sourceSets.test]
- configFile =rootProject.file('config/checkstyle/checkstyle.xml')
+ configFile = rootProject.file('config/checkstyle/checkstyle.xml')
}
-tasks.withType(Checkstyle) {
+tasks.withType(Checkstyle).configureEach {
reports {
xml.required = false
html.required = true
}
+ excludes = [
+ "**/module-info.java"
+ , "net/sf/jsqlparser/parser/SimpleCharStream.java"
+ ]
}
-task renderRR() {
+spotless {
+ // optional: limit format enforcement to just the files changed by this feature branch
+ ratchetFrom 'origin/master'
+
+ format 'misc', {
+ // define the files to apply `misc` to
+ target '*.rst', '*.md', '.gitignore'
+
+ // define the steps to apply to those files
+ trimTrailingWhitespace()
+ leadingTabsToSpaces(4)
+ endWithNewline()
+ }
+ java {
+ leadingTabsToSpaces(4)
+ eclipse().configFile('config/formatter/eclipse-java-google-style.xml')
+ }
+}
+
+
+tasks.register('renderRR') {
+ dependsOn(compileJavacc)
+
doLast {
- // these WAR files have been provided as a courtesy by Gunther Rademacher
- // and belong to the RR - Railroad Diagram Generator Project
- // https://github.com/GuntherRademacher/rr
- //
- // Hosting at manticore-projects.com is temporary until a better solution is found
- // Please do not use these files without Gunther's permission
- download {
+ def rrDir = layout.buildDirectory.dir("rr").get().asFile
+
+ // Download convert.war
+ download.run {
src 'http://manticore-projects.com/download/convert.war'
- dest "$buildDir/rr/convert.war"
+ dest new File(rrDir, "convert.war")
overwrite false
+ onlyIfModified true
}
-
- download {
+
+ // Download rr.war
+ download.run {
src 'http://manticore-projects.com/download/rr.war'
- dest "$buildDir/rr/rr.war"
+ dest new File(rrDir, "rr.war")
overwrite false
+ onlyIfModified true
+ tempAndMove true
}
-
- javaexec {
- standardOutput = new FileOutputStream("${buildDir}/rr/JSqlParserCC.ebnf")
- main="-jar";
- args = [
- "$buildDir/rr/convert.war",
- "$buildDir/generated/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jj"
- ]
+
+ // Convert JJ file to EBNF
+ def ebnfFile = new File(rrDir, "JSqlParserCC.ebnf")
+ def jjFile = layout.buildDirectory.dir("generated/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jj").get().asFile.absolutePath
+
+ def convertProc = new ProcessBuilder('java', '-jar',
+ new File(rrDir, "convert.war").absolutePath,
+ jjFile)
+ .redirectOutput(ebnfFile)
+ .redirectErrorStream(true)
+ .start()
+ if (convertProc.waitFor() != 0) {
+ throw new GradleException("Failed to convert JJ to EBNF")
}
-
- javaexec {
- main="-jar";
- args = [
- "$buildDir/rr/rr.war",
- "-noepsilon",
- "-color:#4D88FF",
- "-offset:0",
- "-width:800",
- //"-png",
- //"-out:${buildDir}/rr/JSqlParserCC.zip",
- "-out:${buildDir}/rr/JSqlParserCC.xhtml",
- "${buildDir}/rr/JSqlParserCC.ebnf"
- ]
- }
+
+ // Generate RR diagrams
+ def rrProc = new ProcessBuilder('java', '-jar',
+ new File(rrDir, "rr.war").absolutePath,
+ "-noepsilon",
+ "-color:#4D88FF",
+ "-offset:0",
+ "-width:800",
+ "-out:${new File(rrDir, "JSqlParserCC.xhtml")}",
+ new File(rrDir, "JSqlParserCC.ebnf").absolutePath)
+ .redirectErrorStream(true)
+ .start()
+ rrProc.inputStream.eachLine { logger.info(it) }
+ if (rrProc.waitFor() != 0) {
+ throw new GradleException("Failed to generate RR diagrams")
+ }
+ }
+}
+
+
+tasks.register('gitChangelogTask', GitChangelogTask) {
+ fromRepo.set( file("$projectDir").toString() )
+ file.set( new File("${projectDir}/src/site/sphinx/changelog.rst") )
+ fromRevision.set( "4.0")
+ //toRef = "1.1";
+
+ // switch off the formatter since the indentation matters for Mark-down
+ // @formatter:off
+ templateContent.set ("""
+************************
+Changelog
+************************
+
+
+{{#tags}}
+{{#ifMatches name "^Unreleased.*"}}
+Latest Changes since |JSQLPARSER_VERSION|
+{{/ifMatches}}
+{{#ifMatches name "^(?!Unreleased).*"}}
+Version {{name}}
+{{/ifMatches}}
+=============================================================
+
+ {{#issues}}
+
+ {{#commits}}
+ {{#ifMatches messageTitle "^(?!Merge).*"}}
+ * **{{{messageTitle}}}**
+
+ {{authorName}}, {{commitDate}}
+ {{/ifMatches}}
+ {{/commits}}
+
+ {{/issues}}
+{{/tags}}
+""")
+ // @formatter:on
+}
+
+tasks.register('updateKeywords', JavaExec) {
+ group = "Execution"
+ description = "Generate the Reserved Keywords documentation"
+ classpath = sourceSets.main.runtimeClasspath
+ args = [
+ file('src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt').absolutePath
+ , file('src/site/sphinx/keywords.rst').absolutePath
+ ]
+ mainClass.set("net.sf.jsqlparser.parser.ParserKeywordsUtils")
+
+ dependsOn(compileJava)
+}
+
+tasks.register('xslt', SaxonXsltTask) {
+ def outFile = version.endsWith("-SNAPSHOT")
+ ? file("src/site/sphinx/syntax_snapshot.rst")
+ : file("src/site/sphinx/syntax_stable.rst")
+
+ dependsOn(renderRR)
+ stylesheet file('src/main/resources/rr/xhtml2rst.xsl')
+
+ parameters(
+ "withFloatingToc": System.getProperty("FLOATING_TOC", "false"),
+ "isSnapshot": Boolean.toString(version.endsWith("-SNAPSHOT"))
+ )
+
+ // Transform every .xml file in the "input" directory.
+ input layout.buildDirectory.file("rr/JSqlParserCC.xhtml").get()
+ output outFile
+}
+
+tasks.register('sphinx', Exec) {
+ dependsOn(gitChangelogTask, renderRR, xslt, xmldoc)
+
+ String PROLOG = """
+.. |_| unicode:: U+00A0
+ :trim:
+
+.. |JSQLPARSER_EMAIL| replace:: support@manticore-projects.com
+.. |JSQLPARSER_VERSION| replace:: ${getVersion(false)}
+.. |JSQLPARSER_SNAPSHOT_VERSION| replace:: ${getVersion(true)}
+.. |JSQLPARSER_STABLE_VERSION_LINK| raw:: html
+
+ ${project.name}-${getVersion(false)}.jar
+
+.. |JSQLPARSER_SNAPSHOT_VERSION_LINK| raw:: html
+
+ ${project.name}-${getVersion(true)}.jar
+
+"""
+
+ args = [
+ "-Dproject=JSQLParser"
+ , "-Dcopyright=Tobias Warneke, 2022"
+ , "-Dauthor=Tobias Warneke"
+ , "-Drelease=${getVersion(false)}"
+ , "-Drst_prolog=$PROLOG"
+ , "${projectDir}/src/site/sphinx"
+ , layout.buildDirectory.file("sphinx").get().asFile
+ ]
+
+ executable "sphinx-build"
+
+ //store the output instead of printing to the console:
+ standardOutput = new ByteArrayOutputStream()
+
+ //extension method stopTomcat.output() can be used to obtain the output:
+ ext.output = {
+ return standardOutput.toString()
}
}
-
+
+publish {
+ dependsOn(check, gitChangelogTask, renderRR, xslt, xmldoc)
+}
publishing {
publications {
- maven(MavenPublication) {
- from(components.java)
+ mavenJava(MavenPublication) {
+ artifactId = 'jsqlparser'
+
+ from components.java
+
+ versionMapping {
+ usage('java-api') {
+ fromResolutionOf('runtimeClasspath')
+ }
+ usage('java-runtime') {
+ fromResolutionResult()
+ }
+ }
+
+ pom {
+ name.set('JSQLParser library')
+ description.set('Parse SQL Statements into Abstract Syntax Trees (AST)')
+ url.set('https://github.com/JSQLParser/JSqlParser')
+
+ licenses {
+ license {
+ name.set('GNU Library or Lesser General Public License (LGPL) V2.1')
+ url.set('http://www.gnu.org/licenses/lgpl-2.1.html')
+ }
+ license {
+ name.set('The Apache Software License, Version 2.0')
+ url.set('http://www.apache.org/licenses/LICENSE-2.0.txt')
+ }
+ }
+
+ developers {
+ developer {
+ id.set('twa')
+ name.set('Tobias Warneke')
+ email.set('t.warneke@gmx.net')
+ }
+ developer {
+ id.set('are')
+ name.set('Andreas Reichel')
+ email.set('andreas@manticore-projects.com')
+ }
+ }
+
+ scm {
+ connection.set('scm:git:https://github.com/JSQLParser/JSqlParser.git')
+ developerConnection.set('scm:git:ssh://git@github.com:JSQLParser/JSqlParser.git')
+ url.set('https://github.com/JSQLParser/JSqlParser.git')
+ }
+ }
+ }
+ }
+
+ repositories {
+ maven {
+ name = "ossrh"
+ def releasesRepoUrl = "https://central.sonatype.com/repository/maven-releases"
+ def snapshotsRepoUrl = "https://central.sonatype.com/repository/maven-snapshots/"
+ url(version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl)
+
+ credentials {
+ username = providers.environmentVariable("ossrhUsername").orNull
+ password = providers.environmentVariable("ossrhPassword").orNull
+ }
}
}
}
-tasks.withType(JavaCompile) {
+
+signing {
+ // don't sign SNAPSHOTS
+ if (!version.endsWith('SNAPSHOT')) {
+ sign publishing.publications.mavenJava
+ }
+}
+
+tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
}
+
+remotes {
+ webServer {
+ host = findProperty("${project.name}.host") ?: "defaultHost" // Provide default if not found
+ user = findProperty("${project.name}.username") ?: "defaultUsername" // Provide default if not found
+ identity = file("${System.getProperty('user.home')}/.ssh/id_rsa")
+ }
+}
+
+
+tasks.register('upload') {
+ doFirst {
+ 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.
+ """
+ )
+ }
+ }
+ doLast {
+ ssh.run {
+ session(remotes.webServer) {
+ def versionStable = getVersion(false)
+ execute "mkdir -p download/${project.name}-${versionStable}"
+ for (File file: fileTree(include:['*.jar'], dir: layout.buildDirectory.dir("libs").get()).collect()) {
+ put from: file, into: "download/${project.name}-${versionStable}"
+ }
+ }
+ }
+ }
+
+ dependsOn(check, assemble, gitChangelogTask, renderRR, xslt, xmldoc)
+}
+
+check {
+ dependsOn jacocoTestCoverageVerification
+}
+
+jmh {
+ jmhVersion = '1.37'
+ jvmArgs = [
+ "--enable-native-access=ALL-UNNAMED"
+ , "--add-opens=java.base/sun.misc=ALL-UNNAMED"
+ , "--add-opens=java.base/java.lang=ALL-UNNAMED"
+ , "-XX:+UnlockDiagnosticVMOptions"
+ , "-XX:+DebugNonSafepoints"
+ ]
+
+ profilers = ['async:libPath=/opt/async-profiler/lib/libasyncProfiler.so;output=tree;dir=build/reports/jmh']
+
+ includes = ['.*JSQLParserBenchmark.*']
+ warmupIterations = 2
+ fork = 3
+ iterations = 5
+ timeOnIteration = '1s'
+}
\ No newline at end of file
diff --git a/config/checkstyle/checkstyle_checks.xml b/config/checkstyle/checkstyle_checks.xml
index 171ec589d..708f38789 100644
--- a/config/checkstyle/checkstyle_checks.xml
+++ b/config/checkstyle/checkstyle_checks.xml
@@ -123,7 +123,7 @@
-
+
@@ -410,7 +410,7 @@
-
+
diff --git a/eclipse-java-google-style.xml b/config/formatter/eclipse-java-google-style.xml
similarity index 99%
rename from eclipse-java-google-style.xml
rename to config/formatter/eclipse-java-google-style.xml
index 39ada243e..5f9965da0 100644
--- a/eclipse-java-google-style.xml
+++ b/config/formatter/eclipse-java-google-style.xml
@@ -65,7 +65,7 @@
-
+
@@ -167,7 +167,7 @@
-
+
@@ -241,7 +241,7 @@
-
+
diff --git a/ruleset.xml b/config/pmd/ruleset.xml
similarity index 69%
rename from ruleset.xml
rename to config/pmd/ruleset.xml
index 1d06a9911..45804d4c0 100644
--- a/ruleset.xml
+++ b/config/pmd/ruleset.xml
@@ -20,28 +20,24 @@ under the License.
- The default ruleset used by the Maven PMD Plugin, when no other ruleset is specified.
- It contains the rules of the old (pre PMD 6.0.0) rulesets java-basic, java-empty, java-imports,
- java-unnecessary, java-unusedcode.
+ Custom PMD ruleset, compatible with PMD 7.x.
- This ruleset might be used as a starting point for an own customized ruleset [0].
+ Based on the old (pre PMD 6.0.0) rulesets java-basic, java-empty, java-imports,
+ java-unnecessary, java-unusedcode, migrated for PMD 7.
- [0] https://pmd.github.io/latest/pmd_userdocs_making_rulesets.html
-
+ This ruleset might be used as a starting point for an own customized ruleset [0].
+
+ [0] https://pmd.github.io/latest/pmd_userdocs_making_rulesets.html
+
-
-
-
-
-
@@ -50,8 +46,15 @@ under the License.
-
-
+
+
+
+
+
+
+
@@ -68,11 +71,16 @@ under the License.
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -82,17 +90,10 @@ under the License.
+
+
-
-
-
-
-
-
-
-
-
-
+
@@ -100,18 +101,14 @@ under the License.
-
-
-
-
+
-
-
-
+
+
-
+
\ No newline at end of file
diff --git a/spotBugsExcludeFilter.xml b/config/spotbugs/spotBugsExcludeFilter.xml
similarity index 100%
rename from spotBugsExcludeFilter.xml
rename to config/spotbugs/spotBugsExcludeFilter.xml
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 000000000..8b590d14c
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,17 @@
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx8G -Xss8m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError
+
+org.gradle.caching=true
+
+# Modularise your project and enable parallel build
+org.gradle.parallel=true
+
+# Enable configure on demand.
+org.gradle.configureondemand=true
+
+# see https://docs.gradle.org/current/userguide/upgrading_version_8.html#xml_parsing_now_requires_recent_parsers
+systemProp.javax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
+systemProp.javax.xml.transform.TransformerFactory=com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
+systemProp.javax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
+
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 7454180f2..b1b8ef56b 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 69a971507..a9db11550 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,9 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip
+networkTimeout=10000
+retries=0
+retryBackOffMs=500
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 744e882ed..379a6582e 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
-#!/usr/bin/env sh
+#!/bin/sh
#
-# Copyright 2015 the original author or authors.
+# Copyright © 2015 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,81 +15,114 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+# SPDX-License-Identifier: Apache-2.0
+#
##############################################################################
-##
-## Gradle start up script for UN*X
-##
+#
+# gradlew start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh gradlew
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob//platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
##############################################################################
# Attempt to set APP_HOME
+
# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
warn () {
echo "$*"
-}
+} >&2
die () {
echo
echo "$*"
echo
exit 1
-}
+} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MSYS* | MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
esac
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACMD=$JAVA_HOME/jre/sh/java
else
- JAVACMD="$JAVA_HOME/bin/java"
+ JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,88 +131,118 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
fi
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
# Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
fi
- i=`expr $i + 1`
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
done
- case $i in
- 0) set -- ;;
- 1) set -- "$args0" ;;
- 2) set -- "$args0" "$args1" ;;
- 3) set -- "$args0" "$args1" "$args2" ;;
- 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
fi
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=`save "$@"`
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
index ac1b06f93..a51ec4f58 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -1,89 +1,82 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+@rem SPDX-License-Identifier: Apache-2.0
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem gradlew startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables, and ensure extensions are enabled
+setlocal EnableExtensions
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+"%COMSPEC%" /c exit 1
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+"%COMSPEC%" /c exit 1
+
+:execute
+@rem Setup the command line
+
+
+
+@rem Execute gradlew
+@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
+@rem which allows us to clear the local environment before executing the java command
+endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
+
+:exitWithErrorLevel
+@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
+"%COMSPEC%" /c exit %ERRORLEVEL%
diff --git a/nb-configuration.xml b/nb-configuration.xml
index 8771b5deb..2c751cae4 100644
--- a/nb-configuration.xml
+++ b/nb-configuration.xml
@@ -19,7 +19,7 @@
LF
false
true
- JDK_1.8
+ JDK_11
false
none
4
diff --git a/pom.xml b/pom.xml
index 11a459882..cd1e28b0b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,15 +1,21 @@
+
4.0.0
+
com.github.jsqlparser
jsqlparser
- 4.3-SNAPSHOT
- JSQLParser library
+ 5.4-SNAPSHOT
+ bundle
+
+ JSQLParser library
+ JSqlParser parses an SQL statement and translate it into a hierarchy of Java classes.
+ The generated hierarchy can be navigated using the Visitor Pattern.
+ https://github.com/JSQLParser/JSqlParser
2004
+
- JSQLParser
+ JSQLParser
- bundle
- https://github.com/JSQLParser/JSqlParser
@@ -24,133 +30,338 @@
+
+
+ Tobias Warneke
+ t.warneke@gmx.net
+
+
+
+
+ scm:git:https://github.com/JSQLParser/JSqlParser.git
+ scm:git:ssh://git@github.com:JSQLParser/JSqlParser.git
+ https://github.com/JSQLParser/JSqlParser.git
+ HEAD
+
+
+
+ GitHub Issues
+ https://github.com/JSQLParser/JSqlParser/issues
+
+
+
+
+
+ sonatype-nexus-snapshots
+ https://central.sonatype.com/repository/maven-snapshots/
+
+ false
+
+
+ true
+
+
+
+
+
+
+ 11
+ [17,24)
+ IfMatch
+
+ UTF-8
+ UTF-8
+
+
+ 2026-01-01T00:00:00Z
+
+
+
+
+ 3.3.0
+ 3.6.3
+ 3.15.0
+ 3.5.0
+ 3.5.0
+ 3.1.4
+ 3.1.4
+ 3.22.0
+ 3.4.0
+ 3.12.0
+ 3.5.6
+ 3.3.1
+ 3.2.8
+ 3.28.0
+ 3.6.0
+ 3.6.0
+ 3.9.0
+ 5.1.8
+ 3.6.0
+ 3.5.0
+ 2.0.0
+ 3.8.0
+ 0.8.15
+ 3.8.0
+ 4.9.3.0
+ 0.10.0
+
+
+ 7.17.0
+ 10.23.1
+
+
+
+ [8.1.1.1939,)
+ 5.14.4
+ 5.23.0
+ 3.27.7
+ 3.0
+ 2.18.0
+ 3.18.0
+ 2.3.232
+ 1.37
+
+
+ f22e0543
+
+
+
+
+
+ org.junit
+ junit-bom
+ ${junit.version}
+ pom
+ import
+
+
+
+
+
+ com.manticore-projects.jsqlformatter
+ javacc-java
+ ${javacc.version}
+ test
+
+
+ com.manticore-projects.jsqlformatter
+ javacc-core
+ ${javacc.version}
+ test
+
commons-io
commons-io
- 2.7
+ ${commons-io.version}
test
- junit
- junit
- 4.13.1
+ org.junit.jupiter
+ junit-jupiter
test
org.mockito
mockito-core
- 2.28.2
+ ${mockito.version}
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ ${mockito.version}
test
org.assertj
assertj-core
- 3.16.1
+ ${assertj.version}
test
org.apache.commons
commons-lang3
- 3.10
+ ${commons-lang3.version}
test
com.h2database
h2
- 1.4.200
+ ${h2.version}
+ test
+
+
+
+
+ org.hamcrest
+ hamcrest
+ ${hamcrest.version}
+ test
+
+
+
+
+ org.openjdk.jmh
+ jmh-core
+ ${jmh.version}
test
-
-
-
- Tobias Warneke
- t.warneke@gmx.net
-
-
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-clean-plugin
+ ${maven-clean-plugin.version}
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ ${maven-resources-plugin.version}
+
+
+ org.apache.maven.plugins
+ maven-install-plugin
+ ${maven-install-plugin.version}
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+ ${maven-deploy-plugin.version}
+
+
+ org.apache.maven.plugins
+ maven-site-plugin
+ ${maven-site-plugin.version}
+
+
+
-
-
- sonatype-nexus-staging
- https://oss.sonatype.org/service/local/staging/deploy/maven2
-
-
- sonatype-nexus-snapshots
- https://oss.sonatype.org/content/repositories/snapshots
-
-
+
+
+
+ org.apache.maven.plugins
+ maven-toolchains-plugin
+ ${maven-toolchains-plugin.version}
+
+
+ select-jdk-toolchain
+
+ select-jdk-toolchain
+
+
+
+
-
- scm:git:https://github.com/JSQLParser/JSqlParser.git
- scm:git:ssh://git@github.com:JSQLParser/JSqlParser.git
- https://github.com/JSQLParser/JSqlParser.git
- HEAD
-
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ ${maven-enforcer-plugin.version}
+
+
+ enforce
+ validate
+
+ enforce
+
+
+
+
+ [3.9.0,)
+
+
+
+
+
+
+
-
- GitHub Issues
- https://github.com/JSQLParser/JSqlParser/issues
-
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ ${exec-maven-plugin.version}
+
+ net.sf.jsqlparser.parser.ParserKeywordsUtils
+
+ src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
+ src/site/sphinx/keywords.rst
+
+
+
-
-
org.apache.maven.plugins
maven-pmd-plugin
- 3.14.0
+ ${maven-pmd-plugin.version}
+ 2
- ${basedir}/ruleset.xml
+ ${project.basedir}/config/pmd/ruleset.xml
**/*Bean.java
**/generated/*.java
+ **/net/sf/jsqlparser/parser/SimpleCharStream.java
- target/generated-sources
- target/generated-test-sources
+ ${project.build.directory}/generated-sources
+ ${project.build.directory}/generated-test-sources
true
pmd
+ process-sources
check
- process-sources
net.sourceforge.pmd
pmd-core
- ${pmdVersion}
+ ${pmd.version}
net.sourceforge.pmd
pmd-java
- ${pmdVersion}
-
-
- net.sourceforge.pmd
- pmd-javascript
- ${pmdVersion}
-
-
- net.sourceforge.pmd
- pmd-jsp
- ${pmdVersion}
+ ${pmd.version}
+
org.codehaus.mojo
build-helper-maven-plugin
- 3.2.0
+ ${build-helper-maven-plugin.version}
add-source
@@ -167,22 +378,47 @@
+
+ org.apache.maven.plugins
maven-compiler-plugin
- 3.7.0
+ ${maven-compiler-plugin.version}
- 1.8
- 1.8
- true
+ ${maven.compiler.release}
${project.build.sourceEncoding}
+ true
true
+ 2000m
+
+ true
+
+ -J-Xss4M
+
+
+
+
+ default-testCompile
+
+ testCompile
+
+
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ ${jmh.version}
+
+
+
+
+
+
org.javacc.plugin
javacc-maven-plugin
- 3.0.3
-
+ ${javacc-maven-plugin.version}
javacc
@@ -190,168 +426,167 @@
jjtree-javacc
+
+
+ -CODE_GENERATOR:"Java"
+ -GRAMMAR_ENCODING:"UTF-8"
+
+
+ -GRAMMAR_ENCODING:"UTF-8"
+ -CODE_GENERATOR:"Java"
+
+
-
-
-
- jjtree
- generate-sources
-
- jjtree
-
-
- net.java.dev.javacc
- javacc
- 7.0.10
+ com.manticore-projects.jsqlformatter
+ javacc-java
+ ${javacc.version}
+
+
+ com.manticore-projects.jsqlformatter
+ javacc-core
+ ${javacc.version}
-
- org.apache.maven.plugins
- maven-eclipse-plugin
- 2.9
-
-
- /target/generated-sources/javacc
-
-
-
-
- org.apache.maven.plugins
- maven-resources-plugin
- 2.6
-
- ${project.build.sourceEncoding}
-
-
+
org.codehaus.mojo
license-maven-plugin
- 1.17
+ ${license-maven-plugin.version}
false
false
false
dual_lgpl_ap2
${project.baseUri}/src/license
+
+ site/sphinx/**
+
- first
+ update-file-header
+ process-sources
update-file-header
- process-sources
+
org.apache.maven.plugins
maven-release-plugin
- 2.5.3
+ ${maven-release-plugin.version}
true
false
forked-path
+ sign-release-artifacts
-
-
- org.apache.maven.scm
- maven-scm-provider-gitexe
- 1.9.5
-
-
+
org.apache.maven.plugins
maven-source-plugin
- 3.2.1
+ ${maven-source-plugin.version}
attach-sources
- jar
+ jar-no-fork
+
org.apache.maven.plugins
maven-javadoc-plugin
- 3.1.1
+ ${maven-javadoc-plugin.version}
attach-javadocs
-
- ${javadoc.opts}
- net.sf.jsqlparser.parser
-
jar
+
+ net.sf.jsqlparser.parser
+ none
+
+ true
+ true
+ 2g
+ 800m
+
+ -J-Xss4m
+
+
-
- maven-site-plugin
- 3.7.1
-
-
- attach-descriptor
-
- attach-descriptor
-
-
-
-
- en
-
-
-
- org.eluder.coveralls
- coveralls-maven-plugin
- 3.1.0
-
-
- org.codehaus.mojo
- cobertura-maven-plugin
- 2.7
-
- xml
-
-
- net/sf/jsqlparser/parser/*.class
- net/sf/jsqlparser/JSQLParserException.class
-
-
-
-
+
+
org.apache.felix
maven-bundle-plugin
- 3.0.1
+ ${maven-bundle-plugin.version}
true
+
+
+ net.sf.jsqlparser
+
+
+
org.apache.maven.plugins
maven-surefire-plugin
- 3.0.0-M4
+ ${maven-surefire-plugin.version}
false
+
+ false
+
+
+ @{jacocoArgLine}
+ --add-opens=java.base/java.lang=ALL-UNNAMED
+ --add-opens=java.base/java.util=ALL-UNNAMED
+ -Xmx2G -Xms800m -Xss4m
+
+
org.jacoco
jacoco-maven-plugin
- 0.8.7
+ ${jacoco-maven-plugin.version}
+ prepare-agent
prepare-agent
+
+
+ jacocoArgLine
+
report
@@ -362,15 +597,63 @@
+
+
+
+ com.diffplug.spotless
+ spotless-maven-plugin
+ ${spotless-maven-plugin.version}
+
+
+ origin/master
+
+
+
+ *.md
+ .gitignore
+
+
+
+
+ true
+ 4
+
+
+
+
+
+ src/main/java/**/*.java
+ src/test/java/**/*.java
+
+
+
+
+
+ config/formatter/eclipse-java-google-style.xml
+
+
+
+
+
+
+
+ org.sonatype.central
+ central-publishing-maven-plugin
+ ${central-publishing-maven-plugin.version}
+ true
+
+ sonatype-nexus
+
+
-
+
org.apache.maven.plugins
maven-surefire-report-plugin
- 2.22.2
+ ${maven-surefire-plugin.version}
${project.reporting.outputDirectory}/testresults
@@ -378,117 +661,33 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 3.1.1
+ ${maven-javadoc-plugin.version}
true
- 800m
none
-
-
+
+ true
+ 2g
+ 800m
+
+ -J-Xss2m
+
org.apache.maven.plugins
maven-project-info-reports-plugin
- 3.0.0
+ ${maven-project-info-reports-plugin.version}
org.apache.maven.plugins
maven-jxr-plugin
- 3.0.0
-
-
-
-
-
- org.codehaus.mojo
- findbugs-maven-plugin
- 3.0.5
-
-
-
-
-
- org.codehaus.mojo
- javacc-maven-plugin
- 2.6
-
-
- false
-
-
- false
-
-
- false
-
-
-
-
- ${project.reporting.outputDirectory}
-
+ com.github.spotbugs
+ spotbugs-maven-plugin
+ ${spotbugs-maven-plugin.version}
@@ -507,7 +706,7 @@
org.apache.maven.plugins
maven-gpg-plugin
- 1.6
+ ${maven-gpg-plugin.version}
sign-artifacts
@@ -516,7 +715,12 @@
sign
- f22e0543
+ ${gpg.keyname}
+
+
+ --pinentry-mode
+ loopback
+
@@ -524,32 +728,20 @@
-
-
+
check.sources
!skipCheckSources
- [1.8,)
org.apache.maven.plugins
maven-checkstyle-plugin
- 3.1.0
+ ${maven-checkstyle-plugin.version}
verify-style
@@ -562,37 +754,33 @@
true
true
+
${project.build.sourceDirectory}
+ **/module-info.java,**/net/sf/jsqlparser/parser/SimpleCharStream.java
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -601,33 +789,24 @@
com.puppycrawl.tools
checkstyle
- 8.29
+ ${checkstyle.version}
+
-
+
skip.all
-
- false
-
true
true
+ true
true
true
-
-
- UTF-8
- 6.36.0
-
-
- JSqlParser parses an SQL statement and translate it into a hierarchy of Java classes.
- The generated hierarchy can be navigated using the Visitor Pattern.
-
+
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 523623eb1..d0322b0de 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -2,4 +2,4 @@
* This file was generated by the Gradle 'init' task.
*/
-rootProject.name = 'jsqlparser'
+rootProject.name = 'JSQLParser'
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
new file mode 100644
index 000000000..ada4bfdf4
--- /dev/null
+++ b/src/main/java/module-info.java
@@ -0,0 +1,61 @@
+/*-
+ * #%L
+ * JSQLParser library
+ * %%
+ * Copyright (C) 2004 - 2024 JSQLParser
+ * %%
+ * Dual licensed under GNU LGPL 2.1 or Apache License 2.0
+ * #L%
+ */
+module net.sf.jsqlparser {
+ requires java.sql;
+ requires java.logging;
+ requires java.desktop;
+
+ exports net.sf.jsqlparser;
+ exports net.sf.jsqlparser.expression;
+ exports net.sf.jsqlparser.expression.operators.arithmetic;
+ exports net.sf.jsqlparser.expression.operators.conditional;
+ exports net.sf.jsqlparser.expression.operators.relational;
+ exports net.sf.jsqlparser.parser;
+ exports net.sf.jsqlparser.parser.feature;
+ exports net.sf.jsqlparser.schema;
+ exports net.sf.jsqlparser.statement;
+ exports net.sf.jsqlparser.statement.alter;
+ exports net.sf.jsqlparser.statement.alter.sequence;
+ exports net.sf.jsqlparser.statement.analyze;
+ exports net.sf.jsqlparser.statement.comment;
+ exports net.sf.jsqlparser.statement.create.function;
+ exports net.sf.jsqlparser.statement.create.index;
+ exports net.sf.jsqlparser.statement.create.policy;
+ exports net.sf.jsqlparser.statement.create.procedure;
+ exports net.sf.jsqlparser.statement.create.schema;
+ exports net.sf.jsqlparser.statement.create.sequence;
+ exports net.sf.jsqlparser.statement.create.synonym;
+ exports net.sf.jsqlparser.statement.create.table;
+ exports net.sf.jsqlparser.statement.create.view;
+ exports net.sf.jsqlparser.statement.delete;
+ exports net.sf.jsqlparser.statement.drop;
+ exports net.sf.jsqlparser.statement.execute;
+ exports net.sf.jsqlparser.statement.export;
+ exports net.sf.jsqlparser.statement.grant;
+ exports net.sf.jsqlparser.statement.imprt;
+ exports net.sf.jsqlparser.statement.insert;
+ exports net.sf.jsqlparser.statement.lock;
+ exports net.sf.jsqlparser.statement.merge;
+ exports net.sf.jsqlparser.statement.piped;
+ exports net.sf.jsqlparser.statement.refresh;
+ exports net.sf.jsqlparser.statement.select;
+ exports net.sf.jsqlparser.statement.show;
+ exports net.sf.jsqlparser.statement.truncate;
+ exports net.sf.jsqlparser.statement.update;
+ exports net.sf.jsqlparser.statement.upsert;
+ exports net.sf.jsqlparser.util;
+ exports net.sf.jsqlparser.util.cnfexpression;
+ exports net.sf.jsqlparser.util.deparser;
+ exports net.sf.jsqlparser.util.validation;
+ exports net.sf.jsqlparser.util.validation.allowedtypes;
+ exports net.sf.jsqlparser.util.validation.feature;
+ exports net.sf.jsqlparser.util.validation.metadata;
+ exports net.sf.jsqlparser.util.validation.validator;
+}
diff --git a/src/main/java/net/sf/jsqlparser/Model.java b/src/main/java/net/sf/jsqlparser/Model.java
index 3b7378d14..4ad52f429 100644
--- a/src/main/java/net/sf/jsqlparser/Model.java
+++ b/src/main/java/net/sf/jsqlparser/Model.java
@@ -9,10 +9,16 @@
*/
package net.sf.jsqlparser;
+import java.io.Serializable;
+
/**
- * A marker interface for jsqlparser-model-classes.
- * The datastructure where the sql syntax is represented by a tree consists of {@link Model}'s
+ *
+ * A marker interface for jsqlparser-model-classes.
+ *
+ *
+ * The datastructure where the sql syntax is represented by a tree consists of {@link Model}'s
+ *
*/
-public interface Model {
+public interface Model extends Serializable {
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/Alias.java b/src/main/java/net/sf/jsqlparser/expression/Alias.java
index e6718f67a..ffc599680 100644
--- a/src/main/java/net/sf/jsqlparser/expression/Alias.java
+++ b/src/main/java/net/sf/jsqlparser/expression/Alias.java
@@ -9,15 +9,27 @@
*/
package net.sf.jsqlparser.expression;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
+
+import net.sf.jsqlparser.schema.MultiPartName;
import net.sf.jsqlparser.statement.create.table.ColDataType;
-public class Alias {
+/**
+ * The type Alias for Tables, Columns or Views.
+ *
+ * We support three different types:
+ * 1) Simple String: `SELECT 1 AS "ALIAS"` when NAME is set and aliasColumns has no elements
+ * 2) UDF Aliases: `SELECT udf(1,2,3) AS "Alias(a,b,c)"` " when NAME!=null and aliasColumns has elements
+ * 3) Column lists for LATERAL VIEW: `SELECT * from a LATERAL VIEW EXPLODE ... AS a, b, c`, when NAME is NULL and aliasColumns has elements
+ * @see Spark LATERAL VIEW
+ */
+public class Alias implements Serializable {
private String name;
private boolean useAs = true;
@@ -36,6 +48,10 @@ public String getName() {
return name;
}
+ public String getUnquotedName() {
+ return MultiPartName.unquote(name);
+ }
+
public void setName(String name) {
this.name = name;
}
@@ -58,20 +74,20 @@ public void setAliasColumns(List aliasColumns) {
@Override
public String toString() {
- String alias = (useAs ? " AS " : " ") + name;
+ String alias = (useAs ? " AS " : " ") + (name != null ? name : "");
if (aliasColumns != null && !aliasColumns.isEmpty()) {
- String ac = "";
+ StringBuilder ac = new StringBuilder();
for (AliasColumn col : aliasColumns) {
if (ac.length() > 0) {
- ac += ", ";
+ ac.append(", ");
}
- ac += col.name;
+ ac.append(col.name);
if (col.colDataType != null) {
- ac += " " + col.colDataType.toString();
+ ac.append(" ").append(col.colDataType);
}
}
- alias += "(" + ac + ")";
+ alias += name != null ? "(" + ac + ")" : ac;
}
return alias;
@@ -92,19 +108,31 @@ public Alias withAliasColumns(List aliasColumns) {
return this;
}
+
+ public Alias addAliasColumns(String... columnNames) {
+ List collection =
+ Optional.ofNullable(getAliasColumns()).orElseGet(ArrayList::new);
+ for (String columnName : columnNames) {
+ collection.add(new AliasColumn(columnName));
+ }
+ return this.withAliasColumns(collection);
+ }
+
public Alias addAliasColumns(AliasColumn... aliasColumns) {
- List collection = Optional.ofNullable(getAliasColumns()).orElseGet(ArrayList::new);
+ List collection =
+ Optional.ofNullable(getAliasColumns()).orElseGet(ArrayList::new);
Collections.addAll(collection, aliasColumns);
return this.withAliasColumns(collection);
}
public Alias addAliasColumns(Collection extends AliasColumn> aliasColumns) {
- List collection = Optional.ofNullable(getAliasColumns()).orElseGet(ArrayList::new);
+ List collection =
+ Optional.ofNullable(getAliasColumns()).orElseGet(ArrayList::new);
collection.addAll(aliasColumns);
return this.withAliasColumns(collection);
}
- public static class AliasColumn {
+ public static class AliasColumn implements Serializable {
public final String name;
public final ColDataType colDataType;
diff --git a/src/main/java/net/sf/jsqlparser/expression/AllValue.java b/src/main/java/net/sf/jsqlparser/expression/AllValue.java
new file mode 100644
index 000000000..14f924ab8
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/AllValue.java
@@ -0,0 +1,25 @@
+/*-
+ * #%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;
+
+public class AllValue extends ASTNodeAccessImpl implements Expression {
+
+ @Override
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
+ }
+
+ @Override
+ public String toString() {
+ return "ALL";
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java b/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java
index 7edd1e717..d94d4ef2e 100644
--- a/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java
@@ -9,24 +9,26 @@
*/
package net.sf.jsqlparser.expression;
-import java.util.List;
-import static java.util.stream.Collectors.joining;
+import java.util.Locale;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
+import net.sf.jsqlparser.statement.select.Limit;
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 path. e.g. row_number() over (order by test). Additionally, there can be an
+ * expression for an analytical aggregate like sum(col) or the "all columns" wildcard like count(*).
*
* @author tw
*/
public class AnalyticExpression extends ASTNodeAccessImpl implements Expression {
- private final OrderByClause orderBy = new OrderByClause();
- private final PartitionByClause partitionBy = new PartitionByClause();
+
private String name;
private Expression expression;
private Expression offset;
@@ -36,50 +38,77 @@ public class AnalyticExpression extends ASTNodeAccessImpl implements Expression
private AnalyticType type = AnalyticType.OVER;
private boolean distinct = false;
private boolean unique = false;
- private boolean ignoreNulls = false;
+ private boolean ignoreNullsOutside = false; // IGNORE NULLS outside function parameters
private Expression filterExpression = null;
- private WindowElement windowElement = null;
private List funcOrderBy = null;
+ private String onOverflowTruncate = null;
- public AnalyticExpression() {
- }
+ private String windowName = null; // refers to an external window definition (paritionBy,
+ // orderBy, windowElement)
+ private WindowDefinition windowDef = new WindowDefinition();
+
+ private Function.HavingClause havingClause;
+
+ private Function.NullHandling nullHandling = null;
+
+ private Limit limit = null;
+
+ private List keywordArguments = null;
+
+ public AnalyticExpression() {}
public AnalyticExpression(Function function) {
- name = function.getName();
- allColumns = function.isAllColumns();
- distinct = function.isDistinct();
- unique = function.isUnique();
- funcOrderBy = function.getOrderByElements();
+ this.name = String.join(" ", function.getMultipartName());
+ this.allColumns = function.isAllColumns();
+ this.distinct = function.isDistinct();
+ this.unique = function.isUnique();
- ExpressionList list = function.getParameters();
+ ExpressionList extends Expression> list = function.getParameters();
if (list != null) {
- if (list.getExpressions().size() > 3) {
- throw new IllegalArgumentException("function object not valid to initialize analytic expression");
+ if (list.size() > 3) {
+ throw new IllegalArgumentException(
+ "function object not valid to initialize analytic expression");
}
- expression = list.getExpressions().get(0);
- if (list.getExpressions().size() > 1) {
- offset = list.getExpressions().get(1);
+ expression = list.get(0);
+ if (list.size() > 1) {
+ offset = list.get(1);
}
- if (list.getExpressions().size() > 2) {
- defaultValue = list.getExpressions().get(2);
+ if (list.size() > 2) {
+ defaultValue = list.get(2);
}
}
- ignoreNulls = function.isIgnoreNulls();
- keep = function.getKeep();
+ this.havingClause = function.getHavingClause();
+ this.ignoreNullsOutside = function.isIgnoreNullsOutside();
+ this.nullHandling = function.getNullHandling();
+ this.funcOrderBy = function.getOrderByElements();
+ this.onOverflowTruncate = function.getOnOverflowTruncate();
+ this.limit = function.getLimit();
+ this.keep = function.getKeep();
+ this.keywordArguments = function.getKeywordArguments();
}
+
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public List getOrderByElements() {
- return orderBy.getOrderByElements();
+ return windowDef.orderBy.getOrderByElements();
}
public void setOrderByElements(List orderByElements) {
- orderBy.setOrderByElements(orderByElements);
+ windowDef.orderBy.setOrderByElements(orderByElements);
+ }
+
+ public String getOnOverflowTruncate() {
+ return onOverflowTruncate;
+ }
+
+ public AnalyticExpression setOnOverflowTruncate(String onOverflowTruncate) {
+ this.onOverflowTruncate = onOverflowTruncate;
+ return this;
}
public KeepExpression getKeep() {
@@ -90,20 +119,21 @@ public void setKeep(KeepExpression keep) {
this.keep = keep;
}
- public ExpressionList getPartitionExpressionList() {
- return partitionBy.getPartitionExpressionList();
+ public ExpressionList> getPartitionExpressionList() {
+ return windowDef.partitionBy;
}
- public void setPartitionExpressionList(ExpressionList partitionExpressionList) {
+ public void setPartitionExpressionList(ExpressionList partitionExpressionList) {
setPartitionExpressionList(partitionExpressionList, false);
}
- public void setPartitionExpressionList(ExpressionList partitionExpressionList, boolean brackets) {
- partitionBy.setPartitionExpressionList(partitionExpressionList, brackets);
+ public void setPartitionExpressionList(ExpressionList partitionExpressionList,
+ boolean brackets) {
+ windowDef.partitionBy.setExpressions(partitionExpressionList, brackets);
}
public boolean isPartitionByBrackets() {
- return partitionBy.isBrackets();
+ return windowDef.partitionBy.isBrackets();
}
public String getName() {
@@ -139,11 +169,11 @@ public void setDefaultValue(Expression defaultValue) {
}
public WindowElement getWindowElement() {
- return windowElement;
+ return windowDef.windowElement;
}
public void setWindowElement(WindowElement windowElement) {
- this.windowElement = windowElement;
+ windowDef.windowElement = windowElement;
}
public AnalyticType getType() {
@@ -171,15 +201,84 @@ public void setUnique(boolean unique) {
}
public boolean isIgnoreNulls() {
- return ignoreNulls;
+ return this.nullHandling == Function.NullHandling.IGNORE_NULLS;
}
public void setIgnoreNulls(boolean ignoreNulls) {
- this.ignoreNulls = ignoreNulls;
+ this.nullHandling = ignoreNulls ? Function.NullHandling.IGNORE_NULLS : null;
+ }
+
+ public boolean isIgnoreNullsOutside() {
+ return ignoreNullsOutside;
+ }
+
+ public void setIgnoreNullsOutside(boolean ignoreNullsOutside) {
+ this.ignoreNullsOutside = ignoreNullsOutside;
+ }
+
+ public String getWindowName() {
+ return windowName;
+ }
+
+ public void setWindowName(String windowName) {
+ this.windowName = windowName;
+ }
+
+ public WindowDefinition getWindowDefinition() {
+ return windowDef;
+ }
+
+ public void setWindowDefinition(WindowDefinition windowDef) {
+ this.windowDef = windowDef;
+ }
+
+
+ public Function.HavingClause getHavingClause() {
+ return havingClause;
+ }
+
+ public AnalyticExpression setHavingClause(Function.HavingClause havingClause) {
+ this.havingClause = havingClause;
+ return this;
+ }
+
+ public AnalyticExpression setHavingClause(String havingType, Expression expression) {
+ this.havingClause = new Function.HavingClause(
+ Function.HavingClause.HavingType
+ .valueOf(havingType.trim().toUpperCase(Locale.ROOT)),
+ expression);
+ return this;
+ }
+
+ public Function.NullHandling getNullHandling() {
+ return nullHandling;
+ }
+
+ public AnalyticExpression setNullHandling(Function.NullHandling nullHandling) {
+ this.nullHandling = nullHandling;
+ return this;
+ }
+
+ public Limit getLimit() {
+ return limit;
+ }
+
+ public AnalyticExpression setLimit(Limit limit) {
+ this.limit = limit;
+ return this;
+ }
+
+ public List getKeywordArguments() {
+ return keywordArguments;
+ }
+
+ public void setKeywordArguments(List keywordArguments) {
+ this.keywordArguments = keywordArguments;
}
@Override
- @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity", "PMD.MissingBreakInSwitch"})
+ @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity",
+ "PMD.MissingBreakInSwitch"})
public String toString() {
StringBuilder b = new StringBuilder();
@@ -188,61 +287,101 @@ public String toString() {
b.append("DISTINCT ");
}
if (expression != null) {
- b.append(expression.toString());
+ b.append(expression);
if (offset != null) {
- b.append(", ").append(offset.toString());
+ b.append(", ").append(offset);
if (defaultValue != null) {
- b.append(", ").append(defaultValue.toString());
+ b.append(", ").append(defaultValue);
}
}
} else if (isAllColumns()) {
b.append("*");
}
- if (isIgnoreNulls()) {
- b.append(" IGNORE NULLS");
+
+ if (havingClause != null) {
+ havingClause.appendTo(b);
}
- if (funcOrderBy!=null) {
+
+ if (nullHandling != null && !ignoreNullsOutside) {
+ switch (nullHandling) {
+ case IGNORE_NULLS:
+ b.append(" IGNORE NULLS");
+ break;
+ case RESPECT_NULLS:
+ b.append(" RESPECT NULLS");
+ break;
+ }
+ }
+
+ if (funcOrderBy != null) {
b.append(" ORDER BY ");
- b.append( funcOrderBy.stream().map(OrderByElement::toString).collect(joining(", ")));
+ b.append(funcOrderBy.stream().map(OrderByElement::toString).collect(joining(", ")));
+ }
+
+ if (onOverflowTruncate != null) {
+ b.append(" ON OVERFLOW ").append(onOverflowTruncate);
+ }
+
+ if (limit != null) {
+ b.append(limit);
+ }
+
+ // Generic keyword arguments (e.g. SEPARATOR ',')
+ if (keywordArguments != null) {
+ for (Function.KeywordArgument ka : keywordArguments) {
+ ka.appendTo(b);
+ }
}
-
+
b.append(") ");
if (keep != null) {
- b.append(keep.toString()).append(" ");
+ b.append(keep).append(" ");
}
if (filterExpression != null) {
b.append("FILTER (WHERE ");
- b.append(filterExpression.toString());
+ b.append(filterExpression);
b.append(")");
if (type != AnalyticType.FILTER_ONLY) {
b.append(" ");
}
}
+ if (nullHandling != null && ignoreNullsOutside) {
+ switch (nullHandling) {
+ case IGNORE_NULLS:
+ b.append(" IGNORE NULLS ");
+ break;
+ case RESPECT_NULLS:
+ b.append(" RESPECT NULLS ");
+ break;
+ }
+ }
+
switch (type) {
case FILTER_ONLY:
return b.toString();
case WITHIN_GROUP:
b.append("WITHIN GROUP");
break;
+ case WITHIN_GROUP_OVER:
+ b.append("WITHIN GROUP (");
+ windowDef.orderBy.toStringOrderByElements(b);
+ b.append(") OVER (");
+ windowDef.partitionBy.toStringPartitionBy(b);
+ b.append(")");
+ break;
default:
b.append("OVER");
}
- b.append(" (");
-
- partitionBy.toStringPartitionBy(b);
- orderBy.toStringOrderByElements(b);
- if (windowElement != null) {
- if (orderBy.getOrderByElements() != null) {
- b.append(' ');
- }
- b.append(windowElement);
+ if (windowName != null) {
+ b.append(" ").append(windowName);
+ } else if (type != AnalyticType.WITHIN_GROUP_OVER) {
+ b.append(" ");
+ b.append(windowDef.toString());
}
- b.append(")");
-
return b.toString();
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/AnalyticType.java b/src/main/java/net/sf/jsqlparser/expression/AnalyticType.java
index 2f60840ff..ea083c902 100644
--- a/src/main/java/net/sf/jsqlparser/expression/AnalyticType.java
+++ b/src/main/java/net/sf/jsqlparser/expression/AnalyticType.java
@@ -9,8 +9,12 @@
*/
package net.sf.jsqlparser.expression;
+import java.util.Locale;
+
public enum AnalyticType {
- OVER,
- WITHIN_GROUP,
- FILTER_ONLY
+ OVER, WITHIN_GROUP, WITHIN_GROUP_OVER, FILTER_ONLY;
+
+ public static AnalyticType from(String type) {
+ return Enum.valueOf(AnalyticType.class, type.toUpperCase(Locale.ROOT));
+ }
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/AnyComparisonExpression.java b/src/main/java/net/sf/jsqlparser/expression/AnyComparisonExpression.java
index 01a770950..cf3ba46d5 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.SubSelect;
+import net.sf.jsqlparser.statement.select.Select;
/**
* Combines ANY and SOME expressions.
@@ -19,56 +18,22 @@
* @author toben
*/
public class AnyComparisonExpression extends ASTNodeAccessImpl implements Expression {
-
- private final ItemsList itemsList;
- private boolean useBracketsForValues = false;
- private final SubSelect subSelect;
+ private final Select select;
private final AnyType anyType;
- public AnyComparisonExpression(AnyType anyType, SubSelect 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 SubSelect getSubSelect() {
- return subSelect;
- }
-
- public ItemsList getItemsList() {
- return itemsList;
- }
-
- public boolean isUsingItemsList() {
- return itemsList!=null;
+ this.select = select;
}
- public boolean isUsingSubSelect() {
- return subSelect!=null;
- }
-
- public boolean isUsingBracketsForValues() {
- return useBracketsForValues;
+ public Select getSelect() {
+ return select;
}
- public void setUseBracketsForValues(boolean useBracketsForValues) {
- this.useBracketsForValues = useBracketsForValues;
- }
-
- public AnyComparisonExpression withUseBracketsForValues(boolean useBracketsForValues) {
- this.setUseBracketsForValues(useBracketsForValues);
- return this;
- }
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public AnyType getAnyType() {
@@ -77,12 +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..da5495d07 100644
--- a/src/main/java/net/sf/jsqlparser/expression/AnyType.java
+++ b/src/main/java/net/sf/jsqlparser/expression/AnyType.java
@@ -9,9 +9,12 @@
*/
package net.sf.jsqlparser.expression;
+import java.util.Locale;
+
public enum AnyType {
+ ANY, SOME, ALL;
- ANY,
- SOME,
- ALL
+ public static AnyType from(String type) {
+ return Enum.valueOf(AnyType.class, type.toUpperCase(Locale.ROOT));
+ }
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/ArrayConstructor.java b/src/main/java/net/sf/jsqlparser/expression/ArrayConstructor.java
index 079191622..5e1c8d0e6 100644
--- a/src/main/java/net/sf/jsqlparser/expression/ArrayConstructor.java
+++ b/src/main/java/net/sf/jsqlparser/expression/ArrayConstructor.java
@@ -9,20 +9,29 @@
*/
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;
+import net.sf.jsqlparser.statement.create.table.ColDataType;
public class ArrayConstructor extends ASTNodeAccessImpl implements Expression {
- private List expressions;
+ private ExpressionList> expressions;
private boolean arrayKeyword;
+ private ColDataType dataType;
+
+ public ArrayConstructor(ExpressionList> expressions, boolean arrayKeyword) {
+ this.expressions = expressions;
+ this.arrayKeyword = arrayKeyword;
+ }
+
+ public ArrayConstructor(Expression... expressions) {
+ this(new ExpressionList(expressions), false);
+ }
- public List getExpressions() {
+ public ExpressionList> getExpressions() {
return expressions;
}
- public void setExpressions(List expressions) {
+ public void setExpressions(ExpressionList> expressions) {
this.expressions = expressions;
}
@@ -34,14 +43,18 @@ public void setArrayKeyword(boolean arrayKeyword) {
this.arrayKeyword = arrayKeyword;
}
- public ArrayConstructor(List expressions, boolean arrayKeyword) {
- this.expressions = expressions;
- this.arrayKeyword = arrayKeyword;
+ public ColDataType getDataType() {
+ return dataType;
+ }
+
+ public ArrayConstructor setDataType(ColDataType dataType) {
+ this.dataType = dataType;
+ return this;
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
@@ -49,9 +62,13 @@ public String toString() {
StringBuilder sb = new StringBuilder();
if (arrayKeyword) {
sb.append("ARRAY");
+
+ if (dataType != null) {
+ sb.append("<").append(dataType).append(">");
+ }
}
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/ArrayExpression.java b/src/main/java/net/sf/jsqlparser/expression/ArrayExpression.java
index aef63b8f6..e86f34cad 100644
--- a/src/main/java/net/sf/jsqlparser/expression/ArrayExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/ArrayExpression.java
@@ -23,13 +23,23 @@ public ArrayExpression() {
// empty constructor
}
- public ArrayExpression(Expression objExpression, Expression indexExpression, Expression startIndexExpression, Expression stopIndexExpression) {
+ public ArrayExpression(Expression objExpression, Expression indexExpression,
+ Expression startIndexExpression, Expression stopIndexExpression) {
this.objExpression = objExpression;
this.indexExpression = indexExpression;
this.startIndexExpression = startIndexExpression;
this.stopIndexExpression = stopIndexExpression;
}
+ public ArrayExpression(Expression objExpression, Expression indexExpression) {
+ this(objExpression, indexExpression, null, null);
+ }
+
+ public ArrayExpression(Expression objExpression, Expression startIndexExpression,
+ Expression stopIndexExpression) {
+ this(objExpression, null, startIndexExpression, stopIndexExpression);
+ }
+
public Expression getObjExpression() {
return objExpression;
}
@@ -63,8 +73,8 @@ public void setStopIndexExpression(Expression stopIndexExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
@@ -90,7 +100,8 @@ public ArrayExpression withIndexExpression(Expression indexExpression) {
return this;
}
- public ArrayExpression withRangeExpression(Expression startIndexExpression, Expression stopIndexExpression) {
+ public ArrayExpression withRangeExpression(Expression startIndexExpression,
+ Expression stopIndexExpression) {
this.setStartIndexExpression(startIndexExpression);
this.setStopIndexExpression(stopIndexExpression);
return this;
diff --git a/src/main/java/net/sf/jsqlparser/expression/BinaryExpression.java b/src/main/java/net/sf/jsqlparser/expression/BinaryExpression.java
index cf87acfb3..ffd9c2d84 100644
--- a/src/main/java/net/sf/jsqlparser/expression/BinaryExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/BinaryExpression.java
@@ -9,8 +9,27 @@
*/
package net.sf.jsqlparser.expression;
+import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseRightShift;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor;
+import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
+import net.sf.jsqlparser.expression.operators.arithmetic.Division;
+import net.sf.jsqlparser.expression.operators.arithmetic.IntegerDivision;
+import net.sf.jsqlparser.expression.operators.arithmetic.Modulo;
+import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication;
+import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction;
+import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
+import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
+import net.sf.jsqlparser.expression.operators.conditional.XorExpression;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.Iterator;
+
/**
* A basic class for binary expressions, that is expressions having a left member and a right member
* which are in turn expressions.
@@ -19,52 +38,220 @@ public abstract class BinaryExpression extends ASTNodeAccessImpl implements Expr
private Expression leftExpression;
private Expression rightExpression;
- // private boolean not = false;
- public BinaryExpression() {
+ public BinaryExpression() {}
+
+ public BinaryExpression(Expression leftExpression, Expression rightExpression) {
+ this.leftExpression = leftExpression;
+ this.rightExpression = rightExpression;
+ }
+
+ public static Expression build(Class extends BinaryExpression> clz, Expression... expressions)
+ throws NoSuchMethodException, InvocationTargetException, InstantiationException,
+ IllegalAccessException {
+ switch (expressions.length) {
+ case 0:
+ return new NullValue();
+ case 1:
+ return expressions[0];
+ default:
+ Iterator it = Arrays.stream(expressions).iterator();
+
+ Expression leftExpression = it.next();
+ Expression rightExpression = it.next();
+ BinaryExpression binaryExpression =
+ clz.getConstructor(Expression.class, Expression.class)
+ .newInstance(leftExpression, rightExpression);
+
+ while (it.hasNext()) {
+ rightExpression = it.next();
+ binaryExpression = clz.getConstructor(Expression.class, Expression.class)
+ .newInstance(binaryExpression, rightExpression);
+ }
+ return binaryExpression;
+ }
+ }
+
+ public static Expression add(Expression... expressions) {
+ try {
+ return build(Addition.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression bitAnd(Expression... expressions) {
+ try {
+ return build(BitwiseAnd.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression bitShiftLeft(Expression... expressions) {
+ try {
+ return build(BitwiseLeftShift.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression multiply(Expression... expressions) {
+ try {
+ return build(Multiplication.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression bitOr(Expression... expressions) {
+ try {
+ return build(BitwiseOr.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression bitShiftRight(Expression... expressions) {
+ try {
+ return build(BitwiseRightShift.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression bitXor(Expression... expressions) {
+ try {
+ return build(BitwiseXor.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression concat(Expression... expressions) {
+ try {
+ return build(Concat.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression divide(Expression... expressions) {
+ try {
+ return build(Division.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression divideInt(Expression... expressions) {
+ try {
+ return build(IntegerDivision.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression modulo(Expression... expressions) {
+ try {
+ return build(Modulo.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression subtract(Expression... expressions) {
+ try {
+ return build(Subtraction.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression or(Expression... expressions) {
+ try {
+ return build(OrExpression.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression xor(Expression... expressions) {
+ try {
+ return build(XorExpression.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Expression and(Expression... expressions) {
+ try {
+ return build(AndExpression.class, expressions);
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException
+ | IllegalAccessException e) {
+ // this should never happen, at least I don't see how
+ throw new RuntimeException(e);
+ }
}
public Expression getLeftExpression() {
return leftExpression;
}
+ public void setLeftExpression(Expression expression) {
+ leftExpression = expression;
+ }
+
public Expression getRightExpression() {
return rightExpression;
}
+ public void setRightExpression(Expression expression) {
+ rightExpression = expression;
+ }
+
public BinaryExpression withLeftExpression(Expression expression) {
setLeftExpression(expression);
return this;
}
- public void setLeftExpression(Expression expression) {
- leftExpression = expression;
- }
-
public BinaryExpression withRightExpression(Expression expression) {
setRightExpression(expression);
return this;
}
- public void setRightExpression(Expression expression) {
- rightExpression = expression;
- }
-
- // public void setNot() {
- // not = true;
- // }
- //
- // public void removeNot() {
- // not = false;
- // }
- //
- // public boolean isNot() {
- // return not;
- // }
@Override
public String toString() {
return // (not ? "NOT " : "") +
- getLeftExpression() + " " + getStringExpression() + " " + getRightExpression();
+ getLeftExpression() + " " + getStringExpression() + " " + getRightExpression();
}
public abstract String getStringExpression();
diff --git a/src/main/java/net/sf/jsqlparser/expression/BooleanValue.java b/src/main/java/net/sf/jsqlparser/expression/BooleanValue.java
new file mode 100644
index 000000000..258a89e16
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/BooleanValue.java
@@ -0,0 +1,74 @@
+/*-
+ * #%L
+ * JSQLParser library
+ * %%
+ * Copyright (C) 2004 - 2024 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 java.util.Objects;
+
+/**
+ * A boolean value true/false
+ */
+public final class BooleanValue extends ASTNodeAccessImpl implements Expression {
+
+ private boolean value = false;
+
+ public BooleanValue() {
+ // empty constructor
+ }
+
+ public BooleanValue(String value) {
+ this(Boolean.parseBoolean(value));
+ }
+
+ public BooleanValue(boolean bool) {
+ value = bool;
+ }
+
+ public boolean getValue() {
+ return value;
+ }
+
+ public void setValue(boolean bool) {
+ value = bool;
+ }
+
+ @Override
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
+ }
+
+ @Override
+ public String toString() {
+ return Boolean.toString(value);
+ }
+
+ public BooleanValue withValue(boolean bool) {
+ this.setValue(bool);
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ BooleanValue that = (BooleanValue) o;
+ return Objects.equals(value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(value);
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/CaseExpression.java b/src/main/java/net/sf/jsqlparser/expression/CaseExpression.java
index 371c40bf0..10fd7d56d 100644
--- a/src/main/java/net/sf/jsqlparser/expression/CaseExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/CaseExpression.java
@@ -10,36 +10,43 @@
package net.sf.jsqlparser.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.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.statement.select.PlainSelect;
/**
* CASE/WHEN expression.
+ *
+ * Syntax:
*
- * Syntax:
+ *
+ *
* CASE
* WHEN condition THEN expression
* [WHEN condition THEN expression]...
* [ELSE expression]
* END
- *
+ *
+ *
*
*
* or
*
*
- *
+ *
+ *
* CASE expression
* WHEN condition THEN expression
* [WHEN condition THEN expression]...
* [ELSE expression]
* END
- *
- *
+ *
+ *
*/
public class CaseExpression extends ASTNodeAccessImpl implements Expression {
@@ -48,9 +55,21 @@ public class CaseExpression extends ASTNodeAccessImpl implements Expression {
private List whenClauses;
private Expression elseExpression;
+ public CaseExpression() {}
+
+ public CaseExpression(WhenClause... whenClauses) {
+ this.whenClauses = Arrays.asList(whenClauses);
+ }
+
+ public CaseExpression(Expression elseExpression, WhenClause... whenClauses) {
+ this.elseExpression = elseExpression;
+ this.whenClauses = Arrays.asList(whenClauses);
+ }
+
+
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public Expression getSwitchExpression() {
@@ -91,9 +110,11 @@ public void setWhenClauses(List whenClauses) {
@Override
public String toString() {
- return (usingBrackets ? "(" : "") + "CASE " + ((switchExpression != null) ? switchExpression + " " : "")
+ return (usingBrackets ? "(" : "") + "CASE "
+ + ((switchExpression != null) ? switchExpression + " " : "")
+ PlainSelect.getStringList(whenClauses, false, false) + " "
- + ((elseExpression != null) ? "ELSE " + elseExpression + " " : "") + "END" + (usingBrackets ? ")" : "");
+ + ((elseExpression != null) ? "ELSE " + elseExpression + " " : "") + "END"
+ + (usingBrackets ? ")" : "");
}
public CaseExpression withSwitchExpression(Expression switchExpression) {
@@ -101,6 +122,10 @@ public CaseExpression withSwitchExpression(Expression switchExpression) {
return this;
}
+ public CaseExpression withWhenClauses(WhenClause... whenClauses) {
+ return this.withWhenClauses(Arrays.asList(whenClauses));
+ }
+
public CaseExpression withWhenClauses(List whenClauses) {
this.setWhenClauses(whenClauses);
return this;
@@ -112,13 +137,15 @@ public CaseExpression withElseExpression(Expression elseExpression) {
}
public CaseExpression addWhenClauses(WhenClause... whenClauses) {
- List collection = Optional.ofNullable(getWhenClauses()).orElseGet(ArrayList::new);
+ List collection =
+ Optional.ofNullable(getWhenClauses()).orElseGet(ArrayList::new);
Collections.addAll(collection, whenClauses);
return this.withWhenClauses(collection);
}
public CaseExpression addWhenClauses(Collection extends WhenClause> whenClauses) {
- List collection = Optional.ofNullable(getWhenClauses()).orElseGet(ArrayList::new);
+ List collection =
+ Optional.ofNullable(getWhenClauses()).orElseGet(ArrayList::new);
collection.addAll(whenClauses);
return this.withWhenClauses(collection);
}
@@ -131,25 +158,25 @@ public E getElseExpression(Class type) {
return type.cast(getElseExpression());
}
- /**
- * @return the usingBrackets
- */
- public boolean isUsingBrackets() {
- return usingBrackets;
- }
-
- /**
- * @param usingBrackets the usingBrackets to set
- */
- public void setUsingBrackets(boolean usingBrackets) {
- this.usingBrackets = usingBrackets;
- }
-
- /**
- * @param usingBrackets the usingBrackets to set
- */
- public CaseExpression withUsingBrackets(boolean usingBrackets) {
- this.usingBrackets=usingBrackets;
- return this;
+ /**
+ * @return the usingBrackets
+ */
+ public boolean isUsingBrackets() {
+ return usingBrackets;
+ }
+
+ /**
+ * @param usingBrackets the usingBrackets to set
+ */
+ public void setUsingBrackets(boolean usingBrackets) {
+ this.usingBrackets = usingBrackets;
+ }
+
+ /**
+ * @param usingBrackets the usingBrackets to set
+ */
+ public CaseExpression withUsingBrackets(boolean usingBrackets) {
+ this.usingBrackets = usingBrackets;
+ return this;
}
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/CastExpression.java b/src/main/java/net/sf/jsqlparser/expression/CastExpression.java
index 519eb4ef6..66af39ed5 100644
--- a/src/main/java/net/sf/jsqlparser/expression/CastExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/CastExpression.java
@@ -9,37 +9,144 @@
*/
package net.sf.jsqlparser.expression;
+import java.util.Locale;
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;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class CastExpression extends ASTNodeAccessImpl implements Expression {
+ private final static Pattern PATTERN =
+ Pattern.compile("(^[a-z0-9_]*){1}", Pattern.CASE_INSENSITIVE);
+ public String keyword;
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 CastExpression withRowConstructor(RowConstructor rowConstructor) {
- setRowConstructor(rowConstructor);
- return this;
+ private ColDataType colDataType = null;
+ private ArrayList columnDefinitions = new ArrayList<>();
+
+ private boolean isImplicitCast = false;
+
+ // BigQuery specific FORMAT clause:
+ // https://cloud.google.com/bigquery/docs/reference/standard-sql/conversion_functions#cast_as_date
+ private String format = null;
+
+ public CastExpression(String keyword, Expression leftExpression, String dataType) {
+ this.keyword = keyword;
+ this.leftExpression = leftExpression;
+ this.colDataType = new ColDataType(dataType);
+ }
+
+ // Implicit Cast
+ public CastExpression(String dataType, String value) {
+ this.keyword = null;
+ this.isImplicitCast = true;
+ this.colDataType = new ColDataType(dataType);
+ this.leftExpression = new StringValue(value);
+ }
+
+ public CastExpression(ColDataType colDataType, String value) {
+ this.keyword = null;
+ this.isImplicitCast = true;
+ this.colDataType = colDataType;
+ this.leftExpression = new StringValue(value);
+ }
+
+ public CastExpression(ColDataType colDataType, Long value) {
+ this.keyword = null;
+ this.isImplicitCast = true;
+ this.colDataType = colDataType;
+ this.leftExpression = new LongValue(value);
+ }
+
+ public CastExpression(ColDataType colDataType, Double value) {
+ this.keyword = null;
+ this.isImplicitCast = true;
+ this.colDataType = colDataType;
+ this.leftExpression = new DoubleValue(value);
+ }
+
+ public CastExpression(Expression leftExpression, String dataType) {
+ this.keyword = null;
+ this.leftExpression = leftExpression;
+ this.colDataType = new ColDataType(dataType);
+ }
+
+
+ public CastExpression(String keyword) {
+ this.keyword = keyword;
+ }
+
+ public CastExpression() {
+ this("CAST");
+ }
+
+ public static boolean isOf(ColDataType colDataType, DataType... types) {
+ return Set.of(types).contains(DataType.from(colDataType.getDataType()));
+ }
+
+ public static boolean isTime(ColDataType colDataType) {
+ return isOf(colDataType, DataType.TIME, DataType.TIME_WITH_TIME_ZONE,
+ DataType.TIME_WITHOUT_TIME_ZONE);
+ }
+
+ public static boolean isTimeStamp(ColDataType colDataType) {
+ return isOf(colDataType, DataType.TIMESTAMP_NS, DataType.TIMESTAMP,
+ DataType.TIMESTAMP_WITHOUT_TIME_ZONE,
+ DataType.DATETIME, DataType.TIMESTAMP_MS, DataType.TIMESTAMP_S,
+ DataType.TIMESTAMPTZ, DataType.TIMESTAMP_WITH_TIME_ZONE);
+ }
+
+ public static boolean isDate(ColDataType colDataType) {
+ return isOf(colDataType, DataType.DATE);
+ }
+
+ public static boolean isBLOB(ColDataType colDataType) {
+ return isOf(colDataType, DataType.BLOB, DataType.BYTEA, DataType.BINARY, DataType.VARBINARY,
+ DataType.BYTES, DataType.VARBYTE);
+ }
+
+ public static boolean isFloat(ColDataType colDataType) {
+ return isOf(colDataType, DataType.REAL, DataType.FLOAT4, DataType.FLOAT, DataType.DOUBLE,
+ DataType.DOUBLE_PRECISION, DataType.FLOAT8);
+ }
+
+ public static boolean isInteger(ColDataType colDataType) {
+ return isOf(colDataType, DataType.TINYINT, DataType.INT1, DataType.SMALLINT, DataType.INT2,
+ DataType.SHORT, DataType.INTEGER, DataType.INT4, DataType.INT, DataType.SIGNED,
+ DataType.BIGINT, DataType.INT8, DataType.LONG, DataType.HUGEINT, DataType.UTINYINT,
+ DataType.USMALLINT, DataType.UINTEGER, DataType.UBIGINT, DataType.UHUGEINT);
+ }
+
+ public static boolean isDecimal(ColDataType colDataType) {
+ return isOf(colDataType, DataType.DECIMAL, DataType.NUMBER, DataType.NUMERIC);
+ }
+
+ public static boolean isText(ColDataType colDataType) {
+ return isOf(colDataType, DataType.VARCHAR, DataType.NVARCHAR, DataType.CHAR, DataType.NCHAR,
+ DataType.BPCHAR, DataType.STRING, DataType.TEXT, DataType.CLOB);
+ }
+
+ public ColDataType getColDataType() {
+ return colDataType;
}
- 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 ArrayList getColumnDefinitions() {
+ return columnDefinitions;
+ }
+
+ public void addColumnDefinition(ColumnDefinition columnDefinition) {
+ this.columnDefinitions.add(columnDefinition);
}
public Expression getLeftExpression() {
@@ -50,32 +157,65 @@ public void setLeftExpression(Expression expression) {
leftExpression = expression;
}
+ public boolean isImplicitCast() {
+ return isImplicitCast;
+ }
+
+ public CastExpression setImplicitCast(boolean implicitCast) {
+ isImplicitCast = implicitCast;
+ return this;
+ }
+
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
+ @Deprecated
public boolean isUseCastKeyword() {
- return useCastKeyword;
+ return keyword != null && !keyword.isEmpty();
}
+ @Deprecated
public void setUseCastKeyword(boolean useCastKeyword) {
- this.useCastKeyword = useCastKeyword;
+ if (useCastKeyword) {
+ if (keyword == null || keyword.isEmpty()) {
+ keyword = "CAST";
+ }
+ } else {
+ keyword = null;
+ }
+ }
+
+ public String getFormat() {
+ return format;
+ }
+
+ public CastExpression setFormat(String format) {
+ this.format = format;
+ return this;
}
@Override
public String toString() {
- if (useCastKeyword) {
- return rowConstructor!=null
- ? "CAST(" + leftExpression + " AS " + rowConstructor.toString() + ")"
- : "CAST(" + leftExpression + " AS " + type.toString() + ")";
+ String formatStr = format != null && !format.isEmpty()
+ ? " FORMAT " + format
+ : "";
+ if (isImplicitCast) {
+ return colDataType + " " + leftExpression;
+ } else if (keyword != null && !keyword.isEmpty()) {
+ return columnDefinitions.size() > 1
+ ? keyword + "(" + leftExpression + " AS ROW("
+ + Select.getStringList(columnDefinitions) + ")" + formatStr + ")"
+ : keyword + "(" + leftExpression + " AS " + colDataType.toString() + formatStr
+ + ")";
} else {
- return leftExpression + "::" + type.toString();
+ return leftExpression + "::" + colDataType.toString();
}
}
public CastExpression withType(ColDataType type) {
- this.setType(type);
+ this.setColDataType(type);
return this;
}
@@ -92,4 +232,66 @@ public CastExpression withLeftExpression(Expression leftExpression) {
public E getLeftExpression(Class type) {
return type.cast(getLeftExpression());
}
+
+ public boolean isOf(CastExpression anotherCast) {
+ return this.colDataType.equals(anotherCast.colDataType);
+ }
+
+ public boolean isOf(DataType... types) {
+ return Set.of(types).contains(DataType.from(colDataType.getDataType()));
+ }
+
+ public boolean isTime() {
+ return isTime(this.colDataType);
+ }
+
+ public boolean isTimeStamp() {
+ return isTimeStamp(this.colDataType);
+ }
+
+ public boolean isDate() {
+ return isDate(this.colDataType);
+ }
+
+ public boolean isBLOB() {
+ return isBLOB(this.colDataType);
+ }
+
+ public boolean isFloat() {
+ return isFloat(this.colDataType);
+ }
+
+ public boolean isInteger() {
+ return isInteger(this.colDataType);
+ }
+
+ public boolean isDecimal() {
+ return isDecimal(this.colDataType);
+ }
+
+ public boolean isText() {
+ return isText(this.colDataType);
+ }
+
+ public enum DataType {
+ ARRAY, BIT, BITSTRING, BLOB, BYTEA, BINARY, VARBINARY, BYTES, BOOLEAN, BOOL, ENUM, INTERVAL, LIST, MAP, STRUCT, TINYINT, INT1, SMALLINT, INT2, SHORT, INTEGER, INT4, INT, SIGNED, BIGINT, INT8, LONG, HUGEINT, UTINYINT, USMALLINT, UINTEGER, UBIGINT, UHUGEINT, DECIMAL, NUMBER, NUMERIC, REAL, FLOAT4, FLOAT, DOUBLE, DOUBLE_PRECISION, FLOAT8, FLOAT64, UUID, VARCHAR, NVARCHAR, CHAR, NCHAR, BPCHAR, STRING, TEXT, CLOB, DATE, TIME, TIME_WITHOUT_TIME_ZONE, TIMETZ, TIME_WITH_TIME_ZONE, TIMESTAMP_NS, TIMESTAMP, TIMESTAMP_WITHOUT_TIME_ZONE, DATETIME, TIMESTAMP_MS, TIMESTAMP_S, TIMESTAMPTZ, TIMESTAMP_WITH_TIME_ZONE, UNKNOWN, VARBYTE, JSON;
+
+ public static DataType from(String typeStr) {
+ Matcher matcher = PATTERN.matcher(
+ typeStr.trim().replaceAll("\\s+", "_").toUpperCase(Locale.ROOT));
+ if (matcher.find()) {
+ try {
+ return Enum.valueOf(DataType.class, matcher.group(0));
+ } catch (Exception ex) {
+ Logger.getLogger(CastExpression.class.getName()).log(Level.FINE,
+ "Type " + typeStr + " unknown", ex);
+ return DataType.UNKNOWN;
+ }
+ } else {
+ Logger.getLogger(CastExpression.class.getName()).log(Level.FINE,
+ "Type " + typeStr + " unknown");
+ return DataType.UNKNOWN;
+ }
+ }
+ }
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/CollateExpression.java b/src/main/java/net/sf/jsqlparser/expression/CollateExpression.java
index 07c2b8616..8a419b241 100644
--- a/src/main/java/net/sf/jsqlparser/expression/CollateExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/CollateExpression.java
@@ -26,8 +26,8 @@ public CollateExpression(Expression leftExpression, String collate) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public Expression getLeftExpression() {
diff --git a/src/main/java/net/sf/jsqlparser/expression/ConnectByPriorOperator.java b/src/main/java/net/sf/jsqlparser/expression/ConnectByPriorOperator.java
new file mode 100644
index 000000000..45c2fde6a
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/ConnectByPriorOperator.java
@@ -0,0 +1,74 @@
+/*-
+ * #%L
+ * JSQLParser library
+ * %%
+ * Copyright (C) 2004 - 2021 JSQLParser
+ * %%
+ * 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.expression;
+
+import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
+import net.sf.jsqlparser.schema.Column;
+
+import java.util.Objects;
+
+/**
+ *
+ * @author are
+ */
+public class ConnectByPriorOperator extends ASTNodeAccessImpl implements Expression {
+ private final Expression expression;
+
+ @Deprecated
+ public ConnectByPriorOperator(Column column) {
+ this.expression = Objects.requireNonNull(column,
+ "The COLUMN of the ConnectByPrior Operator must not be null");
+ }
+
+ public ConnectByPriorOperator(Expression column) {
+ this.expression = Objects.requireNonNull(column,
+ "The COLUMN of the ConnectByPrior Operator must not be null");
+ }
+
+ @Deprecated
+ public Expression getColumn() {
+ return getExpression();
+ }
+
+ public Expression getExpression() {
+ return expression;
+ }
+
+ @Override
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
+ }
+
+ public StringBuilder appendTo(StringBuilder builder) {
+ builder.append("PRIOR ").append(expression);
+ return builder;
+ }
+
+ @Override
+ public String toString() {
+ return appendTo(new StringBuilder()).toString();
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/ConnectByRootOperator.java b/src/main/java/net/sf/jsqlparser/expression/ConnectByRootOperator.java
index 817023422..776dc031e 100644
--- a/src/main/java/net/sf/jsqlparser/expression/ConnectByRootOperator.java
+++ b/src/main/java/net/sf/jsqlparser/expression/ConnectByRootOperator.java
@@ -26,34 +26,46 @@
package net.sf.jsqlparser.expression;
import java.util.Objects;
+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.schema.Column;
/**
- *
* @author are
*/
public class ConnectByRootOperator extends ASTNodeAccessImpl implements Expression {
- private final Column column;
+ private final Expression expression;
+ @Deprecated
public ConnectByRootOperator(Column column) {
- this.column = Objects.requireNonNull(column, "The COLUMN of the ConnectByRoot Operator must not be null");
+ this.expression = Objects.requireNonNull(column,
+ "The COLUMN of the ConnectByRoot Operator must not be null");
+ }
+
+ public ConnectByRootOperator(Expression column) {
+ this.expression = Objects.requireNonNull(column,
+ "The EXPRESSION of the ConnectByRoot Operator must not be null");
}
- public Column getColumn() {
- return column;
+ @Deprecated
+ public Expression getColumn() {
+ return expression;
+ }
+
+ public Expression getExpression() {
+ return expression;
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
-
+
public StringBuilder appendTo(StringBuilder builder) {
- builder.append("CONNECT_BY_ROOT ").append(column);
+ builder.append("CONNECT_BY_ROOT ").append(expression);
return builder;
}
-
+
@Override
public String toString() {
return appendTo(new StringBuilder()).toString();
diff --git a/src/main/java/net/sf/jsqlparser/expression/DateTimeLiteralExpression.java b/src/main/java/net/sf/jsqlparser/expression/DateTimeLiteralExpression.java
index 173c564f7..c2873bfb0 100644
--- a/src/main/java/net/sf/jsqlparser/expression/DateTimeLiteralExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/DateTimeLiteralExpression.java
@@ -9,6 +9,7 @@
*/
package net.sf.jsqlparser.expression;
+import java.util.Locale;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
public class DateTimeLiteralExpression extends ASTNodeAccessImpl implements Expression {
@@ -33,13 +34,13 @@ public void setType(DateTime type) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
public String toString() {
- return type.name() + " " + value;
+ return type != null ? type.name() + " " + value : value;
}
public DateTimeLiteralExpression withValue(String value) {
@@ -53,6 +54,10 @@ public DateTimeLiteralExpression withType(DateTime type) {
}
public enum DateTime {
- DATE, TIME, TIMESTAMP;
+ DATE, DATETIME, TIME, TIMESTAMP, TIMESTAMPTZ;
+
+ public static DateTime from(String dateTimeStr) {
+ return Enum.valueOf(DateTime.class, dateTimeStr.toUpperCase(Locale.ROOT));
+ }
}
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/DateUnitExpression.java b/src/main/java/net/sf/jsqlparser/expression/DateUnitExpression.java
new file mode 100644
index 000000000..922c0c419
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/DateUnitExpression.java
@@ -0,0 +1,51 @@
+/*-
+ * #%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 java.util.Locale;
+import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
+
+import java.util.Objects;
+
+public class DateUnitExpression extends ASTNodeAccessImpl implements Expression {
+
+ private final DateUnit type;
+
+ public DateUnitExpression(DateUnit type) {
+ this.type = Objects.requireNonNull(type);
+ }
+
+ public DateUnitExpression(String DateUnitStr) {
+ this.type = Objects.requireNonNull(DateUnit.from(DateUnitStr));
+ }
+
+ public DateUnit getType() {
+ return type;
+ }
+
+
+ @Override
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
+ }
+
+ @Override
+ public String toString() {
+ return type.toString();
+ }
+
+ public enum DateUnit {
+ CENTURY, DECADE, YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND, MILLISECOND, MICROSECOND, NANOSECOND;
+
+ public static DateUnit from(String UnitStr) {
+ return Enum.valueOf(DateUnit.class, UnitStr.toUpperCase(Locale.ROOT));
+ }
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/DateValue.java b/src/main/java/net/sf/jsqlparser/expression/DateValue.java
index 8c28a5fdd..d03a73c66 100644
--- a/src/main/java/net/sf/jsqlparser/expression/DateValue.java
+++ b/src/main/java/net/sf/jsqlparser/expression/DateValue.java
@@ -38,8 +38,8 @@ public DateValue(String value) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public Date getValue() {
diff --git a/src/main/java/net/sf/jsqlparser/expression/DoubleValue.java b/src/main/java/net/sf/jsqlparser/expression/DoubleValue.java
index 43e072dcf..8d25aa61a 100644
--- a/src/main/java/net/sf/jsqlparser/expression/DoubleValue.java
+++ b/src/main/java/net/sf/jsqlparser/expression/DoubleValue.java
@@ -16,7 +16,7 @@
*/
public class DoubleValue extends ASTNodeAccessImpl implements Expression {
- private double value;
+ private Double value;
private String stringValue;
public DoubleValue() {
@@ -24,6 +24,9 @@ public DoubleValue() {
}
public DoubleValue(final String value) {
+ if (value == null || value.length() == 0) {
+ throw new IllegalArgumentException("value can neither be null nor empty.");
+ }
String val = value;
if (val.charAt(0) == '+') {
val = val.substring(1);
@@ -32,17 +35,23 @@ public DoubleValue(final String value) {
this.stringValue = val;
}
+ public DoubleValue(final double value) {
+ this.value = value;
+ this.stringValue = String.valueOf(value);
+ }
+
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public double getValue() {
return value;
}
- public void setValue(double d) {
+ public void setValue(Double d) {
value = d;
+ stringValue = String.valueOf(value);
}
@Override
@@ -50,7 +59,7 @@ public String toString() {
return stringValue;
}
- public DoubleValue withValue(double value) {
+ public DoubleValue withValue(Double value) {
this.setValue(value);
return this;
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/Expression.java b/src/main/java/net/sf/jsqlparser/expression/Expression.java
index daeb2da83..1f733d564 100644
--- a/src/main/java/net/sf/jsqlparser/expression/Expression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/Expression.java
@@ -14,6 +14,10 @@
public interface Expression extends ASTNodeAccess, Model {
- void accept(ExpressionVisitor expressionVisitor);
+ T accept(ExpressionVisitor expressionVisitor, S context);
+
+ default void accept(ExpressionVisitor expressionVisitor) {
+ this.accept(expressionVisitor, null);
+ }
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java
index 15ca4da56..2eb909a98 100644
--- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java
+++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java
@@ -9,177 +9,817 @@
*/
package net.sf.jsqlparser.expression;
-import net.sf.jsqlparser.expression.operators.arithmetic.*;
+import java.util.List;
+import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseRightShift;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor;
+import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
+import net.sf.jsqlparser.expression.operators.arithmetic.Division;
+import net.sf.jsqlparser.expression.operators.arithmetic.IntegerDivision;
+import net.sf.jsqlparser.expression.operators.arithmetic.Modulo;
+import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication;
+import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.conditional.XorExpression;
-import net.sf.jsqlparser.expression.operators.relational.*;
+import net.sf.jsqlparser.expression.operators.relational.Between;
+import net.sf.jsqlparser.expression.operators.relational.ContainedBy;
+import net.sf.jsqlparser.expression.operators.relational.Contains;
+import net.sf.jsqlparser.expression.operators.relational.CosineSimilarity;
+import net.sf.jsqlparser.expression.operators.relational.DoubleAnd;
+import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
+import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression;
+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;
+import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
+import net.sf.jsqlparser.expression.operators.relational.InExpression;
+import net.sf.jsqlparser.expression.operators.relational.IncludesExpression;
+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.IsUnknownExpression;
+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;
+import net.sf.jsqlparser.expression.operators.relational.Plus;
+import net.sf.jsqlparser.expression.operators.relational.PriorTo;
+import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator;
+import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression;
+import net.sf.jsqlparser.expression.operators.relational.TSQLLeftJoin;
+import net.sf.jsqlparser.expression.operators.relational.TSQLRightJoin;
import net.sf.jsqlparser.schema.Column;
+import net.sf.jsqlparser.statement.piped.FromQuery;
import net.sf.jsqlparser.statement.select.AllColumns;
import net.sf.jsqlparser.statement.select.AllTableColumns;
-import net.sf.jsqlparser.statement.select.SubSelect;
+import net.sf.jsqlparser.statement.select.FunctionAllColumns;
+import net.sf.jsqlparser.statement.select.GroupByElement;
+import net.sf.jsqlparser.statement.select.Limit;
+import net.sf.jsqlparser.statement.select.OrderByElement;
+import net.sf.jsqlparser.statement.select.ParenthesedSelect;
+import net.sf.jsqlparser.statement.select.Select;
+import net.sf.jsqlparser.statement.update.UpdateSet;
+
+public interface ExpressionVisitor {
+
+ default T visitExpressions(ExpressionList extends Expression> expressions, S context) {
+ if (expressions != null) {
+ expressions.forEach(expression -> expression.accept(this, context));
+ }
+ return null;
+ };
+
+ default T visitExpression(Expression expression, S context) {
+ if (expression != null) {
+ expression.accept(this, context);
+ }
+ return null;
+ }
+
+ default T visitOrderBy(List orderByElements, S context) {
+ if (orderByElements != null) {
+ for (OrderByElement orderByElement : orderByElements) {
+ orderByElement.getExpression().accept(this, context);
+ }
+ }
+ return null;
+ }
+
+ default T visitLimit(Limit limit, S context) {
+ if (limit != null && !limit.isLimitNull() && !limit.isLimitAll()) {
+ if (limit.getOffset() != null) {
+ limit.getOffset().accept(this, context);
+ }
+ if (limit.getRowCount() != null) {
+ limit.getRowCount().accept(this, context);
+ }
+ if (limit.getByExpressions() != null) {
+ limit.getByExpressions().accept(this, context);
+ }
+ }
+ return null;
+ }
+
+ default T visitPreferringClause(PreferringClause preferringClause, S context) {
+ if (preferringClause != null) {
+ if (preferringClause.getPreferring() != null) {
+ preferringClause.getPreferring().accept(this, context);
+ }
+ if (preferringClause.getPartitionBy() != null) {
+ for (Expression expression : preferringClause.getPartitionBy()) {
+ expression.accept(this, context);
+ }
+ }
+ }
+ return null;
+ }
+
+ default T visitUpdateSets(List updateSets, S context) {
+ if (updateSets != null) {
+ for (UpdateSet updateSet : updateSets) {
+ for (Column column : updateSet.getColumns()) {
+ column.accept(this, context);
+ }
+ for (Expression value : updateSet.getValues()) {
+ value.accept(this, context);
+ }
+ }
+ }
+ return null;
+ }
+
+ default T visit(GroupByElement groupBy, S context) {
+ if (groupBy != null) {
+ for (Expression expression : groupBy.getGroupByExpressionList()) {
+ expression.accept(this, context);
+ }
+ if (!groupBy.getGroupingSets().isEmpty()) {
+ for (ExpressionList> expressionList : groupBy.getGroupingSets()) {
+ expressionList.accept(this, context);
+ }
+ }
+ }
+ return null;
+ }
+
+ T visit(BitwiseRightShift bitwiseRightShift, S context);
+
+ default void visit(BitwiseRightShift bitwiseRightShift) {
+ this.visit(bitwiseRightShift, null);
+ }
+
+ T visit(BitwiseLeftShift bitwiseLeftShift, S context);
+
+ default void visit(BitwiseLeftShift bitwiseLeftShift) {
+ this.visit(bitwiseLeftShift, null);
+ }
+
+ T visit(NullValue nullValue, S context);
+
+ default void visit(NullValue nullValue) {
+ this.visit(nullValue, null);
+ }
+
+ T visit(Function function, S context);
+
+ default void visit(Function function) {
+ this.visit(function, null);
+ }
+
+ T visit(SignedExpression signedExpression, S context);
+
+ default void visit(SignedExpression signedExpression) {
+ this.visit(signedExpression, null);
+ }
+
+ T visit(JdbcParameter jdbcParameter, S context);
-public interface ExpressionVisitor {
+ default void visit(JdbcParameter jdbcParameter) {
+ this.visit(jdbcParameter, null);
+ }
- void visit(BitwiseRightShift aThis);
+ T visit(JdbcNamedParameter jdbcNamedParameter, S context);
- void visit(BitwiseLeftShift aThis);
+ default void visit(JdbcNamedParameter jdbcNamedParameter) {
+ this.visit(jdbcNamedParameter, null);
+ }
- void visit(NullValue nullValue);
+ T visit(DoubleValue doubleValue, S context);
- void visit(Function function);
+ default void visit(DoubleValue doubleValue) {
+ this.visit(doubleValue, null);
+ }
- void visit(SignedExpression signedExpression);
+ T visit(LongValue longValue, S context);
- void visit(JdbcParameter jdbcParameter);
+ default void visit(LongValue longValue) {
+ this.visit(longValue, null);
+ }
- void visit(JdbcNamedParameter jdbcNamedParameter);
+ T visit(HexValue hexValue, S context);
- void visit(DoubleValue doubleValue);
+ default void visit(HexValue hexValue) {
+ this.visit(hexValue, null);
+ }
- void visit(LongValue longValue);
+ T visit(DateValue dateValue, S context);
- void visit(HexValue hexValue);
+ default void visit(DateValue dateValue) {
+ this.visit(dateValue, null);
+ }
- void visit(DateValue dateValue);
+ T visit(TimeValue timeValue, S context);
- void visit(TimeValue timeValue);
+ default void visit(TimeValue timeValue) {
+ this.visit(timeValue, null);
+ }
- void visit(TimestampValue timestampValue);
+ T visit(TimestampValue timestampValue, S context);
- void visit(Parenthesis parenthesis);
+ default void visit(TimestampValue timestampValue) {
+ this.visit(timestampValue, null);
+ }
- void visit(StringValue stringValue);
+ T visit(StringValue stringValue, S context);
- void visit(Addition addition);
+ default void visit(StringValue stringValue) {
+ this.visit(stringValue, null);
+ }
- void visit(Division division);
+ T visit(BooleanValue booleanValue, S context);
- void visit(IntegerDivision division);
+ default void visit(BooleanValue booleanValue) {
+ this.visit(booleanValue, null);
+ }
- void visit(Multiplication multiplication);
+ T visit(Addition addition, S context);
- void visit(Subtraction subtraction);
+ default void visit(Addition addition) {
+ this.visit(addition, null);
+ }
- void visit(AndExpression andExpression);
+ T visit(Division division, S context);
- void visit(OrExpression orExpression);
+ default void visit(Division division) {
+ this.visit(division, null);
+ }
- void visit(XorExpression orExpression);
+ T visit(IntegerDivision integerDivision, S context);
- void visit(Between between);
+ default void visit(IntegerDivision integerDivision) {
+ this.visit(integerDivision, null);
+ }
- void visit(EqualsTo equalsTo);
+ T visit(Multiplication multiplication, S context);
- void visit(GreaterThan greaterThan);
+ default void visit(Multiplication multiplication) {
+ this.visit(multiplication, null);
+ }
- void visit(GreaterThanEquals greaterThanEquals);
+ T visit(Subtraction subtraction, S context);
- void visit(InExpression inExpression);
+ default void visit(Subtraction subtraction) {
+ this.visit(subtraction, null);
+ }
- void visit(FullTextSearch fullTextSearch);
+ T visit(AndExpression andExpression, S context);
- void visit(IsNullExpression isNullExpression);
+ default void visit(AndExpression andExpression) {
+ this.visit(andExpression, null);
+ }
- void visit(IsBooleanExpression isBooleanExpression);
+ T visit(OrExpression orExpression, S context);
- void visit(LikeExpression likeExpression);
+ default void visit(OrExpression orExpression) {
+ this.visit(orExpression, null);
+ }
- void visit(MinorThan minorThan);
+ T visit(XorExpression xorExpression, S context);
- void visit(MinorThanEquals minorThanEquals);
+ default void visit(XorExpression xorExpression) {
+ this.visit(xorExpression, null);
+ }
- void visit(NotEqualsTo notEqualsTo);
+ T visit(Between between, S context);
- void visit(Column tableColumn);
+ default void visit(Between between) {
+ this.visit(between, null);
+ }
- void visit(SubSelect subSelect);
+ T visit(OverlapsCondition overlapsCondition, S context);
- void visit(CaseExpression caseExpression);
+ default void visit(OverlapsCondition overlapsCondition) {
+ this.visit(overlapsCondition, null);
+ }
- void visit(WhenClause whenClause);
+ T visit(EqualsTo equalsTo, S context);
- void visit(ExistsExpression existsExpression);
+ default void visit(EqualsTo equalsTo) {
+ this.visit(equalsTo, null);
+ }
- void visit(AnyComparisonExpression anyComparisonExpression);
+ T visit(GreaterThan greaterThan, S context);
- void visit(Concat concat);
+ default void visit(GreaterThan greaterThan) {
+ this.visit(greaterThan, null);
+ }
- void visit(Matches matches);
+ T visit(GreaterThanEquals greaterThanEquals, S context);
- void visit(BitwiseAnd bitwiseAnd);
+ default void visit(GreaterThanEquals greaterThanEquals) {
+ this.visit(greaterThanEquals, null);
+ }
- void visit(BitwiseOr bitwiseOr);
+ T visit(InExpression inExpression, S context);
- void visit(BitwiseXor bitwiseXor);
+ default void visit(InExpression inExpression) {
+ this.visit(inExpression, null);
+ }
- void visit(CastExpression cast);
+ T visit(IncludesExpression includesExpression, S context);
- void visit(Modulo modulo);
+ default void visit(IncludesExpression includesExpression) {
+ this.visit(includesExpression, null);
+ }
- void visit(AnalyticExpression aexpr);
+ T visit(ExcludesExpression excludesExpression, S context);
- void visit(ExtractExpression eexpr);
+ default void visit(ExcludesExpression excludesExpression) {
+ this.visit(excludesExpression, null);
+ }
- void visit(IntervalExpression iexpr);
+ T visit(FullTextSearch fullTextSearch, S context);
- void visit(OracleHierarchicalExpression oexpr);
+ default void visit(FullTextSearch fullTextSearch) {
+ this.visit(fullTextSearch, null);
+ }
- void visit(RegExpMatchOperator rexpr);
+ T visit(IsNullExpression isNullExpression, S context);
- void visit(JsonExpression jsonExpr);
+ default void visit(IsNullExpression isNullExpression) {
+ this.visit(isNullExpression, null);
+ }
- void visit(JsonOperator jsonExpr);
+ T visit(IsBooleanExpression isBooleanExpression, S context);
- void visit(RegExpMySQLOperator regExpMySQLOperator);
+ default void visit(IsBooleanExpression isBooleanExpression) {
+ this.visit(isBooleanExpression, null);
+ }
- void visit(UserVariable var);
+ T visit(IsUnknownExpression isUnknownExpression, S context);
- void visit(NumericBind bind);
+ default void visit(IsUnknownExpression isUnknownExpression) {
+ this.visit(isUnknownExpression, null);
+ }
- void visit(KeepExpression aexpr);
+ T visit(LikeExpression likeExpression, S context);
- void visit(MySQLGroupConcat groupConcat);
+ default void visit(LikeExpression likeExpression) {
+ this.visit(likeExpression, null);
+ }
- void visit(ValueListExpression valueList);
+ T visit(MinorThan minorThan, S context);
- void visit(RowConstructor rowConstructor);
+ default void visit(MinorThan minorThan) {
+ this.visit(minorThan, null);
+ }
- void visit(RowGetExpression rowGetExpression);
+ T visit(MinorThanEquals minorThanEquals, S context);
- void visit(OracleHint hint);
+ default void visit(MinorThanEquals minorThanEquals) {
+ this.visit(minorThanEquals, null);
+ }
- void visit(TimeKeyExpression timeKeyExpression);
+ T visit(NotEqualsTo notEqualsTo, S context);
- void visit(DateTimeLiteralExpression literal);
+ default void visit(NotEqualsTo notEqualsTo) {
+ this.visit(notEqualsTo, null);
+ }
- void visit(NotExpression aThis);
+ T visit(DoubleAnd doubleAnd, S context);
- void visit(NextValExpression aThis);
+ default void visit(DoubleAnd doubleAnd) {
+ this.visit(doubleAnd, null);
+ }
- void visit(CollateExpression aThis);
+ T visit(Contains contains, S context);
- void visit(SimilarToExpression aThis);
+ default void visit(Contains contains) {
+ this.visit(contains, null);
+ }
- void visit(ArrayExpression aThis);
+ T visit(ContainedBy containedBy, S context);
- void visit(ArrayConstructor aThis);
+ default void visit(ContainedBy containedBy) {
+ this.visit(containedBy, null);
+ }
- void visit(VariableAssignment aThis);
+ T visit(ParenthesedSelect select, S context);
- void visit(XMLSerializeExpr aThis);
+ T visit(Column column, S context);
- void visit(TimezoneExpression aThis);
+ default void visit(Column column) {
+ this.visit(column, null);
+ }
- void visit(JsonAggregateFunction aThis);
+ T visit(CaseExpression caseExpression, S context);
- void visit(JsonFunction aThis);
+ default void visit(CaseExpression caseExpression) {
+ this.visit(caseExpression, null);
+ }
- void visit(ConnectByRootOperator aThis);
+ T visit(WhenClause whenClause, S context);
- void visit(OracleNamedFunctionParameter aThis);
+ default void visit(WhenClause whenClause) {
+ this.visit(whenClause, null);
+ }
- void visit(AllColumns allColumns);
+ T visit(ExistsExpression existsExpression, S context);
- void visit(AllTableColumns allTableColumns);
+ default void visit(ExistsExpression existsExpression) {
+ this.visit(existsExpression, null);
+ }
+
+ T visit(MemberOfExpression memberOfExpression, S context);
+
+ default void visit(MemberOfExpression memberOfExpression) {
+ this.visit(memberOfExpression, null);
+ }
+
+ T visit(AnyComparisonExpression anyComparisonExpression, S context);
+
+ default void visit(AnyComparisonExpression anyComparisonExpression) {
+ this.visit(anyComparisonExpression, null);
+ }
+
+ T visit(Concat concat, S context);
+
+ default void visit(Concat concat) {
+ this.visit(concat, null);
+ }
+
+ T visit(Matches matches, S context);
+
+ default void visit(Matches matches) {
+ this.visit(matches, null);
+ }
+
+ T visit(BitwiseAnd bitwiseAnd, S context);
+
+ default void visit(BitwiseAnd bitwiseAnd) {
+ this.visit(bitwiseAnd, null);
+ }
+
+ T visit(BitwiseOr bitwiseOr, S context);
+
+ default void visit(BitwiseOr bitwiseOr) {
+ this.visit(bitwiseOr, null);
+ }
+
+ T visit(BitwiseXor bitwiseXor, S context);
+
+ default void visit(BitwiseXor bitwiseXor) {
+ this.visit(bitwiseXor, null);
+ }
+
+ T visit(CastExpression castExpression, S context);
+
+ default void visit(CastExpression castExpression) {
+ this.visit(castExpression, null);
+ }
+
+ T visit(Modulo modulo, S context);
+
+ default void visit(Modulo modulo) {
+ this.visit(modulo, null);
+ }
+
+ T visit(AnalyticExpression analyticExpression, S context);
+
+ default void visit(AnalyticExpression analyticExpression) {
+ this.visit(analyticExpression, null);
+ }
+
+ T visit(ExtractExpression extractExpression, S context);
+
+ default void visit(ExtractExpression extractExpression) {
+ this.visit(extractExpression, null);
+ }
+
+ T visit(IntervalExpression intervalExpression, S context);
+
+ default void visit(IntervalExpression intervalExpression) {
+ this.visit(intervalExpression, null);
+ }
+
+ T visit(OracleHierarchicalExpression hierarchicalExpression, S context);
+
+ default void visit(OracleHierarchicalExpression hierarchicalExpression) {
+ this.visit(hierarchicalExpression, null);
+ }
+
+ T visit(RegExpMatchOperator regExpMatchOperator, S context);
+
+ default void visit(RegExpMatchOperator regExpMatchOperator) {
+ this.visit(regExpMatchOperator, null);
+ }
+
+ T visit(JsonExpression jsonExpression, S context);
+
+ default void visit(JsonExpression jsonExpression) {
+ this.visit(jsonExpression, null);
+ }
+
+ T visit(JsonOperator jsonOperator, S context);
+
+ default void visit(JsonOperator jsonOperator) {
+ this.visit(jsonOperator, null);
+ }
+
+ T visit(UserVariable userVariable, S context);
+
+ default void visit(UserVariable userVariable) {
+ this.visit(userVariable, null);
+ }
+
+ T visit(NumericBind numericBind, S context);
+
+ default void visit(NumericBind numericBind) {
+ this.visit(numericBind, null);
+ }
+
+ T visit(KeepExpression keepExpression, S context);
+
+ default void visit(KeepExpression keepExpression) {
+ this.visit(keepExpression, null);
+ }
+
+ T visit(MySQLGroupConcat groupConcat, S context);
+
+ default void visit(MySQLGroupConcat groupConcat) {
+ this.visit(groupConcat, null);
+ }
+
+ T visit(ExpressionList extends Expression> expressionList, S context);
+
+ default void visit(ExpressionList extends Expression> expressionList) {
+ this.visit(expressionList, null);
+ }
+
+ T visit(RowConstructor extends Expression> rowConstructor, S context);
+
+ default void visit(RowConstructor extends Expression> rowConstructor) {
+ this.visit(rowConstructor, null);
+ }
+
+ T visit(RowGetExpression rowGetExpression, S context);
+
+ default void visit(RowGetExpression rowGetExpression) {
+ this.visit(rowGetExpression, null);
+ }
+
+ T visit(OracleHint hint, S context);
+
+ default void visit(OracleHint hint) {
+ this.visit(hint, null);
+ }
+
+ T visit(TimeKeyExpression timeKeyExpression, S context);
+
+ default void visit(TimeKeyExpression timeKeyExpression) {
+ this.visit(timeKeyExpression, null);
+ }
+
+ T visit(DateTimeLiteralExpression dateTimeLiteralExpression, S context);
+
+ default void visit(DateTimeLiteralExpression dateTimeLiteralExpression) {
+ this.visit(dateTimeLiteralExpression, null);
+ }
+
+ T visit(NotExpression notExpression, S context);
+
+ default void visit(NotExpression notExpression) {
+ this.visit(notExpression, null);
+ }
+
+ T visit(NextValExpression nextValExpression, S context);
+
+ default void visit(NextValExpression nextValExpression) {
+ this.visit(nextValExpression, null);
+ }
+
+ T visit(CollateExpression collateExpression, S context);
+
+ default void visit(CollateExpression collateExpression) {
+ this.visit(collateExpression, null);
+ }
+
+ T visit(SimilarToExpression similarToExpression, S context);
+
+ default void visit(SimilarToExpression similarToExpression) {
+ this.visit(similarToExpression, null);
+ }
+
+ T visit(ArrayExpression arrayExpression, S context);
+
+ default void visit(ArrayExpression arrayExpression) {
+ this.visit(arrayExpression, null);
+ }
+
+ T visit(ArrayConstructor arrayConstructor, S context);
+
+ default void visit(ArrayConstructor arrayConstructor) {
+ this.visit(arrayConstructor, null);
+ }
+
+ default T visit(MapExpression mapExpression, S context) {
+ return null;
+ }
+
+ default void visit(MapExpression mapExpression) {
+ this.visit(mapExpression, null);
+ }
+
+ T visit(VariableAssignment variableAssignment, S context);
+
+ default void visit(VariableAssignment variableAssignment) {
+ this.visit(variableAssignment, null);
+ }
+
+ T visit(XMLSerializeExpr xmlSerializeExpr, S context);
+
+ default void visit(XMLSerializeExpr xmlSerializeExpr) {
+ this.visit(xmlSerializeExpr, null);
+ }
+
+ T visit(TimezoneExpression timezoneExpression, S context);
+
+ default void visit(TimezoneExpression timezoneExpression) {
+ this.visit(timezoneExpression, null);
+ }
+
+ T visit(JsonAggregateFunction jsonAggregateFunction, S context);
+
+ default void visit(JsonAggregateFunction jsonAggregateFunction) {
+ this.visit(jsonAggregateFunction, null);
+ }
+
+ T visit(JsonFunction jsonFunction, S context);
+
+ default void visit(JsonFunction jsonFunction) {
+ this.visit(jsonFunction, null);
+ }
+
+ default T visit(JsonTableFunction jsonTableFunction, S context) {
+ return visit((Function) jsonTableFunction, context);
+ }
+
+ default void visit(JsonTableFunction jsonTableFunction) {
+ this.visit(jsonTableFunction, null);
+ }
+
+ default T visit(XmlTableFunction xmlTableFunction, S context) {
+ return visit((Function) xmlTableFunction, context);
+ }
+
+ default void visit(XmlTableFunction xmlTableFunction) {
+ this.visit(xmlTableFunction, null);
+ }
+
+ T visit(ConnectByRootOperator connectByRootOperator, S context);
+
+ default void visit(ConnectByRootOperator connectByRootOperator) {
+ this.visit(connectByRootOperator, null);
+ }
+
+ T visit(ConnectByPriorOperator connectByPriorOperator, S context);
+
+ default void visit(ConnectByPriorOperator connectByPriorOperator) {
+ this.visit(connectByPriorOperator, null);
+ }
+
+ T visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, S context);
+
+ default void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter) {
+ this.visit(oracleNamedFunctionParameter, null);
+ }
+
+ T visit(AllColumns allColumns, S context);
+
+ T visit(FunctionAllColumns functionColumns, S context);
+
+ default void visit(AllColumns allColumns) {
+ this.visit(allColumns, null);
+ }
+
+ T visit(AllTableColumns allTableColumns, S context);
+
+ default void visit(AllTableColumns allTableColumns) {
+ this.visit(allTableColumns, null);
+ }
+
+ T visit(AllValue allValue, S context);
+
+ default void visit(AllValue allValue) {
+ this.visit(allValue, null);
+ }
+
+ T visit(IsDistinctExpression isDistinctExpression, S context);
+
+ default void visit(IsDistinctExpression isDistinctExpression) {
+ this.visit(isDistinctExpression, null);
+ }
+
+ T visit(GeometryDistance geometryDistance, S context);
+
+ default void visit(GeometryDistance geometryDistance) {
+ this.visit(geometryDistance, null);
+ }
+
+ T visit(Select select, S context);
+
+ T visit(TranscodingFunction transcodingFunction, S context);
+
+ default void visit(TranscodingFunction transcodingFunction) {
+ this.visit(transcodingFunction, null);
+ }
+
+ T visit(TrimFunction trimFunction, S context);
+
+ default void visit(TrimFunction trimFunction) {
+ this.visit(trimFunction, null);
+ }
+
+ T visit(RangeExpression rangeExpression, S context);
+
+ default void visit(RangeExpression rangeExpression) {
+ this.visit(rangeExpression, null);
+ }
+
+ T visit(TernaryExpression ternaryExpression, S context);
+
+ default void visit(TernaryExpression ternaryExpression) {
+ this.visit(ternaryExpression, null);
+ }
+
+ T visit(TSQLLeftJoin tsqlLeftJoin, S context);
+
+ default void visit(TSQLLeftJoin tsqlLeftJoin) {
+ this.visit(tsqlLeftJoin, null);
+ }
+
+ T visit(TSQLRightJoin tsqlRightJoin, S context);
+
+ default void visit(TSQLRightJoin tsqlRightJoin) {
+ this.visit(tsqlRightJoin, null);
+ }
+
+ T visit(StructType structType, S context);
+
+ default void visit(StructType structType) {
+ this.visit(structType, null);
+ }
+
+ T visit(LambdaExpression lambdaExpression, S context);
+
+ default void visit(LambdaExpression lambdaExpression) {
+ this.visit(lambdaExpression, null);
+ }
+
+ T visit(HighExpression highExpression, S context);
+
+ default void visit(HighExpression highExpression) {
+ this.visit(highExpression, null);
+ }
+
+ T visit(LowExpression lowExpression, S context);
+
+ default void visit(LowExpression lowExpression) {
+ this.visit(lowExpression, null);
+ }
+
+ T visit(Plus plus, S context);
+
+ default void visit(Plus plus) {
+ this.visit(plus, null);
+ }
+
+ T visit(PriorTo priorTo, S context);
+
+ default void visit(PriorTo priorTo) {
+ this.visit(priorTo, null);
+ }
+
+ T visit(Inverse inverse, S context);
+
+ default void visit(Inverse inverse) {
+ this.visit(inverse, null);
+ }
+
+ T visit(CosineSimilarity cosineSimilarity, S context);
+
+ T visit(FromQuery fromQuery, S context);
+
+ T visit(DateUnitExpression dateUnitExpression, S context);
+
+ T visit(KeyExpression keyExpression, S context);
+
+ default void visit(KeyExpression keyExpression) {
+ this.visit(keyExpression, null);
+ }
+
+ T visit(PostgresNamedFunctionParameter postgresNamedFunctionParameter, S context);
+
+ default void visit(PostgresNamedFunctionParameter postgresNamedFunctionParameter) {
+ this.visit(postgresNamedFunctionParameter, null);
+ }
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java
index cfa5555a7..274d4e00a 100644
--- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java
+++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java
@@ -9,621 +9,902 @@
*/
package net.sf.jsqlparser.expression;
-import net.sf.jsqlparser.expression.operators.arithmetic.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Optional;
+import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseRightShift;
+import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor;
+import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
+import net.sf.jsqlparser.expression.operators.arithmetic.Division;
+import net.sf.jsqlparser.expression.operators.arithmetic.IntegerDivision;
+import net.sf.jsqlparser.expression.operators.arithmetic.Modulo;
+import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication;
+import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.conditional.XorExpression;
-import net.sf.jsqlparser.expression.operators.relational.*;
+import net.sf.jsqlparser.expression.operators.relational.Between;
+import net.sf.jsqlparser.expression.operators.relational.ContainedBy;
+import net.sf.jsqlparser.expression.operators.relational.Contains;
+import net.sf.jsqlparser.expression.operators.relational.CosineSimilarity;
+import net.sf.jsqlparser.expression.operators.relational.DoubleAnd;
+import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
+import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression;
+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;
+import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
+import net.sf.jsqlparser.expression.operators.relational.InExpression;
+import net.sf.jsqlparser.expression.operators.relational.IncludesExpression;
+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.IsUnknownExpression;
+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;
+import net.sf.jsqlparser.expression.operators.relational.Plus;
+import net.sf.jsqlparser.expression.operators.relational.PriorTo;
+import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator;
+import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression;
+import net.sf.jsqlparser.expression.operators.relational.TSQLLeftJoin;
+import net.sf.jsqlparser.expression.operators.relational.TSQLRightJoin;
import net.sf.jsqlparser.schema.Column;
-import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
+import net.sf.jsqlparser.statement.piped.FromQuery;
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.FunctionAllColumns;
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.SelectExpressionItem;
+import net.sf.jsqlparser.statement.select.Select;
+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.SubSelect;
import net.sf.jsqlparser.statement.select.UnPivot;
import net.sf.jsqlparser.statement.select.WithItem;
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.UncommentedEmptyMethodBody"})
-public class ExpressionVisitorAdapter implements ExpressionVisitor, ItemsListVisitor, PivotVisitor, SelectItemVisitor {
+public class ExpressionVisitorAdapter
+ implements ExpressionVisitor, PivotVisitor, SelectItemVisitor {
- private SelectVisitor selectVisitor;
+ private SelectVisitor selectVisitor;
- public SelectVisitor getSelectVisitor() {
+ public ExpressionVisitorAdapter(SelectVisitor selectVisitor) {
+ this.selectVisitor = selectVisitor;
+ }
+
+ public ExpressionVisitorAdapter() {
+ this.selectVisitor = null;
+ }
+
+ public SelectVisitor getSelectVisitor() {
return selectVisitor;
}
- public void setSelectVisitor(SelectVisitor selectVisitor) {
+ public ExpressionVisitorAdapter setSelectVisitor(SelectVisitor selectVisitor) {
this.selectVisitor = selectVisitor;
+ return this;
}
@Override
- public void visit(NullValue value) {
-
+ public T visit(NullValue nullValue, S context) {
+ return applyExpression(nullValue, context);
}
@Override
- public void visit(Function function) {
+ public T visit(Function function, S context) {
+ ArrayList subExpressions = new ArrayList<>();
if (function.getParameters() != null) {
- function.getParameters().accept(this);
+ subExpressions.addAll(function.getParameters());
+ }
+ if (function.getChainedParameters() != null) {
+ subExpressions.addAll(function.getChainedParameters());
}
if (function.getKeep() != null) {
- function.getKeep().accept(this);
+ subExpressions.add(function.getKeep());
}
if (function.getOrderByElements() != null) {
for (OrderByElement orderByElement : function.getOrderByElements()) {
- orderByElement.getExpression().accept(this);
+ subExpressions.add(orderByElement.getExpression());
}
}
+ return visitExpressions(function, context, subExpressions);
}
@Override
- public void visit(SignedExpression expr) {
- expr.getExpression().accept(this);
+ public T visit(SignedExpression signedExpression, S context) {
+ return signedExpression.getExpression().accept(this, context);
}
@Override
- public void visit(JdbcParameter parameter) {
-
+ public T visit(JdbcParameter jdbcParameter, S context) {
+ return applyExpression(jdbcParameter, context);
}
@Override
- public void visit(JdbcNamedParameter parameter) {
-
+ public T visit(JdbcNamedParameter jdbcNamedParameter, S context) {
+ return applyExpression(jdbcNamedParameter, context);
}
@Override
- public void visit(DoubleValue value) {
-
+ public T visit(DoubleValue doubleValue, S context) {
+ return applyExpression(doubleValue, context);
}
@Override
- public void visit(LongValue value) {
+ public T visit(LongValue longValue, S context) {
+ return applyExpression(longValue, context);
+ }
+ @Override
+ public T visit(DateValue dateValue, S context) {
+ return applyExpression(dateValue, context);
}
@Override
- public void visit(DateValue value) {
+ public T visit(TimeValue timeValue, S context) {
+ return applyExpression(timeValue, context);
+ }
+ @Override
+ public T visit(TimestampValue timestampValue, S context) {
+ return applyExpression(timestampValue, context);
}
@Override
- public void visit(TimeValue value) {
+ public T visit(StringValue stringValue, S context) {
+ return applyExpression(stringValue, context);
+ }
+ @Override
+ public T visit(BooleanValue booleanValue, S context) {
+ return applyExpression(booleanValue, context);
}
@Override
- public void visit(TimestampValue value) {
+ public T visit(Addition addition, S context) {
+ return visitBinaryExpression(addition, context);
+ }
+ @Override
+ public T visit(Division division, S context) {
+ return visitBinaryExpression(division, context);
}
@Override
- public void visit(Parenthesis parenthesis) {
- parenthesis.getExpression().accept(this);
+ public T visit(IntegerDivision integerDivision, S context) {
+ return visitBinaryExpression(integerDivision, context);
}
@Override
- public void visit(StringValue value) {
+ public T visit(Multiplication multiplication, S context) {
+ return visitBinaryExpression(multiplication, context);
+ }
+ @Override
+ public T visit(Subtraction subtraction, S context) {
+ return visitBinaryExpression(subtraction, context);
}
@Override
- public void visit(Addition expr) {
- visitBinaryExpression(expr);
+ public T visit(AndExpression andExpression, S context) {
+ return visitBinaryExpression(andExpression, context);
}
@Override
- public void visit(Division expr) {
- visitBinaryExpression(expr);
+ public T visit(OrExpression orExpression, S context) {
+ return visitBinaryExpression(orExpression, context);
}
@Override
- public void visit(IntegerDivision expr) {
- visitBinaryExpression(expr);
+ public T visit(XorExpression xorExpression, S context) {
+ return visitBinaryExpression(xorExpression, context);
}
@Override
- public void visit(Multiplication expr) {
- visitBinaryExpression(expr);
+ public T visit(Between between, S context) {
+ return visitExpressions(between, context, between.getLeftExpression(),
+ between.getBetweenExpressionStart(), between.getBetweenExpressionEnd());
}
+ public T visit(OverlapsCondition overlapsCondition, S context) {
+ return visitExpressions(overlapsCondition, context, overlapsCondition.getLeft(),
+ overlapsCondition.getRight());
+ }
+
+
@Override
- public void visit(Subtraction expr) {
- visitBinaryExpression(expr);
+ public T visit(EqualsTo equalsTo, S context) {
+ return visitBinaryExpression(equalsTo, context);
}
@Override
- public void visit(AndExpression expr) {
- visitBinaryExpression(expr);
+ public T visit(GreaterThan greaterThan, S context) {
+ return visitBinaryExpression(greaterThan, context);
}
@Override
- public void visit(OrExpression expr) {
- visitBinaryExpression(expr);
+ public T visit(GreaterThanEquals greaterThanEquals, S context) {
+ return visitBinaryExpression(greaterThanEquals, context);
}
@Override
- public void visit(XorExpression expr) {
- visitBinaryExpression(expr);
+ public T visit(InExpression inExpression, S context) {
+ return visitExpressions(inExpression, context, inExpression.getLeftExpression(),
+ inExpression.getRightExpression());
}
@Override
- public void visit(Between expr) {
- expr.getLeftExpression().accept(this);
- expr.getBetweenExpressionStart().accept(this);
- expr.getBetweenExpressionEnd().accept(this);
+ public T visit(IncludesExpression includesExpression, S context) {
+ return visitExpressions(includesExpression, context, includesExpression.getLeftExpression(),
+ includesExpression.getRightExpression());
}
@Override
- public void visit(EqualsTo expr) {
- visitBinaryExpression(expr);
+ public T visit(ExcludesExpression excludesExpression, S context) {
+ return visitExpressions(excludesExpression, context, excludesExpression.getLeftExpression(),
+ excludesExpression.getRightExpression());
}
@Override
- public void visit(GreaterThan expr) {
- visitBinaryExpression(expr);
+ public T visit(IsNullExpression isNullExpression, S context) {
+ return isNullExpression.getLeftExpression().accept(this, context);
}
@Override
- public void visit(GreaterThanEquals expr) {
- visitBinaryExpression(expr);
+ public T visit(FullTextSearch fullTextSearch, S context) {
+ ArrayList subExpressions = new ArrayList<>(fullTextSearch.getMatchColumns());
+ subExpressions.add(fullTextSearch.getAgainstValue());
+ return visitExpressions(fullTextSearch, context, subExpressions);
}
@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);
- } else {
- expr.getMultiExpressionList().accept(this);
- }
+ public T visit(IsBooleanExpression isBooleanExpression, S context) {
+ return isBooleanExpression.getLeftExpression().accept(this, context);
}
@Override
- public void visit(IsNullExpression expr) {
- expr.getLeftExpression().accept(this);
+ public T visit(IsUnknownExpression isUnknownExpression, S context) {
+ return isUnknownExpression.getLeftExpression().accept(this, context);
}
@Override
- public void visit(FullTextSearch expr) {
- for (Column col : expr.getMatchColumns()) {
- col.accept(this);
- }
+ public T visit(LikeExpression likeExpression, S context) {
+ return visitBinaryExpression(likeExpression, context);
}
@Override
- public void visit(IsBooleanExpression expr) {
- expr.getLeftExpression().accept(this);
+ public T visit(MinorThan minorThan, S context) {
+ return visitBinaryExpression(minorThan, context);
}
@Override
- public void visit(LikeExpression expr) {
- visitBinaryExpression(expr);
+ public T visit(MinorThanEquals minorThanEquals, S context) {
+ return visitBinaryExpression(minorThanEquals, context);
}
@Override
- public void visit(MinorThan expr) {
- visitBinaryExpression(expr);
+ public T visit(NotEqualsTo notEqualsTo, S context) {
+ return visitBinaryExpression(notEqualsTo, context);
}
@Override
- public void visit(MinorThanEquals expr) {
- visitBinaryExpression(expr);
+ public T visit(DoubleAnd doubleAnd, S context) {
+ return visitBinaryExpression(doubleAnd, context);
}
@Override
- public void visit(NotEqualsTo expr) {
- visitBinaryExpression(expr);
+ public T visit(Contains contains, S context) {
+ return visitBinaryExpression(contains, context);
}
@Override
- public void visit(Column column) {
+ public T visit(ContainedBy containedBy, S context) {
+ return visitBinaryExpression(containedBy, context);
+ }
+ @Override
+ public T visit(Column column, S context) {
+ return applyExpression(column, context);
}
@Override
- public void visit(SubSelect subSelect) {
- if (selectVisitor != null) {
- if (subSelect.getWithItemsList() != null) {
- for (WithItem item : subSelect.getWithItemsList()) {
- item.accept(selectVisitor);
- }
- }
- subSelect.getSelectBody().accept(selectVisitor);
- }
- if (subSelect.getPivot() != null) {
- subSelect.getPivot().accept(this);
+ public T visit(ParenthesedSelect select, S context) {
+ visit((Select) select, context);
+ if (select.getPivot() != null) {
+ select.getPivot().accept(this, context);
}
+ return null;
}
@Override
- public void visit(CaseExpression expr) {
- if (expr.getSwitchExpression() != null) {
- expr.getSwitchExpression().accept(this);
- }
- for (Expression x : expr.getWhenClauses()) {
- x.accept(this);
+ public T visit(CaseExpression caseExpression, S context) {
+ ArrayList