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/.github/workflows/gradle.yml b/.github/workflows/gradle.yml
deleted file mode 100644
index 67ccc3166..000000000
--- a/.github/workflows/gradle.yml
+++ /dev/null
@@ -1,35 +0,0 @@
-# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
-# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
-
-name: Gradle CI
-
-on:
- push:
- branches: [ "master" ]
- pull_request:
- branches: [ "master" ]
-
-permissions:
- contents: read
-
-jobs:
- check:
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
- - name: Set up JDK 11
- uses: actions/setup-java@v3
- with:
- java-version: '11'
- distribution: 'temurin'
- - name: Build with Gradle
- uses: gradle/gradle-build-action@v2.6.0
- with:
- arguments: check
- env:
- ossrhUsername: ${{ secrets.OSSRHPASSWORD }}
- ossrhPassword: ${{ secrets.OSSRHUSERNAME }}
diff --git a/.github/workflows/gradle_publish.yml b/.github/workflows/gradle_publish.yml
deleted file mode 100644
index 4e8cbddea..000000000
--- a/.github/workflows/gradle_publish.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-# This workflow uses actions that are not certified by GitHub.
-# They are provided by a third-party and are governed by
-# separate terms of service, privacy policy, and support
-# documentation.
-# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
-# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
-
-name: Gradle publish Snapshot
-
-on:
- workflow_dispatch:
-
-permissions:
- contents: read
-
-jobs:
- publish:
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
- - name: Set up JDK 11
- uses: actions/setup-java@v3
- with:
- java-version: '11'
- distribution: 'temurin'
- - name: Build with Gradle
- uses: gradle/gradle-build-action@v2.6.0
- with:
- arguments: publish
- # arguments: build check publish
- env:
- ossrhUsername: ${{ secrets.OSSRHPASSWORD }}
- ossrhPassword: ${{ secrets.OSSRHUSERNAME }}
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
deleted file mode 100644
index 3c265b631..000000000
--- a/.github/workflows/maven.yml
+++ /dev/null
@@ -1,36 +0,0 @@
-# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
-# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
-
-name: Maven CI
-
-on:
- push:
- branches: [ master ]
- pull_request:
- branches: [ master ]
-
-jobs:
- package:
-
- runs-on: ubuntu-latest
- strategy:
- matrix:
- java: [11]
- name: Java ${{ matrix.java }} building ...
-
- steps:
- - uses: actions/checkout@v3
- - name: Set up Java ${{ matrix.java }}
- uses: actions/setup-java@v3
- with:
- java-version: ${{ matrix.java }}
- distribution: 'temurin'
- cache: maven
- server-id: sonatype-nexus-snapshots
- server-username: MAVEN_USERNAME
- server-password: MAVEN_PASSWORD
- - name: Build with Maven
- run: mvn -B package --file pom.xml -DdisableXmlReport=true -Djacoco.skip=true -Dpmd.skip=true
- env:
- MAVEN_USERNAME: ${{ secrets.OSSRHUSERNAME }}
- MAVEN_PASSWORD: ${{ secrets.OSSRHPASSWORD }}
diff --git a/.github/workflows/maven_deploy.yml b/.github/workflows/maven_deploy.yml
deleted file mode 100644
index 740e80cb1..000000000
--- a/.github/workflows/maven_deploy.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-name: Maven deploy snapshot
-
-on:
- push:
- branches: [ "master" ]
-
-jobs:
- deploy:
-
- runs-on: ubuntu-latest
- strategy:
- matrix:
- java: [11]
- name: Java ${{ matrix.java }} building ...
-
- steps:
- - uses: actions/checkout@v3
- - name: Set up Java ${{ matrix.java }}
- uses: actions/setup-java@v3
- with:
- java-version: ${{ matrix.java }}
- distribution: 'temurin'
- cache: maven
- server-id: sonatype-nexus-snapshots
- server-username: MAVEN_USERNAME
- server-password: MAVEN_PASSWORD
- - name: Build with Maven
- run: mvn -B deploy --file pom.xml -DdisableXmlReport=true -Djacoco.skip=true -Dpmd.skip=true
- env:
- MAVEN_USERNAME: ${{ secrets.OSSRHUSERNAME }}
- MAVEN_PASSWORD: ${{ secrets.OSSRHPASSWORD }}
diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml
deleted file mode 100644
index ad8bde188..000000000
--- a/.github/workflows/sphinx.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-name: Sphinx Pages
-on:
- push:
- branches: [ "master" ]
-
-permissions: write-all
-jobs:
- docs:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/setup-python@v4
- - name: Install XSLT Processor
- run: sudo apt-get install xsltproc sphinx-common
- - name: Install dependencies
- run: pip install furo myst_parser sphinx-prompt sphinx_substitution_extensions sphinx_issues sphinx_inline_tabs pygments
- - name: Checkout project sources
- uses: actions/checkout@v2
- with:
- ref: master
- fetch-depth: 0
- - name: Setup Gradle
- uses: gradle/gradle-build-action@v2.4.2
- - name: Run build with Gradle Wrapper
- run: FLOATING_TOC=false gradle --no-build-cache clean xmldoc sphinx
- - name: Deploy
- uses: actions/configure-pages@v2
- - name: Upload artifact
- uses: actions/upload-pages-artifact@v1
- with:
- # Upload entire repository
- path: 'build/sphinx'
- - name: Deploy to GitHub Pages
- id: deployment
- uses: actions/deploy-pages@v1
diff --git a/.gitignore b/.gitignore
index 20db77d7c..955e7bf2d 100755
--- a/.gitignore
+++ b/.gitignore
@@ -1,16 +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/javadoc_stable.rst
/src/site/sphinx/syntax_stable.rst
-/src/site/sphinx/javadoc_snapshot.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
@@ -31,3 +32,6 @@
/nbproject/
/.gradle
+
+# Mac
+.DS_Store
diff --git a/README.md b/README.md
index 2e147efc3..42122c891 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,22 @@
-# [JSqlParser 4.9 Website](https://jsqlparser.github.io/JSqlParser)
+# [JSqlParser 5.3 Website](https://jsqlparser.github.io/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) [](https://www.javadoc.io/doc/com.github.jsqlparser/jsqlparser)
+[](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?utm_source=github.com&utm_medium=referral&utm_content=JSQLParser/JSqlParser&utm_campaign=Badge_Grade)
+[](https://central.sonatype.com/artifact/com.github.jsqlparser/jsqlparser) [](https://www.javadoc.io/doc/com.github.jsqlparser/jsqlparser)
[](https://gitter.im/JSQLParser/JSqlParser?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
+A huge thank you to our sponsor, [Starlake.ai](https://starlake.ai/) who simplifies data ingestion, transformation, and orchestration, enabling faster delivery of high-quality data. Starlake has been instrumental in providing Piped SQL and numerous test cases for BigQuery, Redshift, DataBricks, and DuckDB. Show your support for ongoing development by visiting Starlake.ai and giving us a star!
+
## Summary
-Please visit the [WebSite](https://jsqlparser.github.io/JSqlParser). **JSqlParser** is a RDBMS agnostic SQL statement parser. It translates SQL statements into a traversable hierarchy of Java classes (see [Samples](https://jsqlparser.github.io/JSqlParser/usage.html#parse-a-sql-statements)):
+Please visit our [WebSite](https://jsqlparser.github.io/JSqlParser) for detailed information. **JSqlParser** is a RDBMS agnostic SQL statement parser. It translates SQL statements into a traversable hierarchy of Java classes (see [Samples](https://jsqlparser.github.io/JSqlParser/usage.html#parse-a-sql-statements)):
```sql
SELECT 1 FROM dual WHERE a = b
-```
-```text
+/* produces the following AST
+
SQL Text
└─Statements: statement.select.PlainSelect
├─selectItems: statement.select.SelectItem
@@ -22,6 +25,7 @@ SQL Text
└─where: expression.operators.relational.EqualsTo
├─Column: a
└─Column: b
+*/
```
```java
@@ -43,26 +47,68 @@ Column a = (Column) equalsTo.getLeftExpression();
Column b = (Column) equalsTo.getRightExpression();
Assertions.assertEquals("a", a.getColumnName());
Assertions.assertEquals("b", b.getColumnName());
-}
```
+## Support for `Piped SQL`
+
+Work is progressing for parsing `Piped SQL`, a much saner and more logical way to write queries in its semantic order.
+```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;
+```
+
+For details, please see https://storage.googleapis.com/gweb-research2023-media/pubtools/1004848.pdf, https://cloud.google.com/bigquery/docs/reference/standard-sql/pipe-syntax and https://duckdb.org/docs/sql/query_syntax/from.html#from-first-syntax
+
+## Java Version
+
+JSQLParser-4.9 was the last JDK8 compatible version. JSQLParser-5.0 and later depend on JDK11 and introduce API breaking changes to the AST Visitors. Please see the Migration Guide for the details.
+
+Building JSQLParser-5.1 and newer with Gradle will depend on a JDK17 toolchain due to the used plugins.
-JSQLParser-4.9 is the last JDK8 compatible version and any future development will depend on JDK11.
+JSQLParser-5.4 Snapshot and later use JavaCC-8 Snapshots for generating the parser.
+
+## Performance
+
+Unfortunately the released JSQLParser-5.2 shows a performance deterioration caused by commit [30cf5d7](https://github.com/JSQLParser/JSqlParser/commit/30cf5d7b930ae0a076f49deb5cc841d39e62b3dc) related to `FunctionAllColumns()`.
+This has been resolved in JSQLParser 5.3-SNAPSHOT and JMH benchmarks have been added to avoid such regressions in the future. Further all `LOOKAHEAD` have been revised one by one, and we have gained back a very good performance of the Parser.
+
+As per March-2026, the productions `Condition()`, `RegularCondition()` and `AndExpression()` have been refactored successfully. Furthermore, we have overhauled Token definition and handling of Reserved Keywords. This resulted in a massive performance boost and seem to have solved most of the performance issues.
+
+```text
+Benchmark (version) Mode Cnt Score Error Units
+JSQLParserBenchmark.parseSQLStatements latest avgt 15 7.602 ± 0.135 ms/op <-- March/26
+JSQLParserBenchmark.parseSQLStatements 5.3 avgt 15 84.687 ± 3.321 ms/op
+JSQLParserBenchmark.parseSQLStatements 5.1 avgt 15 86.592 ± 5.781 ms/op
+```
## [Supported Grammar and Syntax](https://jsqlparser.github.io/JSqlParser/syntax.html)
**JSqlParser** aims to support the SQL standard as well as all major RDBMS. Any missing syntax or features can be added on demand.
-| RDBMS | Statements |
-|-----------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
-| Oracle
MS SQL Server and Sybase
Postgres
MySQL and MariaDB
DB2
H2 and HSQLDB and Derby
SQLite | `SELECT`
`INSERT`, `UPDATE`, `UPSERT`, `MERGE`
`DELETE`, `TRUNCATE TABLE`
`CREATE ...`, `ALTER ....`, `DROP ...`
`WITH ...` |
-| Salesforce SOQL | `INCLUDES`, `EXCLUDES` |
+| RDBMS | Statements |
+|-----------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|
+| BigQuery
Snowflake
DuckDB
Redshift
Oracle
MS SQL Server and Sybase
Postgres
MySQL and MariaDB
DB2
H2 and HSQLDB and Derby
SQLite | `SELECT`
`INSERT`, `UPDATE`, `UPSERT`, `MERGE`
`DELETE`, `TRUNCATE TABLE`
`CREATE ...`, `ALTER ....`, `DROP ...`
`WITH ...` |
+| PostgreSQL Row Level Security | `CREATE POLICY`
`ALTER TABLE ... ENABLE/DISABLE/FORCE/NO FORCE ROW LEVEL SECURITY` |
+| Salesforce SOQL | `INCLUDES`, `EXCLUDES` |
+| Piped SQL (also known as FROM SQL) | |
**JSqlParser** can also be used to create SQL Statements from Java Code with a fluent API (see [Samples](https://jsqlparser.github.io/JSqlParser/usage.html#build-a-sql-statements)).
+## Sister Projects
+
+If you like JSqlParser then please check out its related projects:
+
+* [JSQLFormatter](https://manticore-projects.com/JSQLFormatter/index.html) for pretty printing and formatting SQL Text
+
+* [JSQLTranspiler](https://manticore-projects.com/JSQLTranspiler/index.html) for dialect specific rewriting, SQL Column resolution and Lineage, provided by [Starlake.ai](https://starlake.ai/)
+
## 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.
-Alternatively the dual-licensed [JOOQ](https://www.jooq.org/doc/latest/manual/sql-building/sql-parser/) provides a hand-written Parser supporting a lot of RDBMS, translation between dialects, SQL transformation, can be used as a JDBC proxy for translation and transformation purposes.
+Alternatively the dual-licensed [JOOQ](https://www.jooq.org/doc/latest/manual/sql-building/sql-parser/) provides a handwritten Parser supporting a lot of RDBMS, translation between dialects, SQL transformation, can be used as a JDBC proxy for translation and transformation purposes.
## [Documentation](https://jsqlparser.github.io/JSqlParser)
1. [Samples](https://jsqlparser.github.io/JSqlParser/usage.html#parse-a-sql-statements)
diff --git a/build.gradle b/build.gradle
index f5e939cb9..a690cef6b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,4 +1,13 @@
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'
@@ -6,12 +15,13 @@ plugins {
id 'signing'
id "org.javacc.javacc" version "latest.release"
- //id 'jacoco'
+ id 'jacoco'
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 "latest.release"
@@ -19,7 +29,8 @@ plugins {
id "se.bjurr.gitchangelog.git-changelog-gradle-plugin" version "latest.release"
id "me.champeau.jmh" version "latest.release"
- id "com.nwalsh.gradle.saxon.saxon-gradle" version "0.9.6"
+ id "com.nwalsh.gradle.saxon.saxon-gradle" version "latest.release"
+ id 'biz.aQute.bnd.builder' version "latest.release"
}
def getVersion = { boolean considerSnapshot ->
@@ -27,58 +38,106 @@ def getVersion = { boolean considerSnapshot ->
Integer minor = 0
Integer patch = null
Integer build = null
- def commit = null
- def snapshot = ""
- new ByteArrayOutputStream().withStream { os ->
- exec {
- args = [
- "--no-pager"
- , "describe"
- , "--tags"
- , "--always"
- , "--dirty=-SNAPSHOT"
- ]
- executable "git"
- standardOutput = os
- }
- def versionStr = os.toString().trim()
- def pattern = /(?\d*)\.(?\d*)(\.(?\d*))?(-(?\d*)-(?[a-zA-Z\d]*))?/
- def matcher = versionStr =~ pattern
- if (matcher.find()) {
- major = matcher.group('major') as Integer
- minor = matcher.group('minor') as Integer
- patch = matcher.group('patch') as Integer
- build = matcher.group('build') as Integer
- commit = matcher.group('commit')
- }
+ 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"
- }
+ if (considerSnapshot && (versionStr.endsWith('SNAPSHOT') || build != null)) {
+ minor++
+ if (patch != null) patch = 0
+ snapshot = "-SNAPSHOT"
}
- return patch!=null
+
+ return patch != null
? "${major}.${minor}.${patch}${snapshot}"
- : "${major}.${minor}${snapshot}"
+ : "${major}.${minor}${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'
description = 'JSQLParser library'
-archivesBaseName = "JSQLParser"
+
+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 {
gradlePluginPortal()
- mavenLocal()
mavenCentral()
- // Sonatype OSSRH
+ // JavaCC 8 Snapshots
maven {
- url = uri('https://s01.oss.sonatype.org/content/repositories/snapshots/')
+ url = uri('https://central.sonatype.com/repository/maven-snapshots/')
}
+
+ maven { url "https://dev.saxonica.com/maven" }
}
configurations {
@@ -95,27 +154,121 @@ dependencies {
testImplementation 'com.h2database:h2:+'
// for JaCoCo Reports
- testImplementation 'org.junit.jupiter:junit-jupiter-api:+'
- testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:+'
- testImplementation 'org.junit.jupiter:junit-jupiter-params:+'
+ testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.11.4'
+ testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.4'
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.4'
+ testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.4'
// https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter
- testImplementation 'org.mockito:mockito-junit-jupiter:+'
+ testImplementation 'org.mockito:mockito-junit-jupiter:5.18.0'
// 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:+'
+ xmlDoclet ('com.manticore-projects.tools:xml-doclet:+'){ changing = true }
// enforce latest version of JavaCC
- testImplementation 'net.java.dev.javacc:javacc:+'
- javacc 'net.java.dev.javacc:javacc:+'
+ testImplementation('org.javacc:core:8.1.0-SNAPSHOT') { changing = true }
+ testImplementation('org.javacc.generator:java:8.1.0-SNAPSHOT') { changing = true }
+
+ jmh 'org.openjdk.jmh:jmh-core:1.37'
+ jmh 'org.openjdk.jmh:jmh-generator-annprocess:1.37'
+ javacc('org.javacc:core:8.1.0-SNAPSHOT') { changing = true }
+ javacc('org.javacc.generator:java:8.1.0-SNAPSHOT') { changing = true }
+}
+configurations.configureEach {
+ resolutionStrategy.eachDependency { DependencyResolveDetails details ->
+ if (details.requested.group in ['org.javacc:core', 'org.javacc.generator']) {
+ // Check for updates every build
+ resolutionStrategy.cacheChangingModulesFor 30, 'seconds'
+ }
+ }
}
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'
+ ]
+}
+
+// Post-process the generated CCJSqlParserTokenManager.java to split large static
+// array initializers into separate methods, preventing the method from
+// exceeding the JVM's 64KB bytecode limit (which breaks ASM-based tools like sbt-assembly).
+tasks.register('splitTokenManagerStaticInit') {
+ dependsOn(compileJavacc)
+
+ def tokenManagerFile = layout.buildDirectory.file(
+ "generated/javacc/net/sf/jsqlparser/parser/CCJSqlParserTokenManager.java"
+ )
+
+ inputs.file(tokenManagerFile)
+ outputs.file(tokenManagerFile)
+
+ doLast {
+ def file = tokenManagerFile.get().asFile
+ if (!file.exists()) {
+ throw new GradleException("CCJSqlParserTokenManager.java not found at ${file}")
+ }
+ def content = file.text
+
+ // Pattern matches static final array field declarations with inline initialization.
+ // We extract large ones and move their initialization into separate methods.
+ def fieldsToExtract = [
+ // [regex-safe field name, array type for method return]
+ ['stringLiterals', 'int[]'],
+ ['jjstrLiteralImages', 'String[]'],
+ ['jjmatchKinds', 'int[]'],
+ ['jjnewLexState', 'int[]'],
+ ]
+
+ fieldsToExtract.each { entry ->
+ def fieldName = entry[0]
+ def arrayType = entry[1]
+
+ // Match: = { ... };
+ // The field declaration may use 'public' or 'private' and 'static final'
+ def pattern = ~"(?s)((?:public|private)\\s+static\\s+final\\s+${java.util.regex.Pattern.quote(arrayType)}\\s+${fieldName}\\s*=\\s*)\\{(.*?)\\};"
+ def matcher = pattern.matcher(content)
+ if (matcher.find()) {
+ def prefix = matcher.group(1)
+ def body = matcher.group(2)
+ def methodName = "_init_${fieldName}"
+ def replacement = "${prefix}${methodName}();\n" +
+ " private static ${arrayType} ${methodName}() { return new ${arrayType} {${body}}; }"
+ content = matcher.replaceFirst(java.util.regex.Matcher.quoteReplacement(replacement))
+ logger.lifecycle("splitTokenManagerStaticInit: extracted ${fieldName} initialization into ${methodName}()")
+ }
+ }
+
+ // Handle int[][] arrays separately (jjcompositeState, jjnextStateSet)
+ def arrayArrayFields = ['jjcompositeState', 'jjnextStateSet']
+ arrayArrayFields.each { fieldName ->
+ def pattern = ~"(?s)(private\\s+static\\s+final\\s+int\\[\\]\\[\\]\\s+${fieldName}\\s*=\\s*)\\{(.*?)\\};"
+ def matcher = pattern.matcher(content)
+ if (matcher.find()) {
+ def prefix = matcher.group(1)
+ def body = matcher.group(2)
+ def methodName = "_init_${fieldName}"
+ def replacement = "${prefix}${methodName}();\n" +
+ " private static int[][] ${methodName}() { return new int[][] {${body}}; }"
+ content = matcher.replaceFirst(java.util.regex.Matcher.quoteReplacement(replacement))
+ logger.lifecycle("splitTokenManagerStaticInit: extracted ${fieldName} initialization into ${methodName}()")
+ }
+ }
+
+ file.text = content
+ }
+}
+
+tasks.withType(JavaCompile).configureEach {
+ dependsOn('splitTokenManagerStaticInit')
}
java {
@@ -124,16 +277,13 @@ java {
sourceCompatibility = '11'
targetCompatibility = '11'
+
// needed for XML-Doclet to work (since Doclet changed again with Java 13)
toolchain {
- languageVersion.set(JavaLanguageVersion.of(11))
+ languageVersion.set(JavaLanguageVersion.of(17))
}
}
-compileJava {
- options.release = 11
-}
-
javadoc {
include("build/generated/javacc/net/sf/jsqlparser/parser/*.java" )
if(JavaVersion.current().isJava9Compatible()) {
@@ -145,171 +295,178 @@ javadoc {
jar {
manifest {
attributes (
- "Automatic-Module-Name": "net.sf.jsqlparser"
+ "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"
)
- def rstFile = reporting.file(
- version.endsWith("-SNAPSHOT")
- ? "xmlDoclet/javadoc_snapshot.rst"
- : "xmlDoclet/javadoc_stable.rst"
- )
-
source = sourceSets.main.allJava
- // beware: Gradle deletes this folder automatically and there is no switch-off
+ // 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.github.markusbernhardt.xmldoclet.XmlDoclet"
+ options.doclet = "com.manticore.tools.xmldoclet.XmlDoclet"
title = "API $version"
- options.addBooleanOption("rst", true)
- options.addBooleanOption("withFloatingToc", Boolean.parseBoolean(System.getenv().getOrDefault("FLOATING_TOC", "true")))
+
options.addStringOption("basePackage", "net.sf.jsqlparser")
options.addStringOption("filename", outFile.getName())
- dependsOn(compileJava)
doLast {
copy {
- from rstFile
- into "${projectDir}/src/site/sphinx/"
+ from outFile
+ into layout.projectDirectory.dir("src/site/sphinx/").asFile
}
}
}
test {
- environment = [ 'EXPORT_TEST_TO_FILE': 'True' ]
+ environment = [ 'EXPORT_TEST_TO_FILE': 'False' ]
useJUnitPlatform()
// set heap size for the test JVM(s)
- minHeapSize = "128m"
- maxHeapSize = "1G"
+ minHeapSize = "1G"
+ maxHeapSize = "4G"
+
+ // set JVM stack size
+ jvmArgs = ['-Xss2m', '--add-opens=java.base/java.lang=ALL-UNNAMED']
+
+ jacoco {
+ excludes = ['net/sf/jsqlparser/parser/CCJSqlParserTokenManager']
+ }
}
coveralls {
jacocoReportPath 'build/reports/jacoco/test/jacocoTestReport.xml'
}
-//
-//jacocoTestReport {
-// afterEvaluate {
-// classDirectories.setFrom(files(classDirectories.files.collect {
-// fileTree(dir: it, exclude: ' net/sf/jsqlparser/parser/CCJSqlParserTokenManager')
-// }))
-// }
-// dependsOn test // tests are required to run before generating the report
-// reports {
-// xml.required = false
-// csv.required = false
-// html.outputLocation = layout.buildDirectory.dir('reports/jacoco')
-// }
-//}
-//jacocoTestCoverageVerification {
-// violationRules {
-// rule {
-// //element = 'CLASS'
-// limit {
-// //@todo: temporarily reduced it 80%, we need to bring that back to 84% accepting the Keywords PR
-// minimum = 0.80
-// }
-// excludes = [
-// 'net.sf.jsqlparser.util.validation.*',
-// 'net.sf.jsqlparser.**.*Adapter',
-// 'net.sf.jsqlparser.parser.JJTCCJSqlParserState',
-// 'net.sf.jsqlparser.parser.TokenMgrError',
-// 'net.sf.jsqlparser.parser.StreamProvider',
-// 'net.sf.jsqlparser.parser.CCJSqlParserTokenManager',
-// 'net.sf.jsqlparser.parser.ParseException',
-// 'net.sf.jsqlparser.parser.SimpleNode',
-// 'net.sf.jsqlparser.parser.SimpleCharStream',
-// 'net.sf.jsqlparser.parser.StringProvider',
-// 'net.sf.jsqlparser.parser.CCJSqlParserTokenManager'
-// ]
-// }
+
+jacocoTestReport {
+ dependsOn test // tests are required to run before generating the report
+ reports {
+ xml.required = false
+ csv.required = false
+ html.outputLocation = layout.buildDirectory.dir('reports/jacoco')
+ }
+}
+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 {
+ //@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'
+// 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 = 7000
-// }
-// excludes = [
+// value = 'MISSEDRATIO'
+// maximum = 0.3
+// }
+// excludes = [
// 'net.sf.jsqlparser.util.validation.*',
// 'net.sf.jsqlparser.**.*Adapter',
-// 'net.sf.jsqlparser.parser.JJTCCJSqlParserState',
-// 'net.sf.jsqlparser.parser.TokenMgrError',
-// 'net.sf.jsqlparser.parser.StreamProvider',
-// 'net.sf.jsqlparser.parser.CCJSqlParserTokenManager',
-// 'net.sf.jsqlparser.parser.ParseException',
-// 'net.sf.jsqlparser.parser.SimpleNode',
-// 'net.sf.jsqlparser.parser.SimpleCharStream',
-// 'net.sf.jsqlparser.parser.StringProvider',
-// 'net.sf.jsqlparser.parser.CCJSqlParserTokenManager'
+// '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.JJTCCJSqlParserState',
-//// 'net.sf.jsqlparser.parser.TokenMgrError',
-//// 'net.sf.jsqlparser.parser.StreamProvider',
-//// 'net.sf.jsqlparser.parser.CCJSqlParserTokenManager',
-//// 'net.sf.jsqlparser.parser.ParseException',
-//// 'net.sf.jsqlparser.parser.SimpleNode',
-//// 'net.sf.jsqlparser.parser.SimpleCharStream',
-//// 'net.sf.jsqlparser.parser.StringProvider',
-//// ]
-//// }
-// }
-//}
+ }
+}
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("config/spotbugs/spotBugsExcludeFilter.xml")
+}
- // do not run over the test, although we should do that eventually
- spotbugsTest.enabled = false
+// do not run over the test, although we should do that eventually
+tasks.named('spotbugsTest').configure {
+ enabled = false
}
pmd {
+ // 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
+ rulesMinimumPriority = 2
ruleSetFiles = files("config/pmd/ruleset.xml")
+}
- pmdMain {
- excludes = [
- "build/generated/*"
- ]
- }
+tasks.named('pmdMain').configure {
+ excludes = [
+ "build/generated/*"
+ , "**/net/sf/jsqlparser/parser/SimpleCharStream.java"
+ ]
}
checkstyle {
@@ -317,6 +474,17 @@ checkstyle {
configFile = rootProject.file('config/checkstyle/checkstyle.xml')
}
+tasks.withType(Checkstyle).configureEach {
+ reports {
+ xml.required = false
+ html.required = true
+ }
+ excludes = [
+ "**/module-info.java"
+ , "net/sf/jsqlparser/parser/SimpleCharStream.java"
+ ]
+}
+
spotless {
// optional: limit format enforcement to just the files changed by this feature branch
ratchetFrom 'origin/master'
@@ -327,82 +495,81 @@ spotless {
// define the steps to apply to those files
trimTrailingWhitespace()
- indentWithSpaces(4) // or spaces. Takes an integer argument if you don't like 4
+ leadingTabsToSpaces(4)
endWithNewline()
}
java {
- indentWithSpaces(4)
+ leadingTabsToSpaces(4)
eclipse().configFile('config/formatter/eclipse-java-google-style.xml')
}
}
-tasks.withType(Checkstyle).configureEach {
- reports {
- xml.required = false
- html.required = true
- }
- excludes = [ "**/module-info.java" ]
-}
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
+ 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 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 = file("$projectDir")
- file = new File("${projectDir}/src/site/sphinx/changelog.rst")
- fromRef = "4.0"
+ 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 ="""
+ templateContent.set ("""
************************
Changelog
************************
@@ -429,38 +596,38 @@ Version {{name}}
{{/issues}}
{{/tags}}
-"""
+""")
// @formatter:on
}
tasks.register('updateKeywords', JavaExec) {
group = "Execution"
- description = "Run the main class with JavaExecTask"
+ 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
]
- main("net.sf.jsqlparser.parser.ParserKeywordsUtils")
+ mainClass.set("net.sf.jsqlparser.parser.ParserKeywordsUtils")
dependsOn(compileJava)
}
-xslt {
+tasks.register('xslt', SaxonXsltTask) {
def outFile = version.endsWith("-SNAPSHOT")
- ? file("src/site/sphinx/syntax_snapshot.rst")
- : file("src/site/sphinx/syntax_stable.rst")
+ ? file("src/site/sphinx/syntax_snapshot.rst")
+ : file("src/site/sphinx/syntax_stable.rst")
dependsOn(renderRR)
- stylesheet 'src/main/resources/rr/xhtml2rst.xsl'
+ stylesheet file('src/main/resources/rr/xhtml2rst.xsl')
- parameters (
- "withFloatingToc": System.getenv().getOrDefault("FLOATING_TOC", "true"),
+ parameters(
+ "withFloatingToc": System.getProperty("FLOATING_TOC", "false"),
"isSnapshot": Boolean.toString(version.endsWith("-SNAPSHOT"))
)
// Transform every .xml file in the "input" directory.
- input "$buildDir/rr/JSqlParserCC.xhtml"
+ input layout.buildDirectory.file("rr/JSqlParserCC.xhtml").get()
output outFile
}
@@ -491,7 +658,7 @@ tasks.register('sphinx', Exec) {
, "-Drelease=${getVersion(false)}"
, "-Drst_prolog=$PROLOG"
, "${projectDir}/src/site/sphinx"
- , "${project.buildDir}/sphinx"
+ , layout.buildDirectory.file("sphinx").get().asFile
]
executable "sphinx-build"
@@ -515,6 +682,7 @@ publishing {
artifactId = 'jsqlparser'
from components.java
+
versionMapping {
usage('java-api') {
fromResolutionOf('runtimeClasspath')
@@ -523,54 +691,61 @@ publishing {
fromResolutionResult()
}
}
+
pom {
- name = 'JSQLParser library'
- description = 'Parse SQL Statements into Abstract Syntax Trees (AST)'
- url = 'https://github.com/JSQLParser/JSqlParser'
+ name.set('JSQLParser library')
+ description.set('Parse SQL Statements into Abstract Syntax Trees (AST)')
+ url.set('https://github.com/JSQLParser/JSqlParser')
+
licenses {
license {
- name = 'GNU Library or Lesser General Public License (LGPL) V2.1'
- url = 'http://www.gnu.org/licenses/lgpl-2.1.html'
+ 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 = 'The Apache Software License, Version 2.0'
- url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+ name.set('The Apache Software License, Version 2.0')
+ url.set('http://www.apache.org/licenses/LICENSE-2.0.txt')
}
}
+
developers {
developer {
- id = 'twa'
- name = 'Tobias Warneke'
- email = 't.warneke@gmx.net'
+ id.set('twa')
+ name.set('Tobias Warneke')
+ email.set('t.warneke@gmx.net')
}
developer {
- id = 'are'
- name = 'Andreas Reichel'
- email = 'andreas@manticore-projects.com'
+ id.set('are')
+ name.set('Andreas Reichel')
+ email.set('andreas@manticore-projects.com')
}
}
+
scm {
- connection = 'scm:git:https://github.com/JSQLParser/JSqlParser.git'
- developerConnection = 'scm:git:ssh://git@github.com:JSQLParser/JSqlParser.git'
- url = 'https://github.com/JSQLParser/JSqlParser.git'
+ 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://oss.sonatype.org/service/local/staging/deploy/maven2/"
- def snapshotsRepoUrl= "https://oss.sonatype.org/content/repositories/snapshots/"
- url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
+ 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 = System.getenv("ossrhUsername")
- password = System.getenv("ossrhPassword")
+ username = providers.environmentVariable("ossrhUsername").orNull
+ password = providers.environmentVariable("ossrhPassword").orNull
}
}
}
}
+
signing {
//def signingKey = findProperty("signingKey")
//def signingPassword = findProperty("signingPassword")
@@ -588,12 +763,13 @@ tasks.withType(JavaCompile).configureEach {
remotes {
webServer {
- host = findProperty("${project.name}.host")
- user = findProperty("${project.name}.username")
- identity = new File("${System.properties['user.home']}/.ssh/id_rsa")
+ 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) {
@@ -610,12 +786,24 @@ tasks.register('upload') {
session(remotes.webServer) {
def versionStable = getVersion(false)
execute "mkdir -p download/${project.name}-${versionStable}"
- for (File file: fileTree(include:['*.jar'], dir:"${project.buildDir}/libs").collect()) {
+ 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
}
-upload.dependsOn(check, assemble, gitChangelogTask, renderRR, xslt, xmldoc)
+jmh {
+ includes = ['.*JSQLParserBenchmark.*']
+ warmupIterations = 2
+ fork = 3
+ iterations = 5
+ timeOnIteration = '1s'
+}
\ No newline at end of file
diff --git a/config/pmd/ruleset.xml b/config/pmd/ruleset.xml
index acca2d6e9..45804d4c0 100644
--- a/config/pmd/ruleset.xml
+++ b/config/pmd/ruleset.xml
@@ -20,14 +20,15 @@ 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
+
@@ -46,6 +47,14 @@ under the License.
+
+
+
+
+
+
@@ -63,14 +72,15 @@ under the License.
-
-
+
+
+
@@ -80,16 +90,10 @@ under the License.
+
+
-
-
-
-
-
-
-
-
-
+
@@ -97,15 +101,14 @@ under the License.
-
-
-
+
+
-
+
-
+
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 522c7558e..8b590d14c 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,6 +1,6 @@
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx1G -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError
+org.gradle.jvmargs=-Xmx8G -Xss8m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError
org.gradle.caching=true
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 7f93135c4..d997cfc60 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 3fa8f862f..dbc3ce4a0 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
index 0adc8e1a5..f640dbced 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
#!/bin/sh
#
-# Copyright © 2015-2021 the original 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,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+# SPDX-License-Identifier: Apache-2.0
+#
##############################################################################
#
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# 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/.
@@ -84,7 +86,7 @@ done
# 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 "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+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
@@ -112,7 +114,6 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;;
esac
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
@@ -145,7 +146,7 @@ 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=SC3045
+ # shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -153,7 +154,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC3045
+ # shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -170,7 +171,6 @@ fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
@@ -202,16 +202,15 @@ fi
# 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 $GRADLE_OPTS can contain fragments of
-# shell script including quotes and variable substitutions, so put them in
-# double quotes to make sure that they get re-expanded; and
-# * put everything else in single quotes, so that it's not re-expanded.
+# 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" \
- -classpath "$CLASSPATH" \
- org.gradle.wrapper.GradleWrapperMain \
+ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
diff --git a/gradlew.bat b/gradlew.bat
index 6689b85be..c4bdd3ab8 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -1,92 +1,93 @@
-@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=.
-@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.
-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% equ 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!
-set EXIT_CODE=%ERRORLEVEL%
-if %EXIT_CODE% equ 0 set EXIT_CODE=1
-if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
-exit /b %EXIT_CODE%
-
-: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 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=.
+@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
+
+goto fail
+
+: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
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 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!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
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 92c47c42d..5ac0c4666 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,11 +2,11 @@
4.0.0
com.github.jsqlparser
jsqlparser
- 4.10-SNAPSHOT
- JSQLParser library
+ 5.4-SNAPSHOT
+ JSQLParser library
2004
- JSQLParser
+ JSQLParser
bundle
https://github.com/JSQLParser/JSqlParser
@@ -24,65 +24,121 @@
+
+
+ javacc8-snapshots
+
+ true
+
+ false
+ https://central.sonatype.com/repository/maven-snapshots/
+
+
+ ossrh-snapshots
+ https://central.sonatype.com/repository/maven-snapshots/
+ true
+ false
+
+
+
+
+ javacc8-snapshots
+
+ true
+
+ false
+ https://central.sonatype.com/repository/maven-snapshots/
+
+
+ ossrh-snapshots
+ https://central.sonatype.com/repository/maven-snapshots/
+ true
+ false
+
+
+
- net.java.dev.javacc
- javacc
- [7.0.13,)
+ org.javacc
+ core
+ 8.1.0-SNAPSHOT
+ pom
+ test
+
+
+ org.javacc.generator
+ java
+ 8.1.0-SNAPSHOT
test
-
commons-io
commons-io
- [2.15.1,)
+ 2.18.0
test
- org.junit.jupiter
- junit-jupiter
- [5.10.2,)
- test
+ org.junit.jupiter
+ junit-jupiter
+ 5.11.4
+ test
org.mockito
mockito-core
- [5.11.0,)
+ 5.15.2
test
org.mockito
mockito-junit-jupiter
- [5.11.0,)
+ 5.15.2
test
org.assertj
assertj-core
- [3.25.3,)
+ (3.27.7,)
test
org.apache.commons
commons-lang3
- [3.14.0,)
+ [3.18.0,)
test
com.h2database
h2
- [2.2.224,)
+ [2.3.232,)
test
org.hamcrest
- hamcrest-all
- 1.3
+ hamcrest
+ 2.2
+ test
+
+
+
+
+ org.openjdk.jmh
+ jmh-core
+ 1.37
test
+
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ 1.37
+ provided
+
+
@@ -95,11 +151,13 @@
sonatype-nexus-staging
- https://oss.sonatype.org/service/local/staging/deploy/maven2/
+ https://central.sonatype.com/repository/maven-releases
sonatype-nexus-snapshots
- https://oss.sonatype.org/content/repositories/snapshots/
+ https://central.sonatype.com/repository/maven-snapshots/
+ false
+ true
@@ -121,7 +179,7 @@
org.codehaus.mojo
exec-maven-plugin
- 3.1.0
+ 3.5.0
net.sf.jsqlparser.parser.ParserKeywordsUtils
@@ -133,8 +191,9 @@
org.apache.maven.plugins
maven-pmd-plugin
- 3.21.2
+ 3.26.0
+ 2
${project.basedir}/config/pmd/ruleset.xml
@@ -142,6 +201,7 @@
**/*Bean.java
**/generated/*.java
+ **/net/sf/jsqlparser/parser/SimpleCharStream.java
target/generated-sources
@@ -174,7 +234,7 @@
org.codehaus.mojo
build-helper-maven-plugin
- 3.2.0
+ 3.6.0
add-source
@@ -193,20 +253,31 @@
maven-compiler-plugin
- 3.10.1
+ 3.14.0
11
11
true
${project.build.sourceEncoding}
true
+ 2000m
+
+ -J-Xss4M
+
+ true
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ 1.37
+
+
org.javacc.plugin
javacc-maven-plugin
- 3.0.3
-
+ 3.8.0
javacc
@@ -214,26 +285,31 @@
jjtree-javacc
+
+
+ -CODE_GENERATOR="Java"
+ -GRAMMAR_ENCODING="UTF-8"
+
+
+ -GRAMMAR_ENCODING="UTF-8"
+ -CODE_GENERATOR="Java"
+
+
- net.java.dev.javacc
- javacc
- 7.0.13
+ org.javacc.generator
+ java
+ 8.1.0-SNAPSHOT
+
+
+ org.javacc
+ core
+ 8.1.0-SNAPSHOT
-
- org.apache.maven.plugins
- maven-eclipse-plugin
- 2.9
-
-
- /target/generated-sources/javacc
-
-
-
org.apache.maven.plugins
maven-resources-plugin
@@ -269,32 +345,23 @@
org.apache.maven.plugins
maven-release-plugin
-
- 3.0.0-M7
+ -->
+ 3.1.1
true
false
forked-path
sign-release-artifacts
-
org.apache.maven.plugins
maven-source-plugin
- 3.2.1
+ 3.3.1
attach-sources
@@ -307,7 +374,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 3.4.1
+ 3.11.2
attach-javadocs
@@ -315,6 +382,10 @@
${javadoc.opts}
net.sf.jsqlparser.parser
none
+ true
+ 2g
+ 800m
+ -J-Xss4m
jar
@@ -325,7 +396,7 @@
org.apache.maven.plugins
maven-jar-plugin
- 3.3.0
+ 3.4.2
@@ -334,41 +405,6 @@
-
- maven-site-plugin
- 3.12.1
-
-
- attach-descriptor
-
- attach-descriptor
-
-
-
-
- en
-
-
-
- org.eluder.coveralls
- coveralls-maven-plugin
- 4.3.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
@@ -378,7 +414,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 3.2.5
+ 3.5.2
false
@@ -386,13 +422,14 @@
--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.10
+ 0.8.13
@@ -411,7 +448,7 @@
com.diffplug.spotless
spotless-maven-plugin
- 2.28.0
+ 2.44.4
origin/master
@@ -452,28 +489,40 @@
+
+ org.sonatype.central
+ central-publishing-maven-plugin
+ 0.10.0
+ true
+
+ sonatype-nexus
+
+
-
+
org.apache.maven.plugins
maven-surefire-report-plugin
- 3.0.0-M7
+ 3.5.2
${project.reporting.outputDirectory}/testresults
+ -Xmx2G -Xms800m -Xss4m
org.apache.maven.plugins
maven-javadoc-plugin
- 3.4.1
+ 3.11.2
true
- 800m
none
-
+ 2g
+ 800m
+ -J-Xss2m
+
`'ü'`
public StringValue getStringValue() {
return new StringValue(
diff --git a/src/main/java/net/sf/jsqlparser/expression/HighExpression.java b/src/main/java/net/sf/jsqlparser/expression/HighExpression.java
new file mode 100644
index 000000000..4d3a9cd63
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/HighExpression.java
@@ -0,0 +1,42 @@
+/*-
+ * #%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 HighExpression extends ASTNodeAccessImpl implements Expression {
+ private Expression expression;
+
+ public HighExpression() {
+ // empty constructor
+ }
+
+ public HighExpression(Expression expression) {
+ this.expression = expression;
+ }
+
+ @Override
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
+ }
+
+ public Expression getExpression() {
+ return expression;
+ }
+
+ public void setExpression(Expression expression) {
+ this.expression = expression;
+ }
+
+ @Override
+ public String toString() {
+ return "HIGH " + expression.toString();
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/IntervalExpression.java b/src/main/java/net/sf/jsqlparser/expression/IntervalExpression.java
index 26584c63d..9c028c769 100644
--- a/src/main/java/net/sf/jsqlparser/expression/IntervalExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/IntervalExpression.java
@@ -15,9 +15,9 @@
public class IntervalExpression extends ASTNodeAccessImpl implements Expression {
+ private final boolean intervalKeyword;
private String parameter = null;
private String intervalType = null;
- private final boolean intervalKeyword;
private Expression expression = null;
public IntervalExpression() {
@@ -28,6 +28,13 @@ public IntervalExpression(boolean intervalKeyword) {
this.intervalKeyword = intervalKeyword;
}
+ public IntervalExpression(int value, String type) {
+ this.parameter = null;
+ this.intervalKeyword = true;
+ this.expression = new LongValue(value);
+ this.intervalType = type;
+ }
+
public boolean isUsingIntervalKeyword() {
return intervalKeyword;
}
@@ -64,8 +71,8 @@ public String toString() {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public IntervalExpression withParameter(String parameter) {
diff --git a/src/main/java/net/sf/jsqlparser/expression/Inverse.java b/src/main/java/net/sf/jsqlparser/expression/Inverse.java
new file mode 100644
index 000000000..b50d8be8f
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/Inverse.java
@@ -0,0 +1,42 @@
+/*-
+ * #%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 Inverse extends ASTNodeAccessImpl implements Expression {
+ private Expression expression;
+
+ public Inverse() {
+ // empty constructor
+ }
+
+ public Inverse(Expression expression) {
+ this.expression = expression;
+ }
+
+ @Override
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
+ }
+
+ public Expression getExpression() {
+ return expression;
+ }
+
+ public void setExpression(Expression expression) {
+ this.expression = expression;
+ }
+
+ @Override
+ public String toString() {
+ return "INVERSE (" + expression.toString() + ")";
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/JdbcNamedParameter.java b/src/main/java/net/sf/jsqlparser/expression/JdbcNamedParameter.java
index 9e8d83792..84aa0b34e 100644
--- a/src/main/java/net/sf/jsqlparser/expression/JdbcNamedParameter.java
+++ b/src/main/java/net/sf/jsqlparser/expression/JdbcNamedParameter.java
@@ -39,8 +39,8 @@ public void setName(String name) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/JdbcParameter.java b/src/main/java/net/sf/jsqlparser/expression/JdbcParameter.java
index aaedebc68..f512c47fc 100644
--- a/src/main/java/net/sf/jsqlparser/expression/JdbcParameter.java
+++ b/src/main/java/net/sf/jsqlparser/expression/JdbcParameter.java
@@ -67,8 +67,8 @@ public void setUseFixedIndex(boolean useFixedIndex) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonAggregateFunction.java b/src/main/java/net/sf/jsqlparser/expression/JsonAggregateFunction.java
index 497c8dbc5..20bfa272e 100644
--- a/src/main/java/net/sf/jsqlparser/expression/JsonAggregateFunction.java
+++ b/src/main/java/net/sf/jsqlparser/expression/JsonAggregateFunction.java
@@ -11,21 +11,19 @@
import java.util.List;
import java.util.Objects;
+
import net.sf.jsqlparser.statement.select.OrderByElement;
/**
- *
* @author Andreas Reichel
*/
public class JsonAggregateFunction extends FilterOverImpl implements Expression {
+ private final OrderByClause expressionOrderBy = new OrderByClause();
private JsonFunctionType functionType;
-
private Expression expression = null;
- private final OrderByClause expressionOrderBy = new OrderByClause();
-
private boolean usingKeyKeyword = false;
- private String key;
+ private Object key;
private boolean usingValueKeyword = false;
private Object value;
@@ -70,11 +68,6 @@ public void setType(JsonFunctionType type) {
"The Type of the JSON Aggregate Function must not be null");
}
- public JsonAggregateFunction withType(JsonFunctionType type) {
- this.setType(type);
- return this;
- }
-
public void setType(String typeName) {
this.functionType = JsonFunctionType
.valueOf(Objects
@@ -83,6 +76,11 @@ public void setType(String typeName) {
.toUpperCase());
}
+ public JsonAggregateFunction withType(JsonFunctionType type) {
+ this.setType(type);
+ return this;
+ }
+
public JsonAggregateFunction withType(String typeName) {
this.setType(typeName);
return this;
@@ -114,15 +112,15 @@ public JsonAggregateFunction withUsingKeyKeyword(boolean usingKeyKeyword) {
return this;
}
- public String getKey() {
+ public Object getKey() {
return key;
}
- public void setKey(String key) {
+ public void setKey(Object key) {
this.key = key;
}
- public JsonAggregateFunction withKey(String key) {
+ public JsonAggregateFunction withKey(Object key) {
this.setKey(key);
return this;
}
@@ -181,8 +179,8 @@ public JsonAggregateFunction withExpressionOrderByElements(
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
// avoid countless Builder --> String conversion
@@ -190,6 +188,7 @@ public void accept(ExpressionVisitor expressionVisitor) {
public StringBuilder append(StringBuilder builder) {
switch (functionType) {
case OBJECT:
+ case MYSQL_OBJECT:
appendObject(builder);
break;
case ARRAY:
@@ -211,6 +210,8 @@ public StringBuilder appendObject(StringBuilder builder) {
builder.append("KEY ");
}
builder.append(key).append(" VALUE ").append(value);
+ } else if (functionType == JsonFunctionType.MYSQL_OBJECT) {
+ builder.append(key).append(", ").append(value);
} else {
builder.append(key).append(":").append(value);
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonAggregateOnNullType.java b/src/main/java/net/sf/jsqlparser/expression/JsonAggregateOnNullType.java
index d9e2b4c51..898dad7c0 100644
--- a/src/main/java/net/sf/jsqlparser/expression/JsonAggregateOnNullType.java
+++ b/src/main/java/net/sf/jsqlparser/expression/JsonAggregateOnNullType.java
@@ -26,7 +26,6 @@
package net.sf.jsqlparser.expression;
/**
- *
* @author Andreas Reichel
*/
public enum JsonAggregateOnNullType {
diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonAggregateUniqueKeysType.java b/src/main/java/net/sf/jsqlparser/expression/JsonAggregateUniqueKeysType.java
index aa1370595..097aad552 100644
--- a/src/main/java/net/sf/jsqlparser/expression/JsonAggregateUniqueKeysType.java
+++ b/src/main/java/net/sf/jsqlparser/expression/JsonAggregateUniqueKeysType.java
@@ -26,7 +26,6 @@
package net.sf.jsqlparser.expression;
/**
- *
* @author Andreas Reichel
*/
public enum JsonAggregateUniqueKeysType {
diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonExpression.java b/src/main/java/net/sf/jsqlparser/expression/JsonExpression.java
index 9fe2811cf..f258e855c 100644
--- a/src/main/java/net/sf/jsqlparser/expression/JsonExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/JsonExpression.java
@@ -18,10 +18,9 @@
import java.util.Map;
public class JsonExpression extends ASTNodeAccessImpl implements Expression {
+ private final List> idents = new ArrayList<>();
private Expression expr;
- private final List> idents = new ArrayList<>();
-
public JsonExpression() {
}
@@ -30,14 +29,14 @@ public JsonExpression(Expression expr) {
this.expr = expr;
}
- public JsonExpression(Expression expr, List> idents) {
+ public JsonExpression(Expression expr, List> idents) {
this.expr = expr;
this.idents.addAll(idents);
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public Expression getExpression() {
@@ -48,26 +47,26 @@ public void setExpression(Expression expr) {
this.expr = expr;
}
- public void addIdent(String ident, String operator) {
+ public void addIdent(Expression ident, String operator) {
idents.add(new AbstractMap.SimpleEntry<>(ident, operator));
}
- public void addAllIdents(Collection> idents) {
+ public void addAllIdents(Collection> idents) {
this.idents.addAll(idents);
}
- public List> getIdentList() {
+ public List> getIdentList() {
return idents;
}
- public Map.Entry getIdent(int index) {
+ public Map.Entry getIdent(int index) {
return idents.get(index);
}
@Deprecated
- public List getIdents() {
- ArrayList l = new ArrayList<>();
- for (Map.Entry ident : idents) {
+ public List getIdents() {
+ ArrayList l = new ArrayList<>();
+ for (Map.Entry ident : idents) {
l.add(ident.getKey());
}
@@ -77,7 +76,7 @@ public List getIdents() {
@Deprecated
public List getOperators() {
ArrayList l = new ArrayList<>();
- for (Map.Entry ident : idents) {
+ for (Map.Entry ident : idents) {
l.add(ident.getValue());
}
return l;
@@ -87,7 +86,7 @@ public List getOperators() {
public String toString() {
StringBuilder b = new StringBuilder();
b.append(expr.toString());
- for (Map.Entry ident : idents) {
+ for (Map.Entry ident : idents) {
b.append(ident.getValue()).append(ident.getKey());
}
return b.toString();
diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonFunction.java b/src/main/java/net/sf/jsqlparser/expression/JsonFunction.java
index 9d09b9711..3cc409873 100644
--- a/src/main/java/net/sf/jsqlparser/expression/JsonFunction.java
+++ b/src/main/java/net/sf/jsqlparser/expression/JsonFunction.java
@@ -11,251 +11,598 @@
import java.util.ArrayList;
import java.util.Objects;
+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
+import net.sf.jsqlparser.statement.create.table.ColDataType;
/**
+ * Represents a JSON-Function.
+ * Currently supported are the types in {@link JsonFunctionType}.
+ *
+ * For JSON_OBJECT the parameters are available from {@link #getKeyValuePairs()}
+ *
+ * For JSON_ARRAY the parameters are availble from {@link #getExpressions()}.
*
* @author Andreas Reichel
*/
-
public class JsonFunction extends ASTNodeAccessImpl implements Expression {
- private JsonFunctionType functionType;
- private final ArrayList keyValuePairs = new ArrayList<>();
- private final ArrayList expressions = new ArrayList<>();
- private JsonAggregateOnNullType onNullType;
- private JsonAggregateUniqueKeysType uniqueKeysType;
-
- public ArrayList getKeyValuePairs() {
- return keyValuePairs;
- }
-
- public ArrayList getExpressions() {
- return expressions;
- }
-
- public JsonKeyValuePair getKeyValuePair(int i) {
- return keyValuePairs.get(i);
- }
-
- public JsonFunctionExpression getExpression(int i) {
- return expressions.get(i);
- }
-
- public boolean add(JsonKeyValuePair keyValuePair) {
- return keyValuePairs.add(keyValuePair);
- }
-
- public void add(int i, JsonKeyValuePair keyValuePair) {
- keyValuePairs.add(i, keyValuePair);
- }
-
- public boolean add(JsonFunctionExpression expression) {
- return expressions.add(expression);
- }
-
- public void add(int i, JsonFunctionExpression expression) {
- expressions.add(i, expression);
- }
-
- public boolean isEmpty() {
- return keyValuePairs.isEmpty();
- }
-
- public JsonAggregateOnNullType getOnNullType() {
- return onNullType;
- }
-
- public void setOnNullType(JsonAggregateOnNullType onNullType) {
- this.onNullType = onNullType;
- }
-
- public JsonFunction withOnNullType(JsonAggregateOnNullType onNullType) {
- this.setOnNullType(onNullType);
- return this;
- }
-
- public JsonAggregateUniqueKeysType getUniqueKeysType() {
- return uniqueKeysType;
- }
-
- public void setUniqueKeysType(JsonAggregateUniqueKeysType uniqueKeysType) {
- this.uniqueKeysType = uniqueKeysType;
- }
-
- public JsonFunction withUniqueKeysType(JsonAggregateUniqueKeysType uniqueKeysType) {
- this.setUniqueKeysType(uniqueKeysType);
- return this;
- }
-
- public JsonFunctionType getType() {
- return functionType;
- }
-
- public void setType(JsonFunctionType type) {
- this.functionType =
- Objects.requireNonNull(type, "The Type of the JSON Aggregate Function must not be null");
- }
-
- public JsonFunction withType(JsonFunctionType type) {
- this.setType(type);
- return this;
- }
-
- public void setType(String typeName) {
- this.functionType = JsonFunctionType.valueOf(
- Objects.requireNonNull(typeName, "The Type of the JSON Aggregate Function must not be null")
- .toUpperCase());
- }
-
- public JsonFunction withType(String typeName) {
- this.setType(typeName);
- return this;
- }
-
- @Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
- }
-
- // avoid countless Builder --> String conversion
- public StringBuilder append(StringBuilder builder) {
- switch (functionType) {
- case OBJECT:
- appendObject(builder);
- break;
- case POSTGRES_OBJECT:
- appendPostgresObject(builder);
- break;
- case MYSQL_OBJECT:
- appendMySqlObject(builder);
- break;
- case ARRAY:
- appendArray(builder);
- break;
- default:
- // this should never happen really
- }
- return builder;
- }
-
- @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
- public StringBuilder appendObject(StringBuilder builder) {
- builder.append("JSON_OBJECT( ");
- int i = 0;
- for (JsonKeyValuePair keyValuePair : keyValuePairs) {
- if (i > 0) {
- builder.append(", ");
- }
- if (keyValuePair.isUsingValueKeyword()) {
- if (keyValuePair.isUsingKeyKeyword()) {
- builder.append("KEY ");
+ public enum JsonOnResponseBehaviorType {
+ ERROR, NULL, DEFAULT, EMPTY, EMPTY_ARRAY, EMPTY_OBJECT, TRUE, FALSE, UNKNOWN
+ }
+
+ public enum JsonWrapperType {
+ WITHOUT, WITH
+ }
+
+ public enum JsonWrapperMode {
+ CONDITIONAL, UNCONDITIONAL
+ }
+
+ public enum JsonQuotesType {
+ KEEP, OMIT
+ }
+
+ public enum ScalarsType {
+ ALLOW, DISALLOW
+ }
+
+ public static class JsonOnResponseBehavior {
+ private JsonOnResponseBehaviorType type;
+ private Expression expression;
+
+ public JsonOnResponseBehavior(JsonOnResponseBehaviorType type) {
+ this(type, null);
+ }
+
+ public JsonOnResponseBehavior(JsonOnResponseBehaviorType type, Expression expression) {
+ this.type = type;
+ this.expression = expression;
+ }
+
+ public JsonOnResponseBehaviorType getType() {
+ return type;
+ }
+
+ public void setType(JsonOnResponseBehaviorType type) {
+ this.type = type;
+ }
+
+ public Expression getExpression() {
+ return expression;
+ }
+
+ public void setExpression(Expression expression) {
+ this.expression = expression;
+ }
+
+ public StringBuilder append(StringBuilder builder) {
+ switch (type) {
+ case ERROR:
+ builder.append("ERROR");
+ break;
+ case NULL:
+ builder.append("NULL");
+ break;
+ case DEFAULT:
+ builder.append("DEFAULT ").append(expression);
+ break;
+ case EMPTY:
+ builder.append("EMPTY ");
+ break;
+ case EMPTY_ARRAY:
+ builder.append("EMPTY ARRAY");
+ break;
+ case EMPTY_OBJECT:
+ builder.append("EMPTY OBJECT");
+ break;
+ case TRUE:
+ builder.append("TRUE");
+ break;
+ case FALSE:
+ builder.append("FALSE");
+ break;
+ case UNKNOWN:
+ builder.append("UNKNOWN");
+ break;
+ default:
+ throw new IllegalStateException("Unhandled JsonOnResponseBehavior: " + type);
+ // this should never happen
+ }
+ return builder;
}
- builder.append(keyValuePair.getKey()).append(" VALUE ").append(keyValuePair.getValue());
- } else {
- builder.append(keyValuePair.getKey()).append(":").append(keyValuePair.getValue());
- }
-
- if (keyValuePair.isUsingFormatJson()) {
- builder.append(" FORMAT JSON");
- }
- i++;
- }
-
- if (onNullType != null) {
- switch (onNullType) {
- case NULL:
- builder.append(" NULL ON NULL");
- break;
- case ABSENT:
- builder.append(" ABSENT On NULL");
- break;
- default:
- // this should never happen
- }
- }
-
- if (uniqueKeysType != null) {
- switch (uniqueKeysType) {
- case WITH:
- builder.append(" WITH UNIQUE KEYS");
- break;
- case WITHOUT:
- builder.append(" WITHOUT UNIQUE KEYS");
- break;
- default:
- // this should never happen
- }
- }
-
- builder.append(" ) ");
-
- return builder;
- }
-
-
- @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
- public StringBuilder appendPostgresObject(StringBuilder builder) {
- builder.append("JSON_OBJECT( ");
- for (JsonKeyValuePair keyValuePair : keyValuePairs) {
- builder.append(keyValuePair.getKey());
- if (keyValuePair.getValue()!=null) {
- builder.append(", ").append(keyValuePair.getValue());
- }
- }
- builder.append(" ) ");
-
- return builder;
- }
-
- public StringBuilder appendMySqlObject(StringBuilder builder) {
- builder.append("JSON_OBJECT( ");
- int i=0;
- for (JsonKeyValuePair keyValuePair : keyValuePairs) {
- if (i>0) {
- builder.append(", ");
- }
- builder.append(keyValuePair.getKey());
- builder.append(", ").append(keyValuePair.getValue());
- i++;
- }
- builder.append(" ) ");
-
- return builder;
- }
-
- @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
- public StringBuilder appendArray(StringBuilder builder) {
- builder.append("JSON_ARRAY( ");
- int i = 0;
-
- for (JsonFunctionExpression expr : expressions) {
- if (i > 0) {
- builder.append(", ");
- }
- expr.append(builder);
- i++;
- }
-
- if (onNullType != null) {
- switch (onNullType) {
- case NULL:
- builder.append(" NULL ON NULL ");
- break;
- case ABSENT:
- builder.append(" ABSENT ON NULL ");
- break;
- default:
- // "ON NULL" was omitted
- }
- }
- builder.append(") ");
-
- return builder;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- return append(builder).toString();
- }
+
+ @Override
+ public String toString() {
+ return append(new StringBuilder()).toString();
+ }
+ }
+
+ private final ArrayList keyValuePairs = new ArrayList<>();
+ private final ArrayList expressions = new ArrayList<>();
+ private final ArrayList passingExpressions = new ArrayList<>();
+ private final ArrayList additionalQueryPathArguments = new ArrayList<>();
+ private JsonFunctionType functionType;
+ private JsonAggregateOnNullType onNullType;
+ private JsonAggregateUniqueKeysType uniqueKeysType;
+
+ private boolean isStrict = false;
+ private JsonFunctionExpression inputExpression;
+ private Expression jsonPathExpression;
+ private ColDataType returningType;
+ private boolean returningFormatJson;
+ private String returningEncoding;
+ private JsonOnResponseBehavior onEmptyBehavior;
+ private JsonOnResponseBehavior onErrorBehavior;
+ private JsonWrapperType wrapperType;
+ private JsonWrapperMode wrapperMode;
+ private boolean wrapperArray;
+ private JsonQuotesType quotesType;
+ private boolean quotesOnScalarString;
+ private ScalarsType scalarsType;
+
+ public JsonFunction() {}
+
+ public JsonFunction(JsonFunctionType functionType) {
+ this.functionType = functionType;
+ }
+
+ /**
+ * Returns the Parameters of an JSON_OBJECT
+ * The KeyValuePairs may not have both key and value set, in some cases only the Key is set.
+ *
+ * @see net.sf.jsqlparser.parser.feature.Feature#allowCommaAsKeyValueSeparator
+ *
+ * @return A List of KeyValuePairs, never NULL
+ */
+ public ArrayList getKeyValuePairs() {
+ return keyValuePairs;
+ }
+
+ /**
+ * Returns the parameters of JSON_ARRAY
+ *
+ * @return A List of {@link JsonFunctionExpression}s, never NULL
+ */
+ public ArrayList getExpressions() {
+ return expressions;
+ }
+
+ public JsonKeyValuePair getKeyValuePair(int i) {
+ return keyValuePairs.get(i);
+ }
+
+ public JsonFunctionExpression getExpression(int i) {
+ return expressions.get(i);
+ }
+
+ public boolean add(JsonKeyValuePair keyValuePair) {
+ return keyValuePairs.add(keyValuePair);
+ }
+
+ public void add(int i, JsonKeyValuePair keyValuePair) {
+ keyValuePairs.add(i, keyValuePair);
+ }
+
+ public boolean add(JsonFunctionExpression expression) {
+ return expressions.add(expression);
+ }
+
+ public void add(int i, JsonFunctionExpression expression) {
+ expressions.add(i, expression);
+ }
+
+ public ArrayList getPassingExpressions() {
+ return passingExpressions;
+ }
+
+ public boolean addPassingExpression(Expression expression) {
+ return passingExpressions.add(expression);
+ }
+
+ public ArrayList getAdditionalQueryPathArguments() {
+ return additionalQueryPathArguments;
+ }
+
+ public boolean addAdditionalQueryPathArgument(String argument) {
+ return additionalQueryPathArguments.add(argument);
+ }
+
+ public JsonFunctionExpression getInputExpression() {
+ return inputExpression;
+ }
+
+ public void setInputExpression(JsonFunctionExpression inputExpression) {
+ this.inputExpression = inputExpression;
+ }
+
+ public Expression getJsonPathExpression() {
+ return jsonPathExpression;
+ }
+
+ public void setJsonPathExpression(Expression jsonPathExpression) {
+ this.jsonPathExpression = jsonPathExpression;
+ }
+
+ public ColDataType getReturningType() {
+ return returningType;
+ }
+
+ public void setReturningType(ColDataType returningType) {
+ this.returningType = returningType;
+ }
+
+ public boolean isReturningFormatJson() {
+ return returningFormatJson;
+ }
+
+ public void setReturningFormatJson(boolean returningFormatJson) {
+ this.returningFormatJson = returningFormatJson;
+ }
+
+ public String getReturningEncoding() {
+ return returningEncoding;
+ }
+
+ public void setReturningEncoding(String returningEncoding) {
+ this.returningEncoding = returningEncoding;
+ }
+
+ public JsonOnResponseBehavior getOnEmptyBehavior() {
+ return onEmptyBehavior;
+ }
+
+ public void setOnEmptyBehavior(JsonOnResponseBehavior onEmptyBehavior) {
+ this.onEmptyBehavior = onEmptyBehavior;
+ }
+
+ public JsonOnResponseBehavior getOnErrorBehavior() {
+ return onErrorBehavior;
+ }
+
+ public void setOnErrorBehavior(JsonOnResponseBehavior onErrorBehavior) {
+ this.onErrorBehavior = onErrorBehavior;
+ }
+
+ public JsonWrapperType getWrapperType() {
+ return wrapperType;
+ }
+
+ public void setWrapperType(JsonWrapperType wrapperType) {
+ this.wrapperType = wrapperType;
+ }
+
+ public JsonWrapperMode getWrapperMode() {
+ return wrapperMode;
+ }
+
+ public void setWrapperMode(JsonWrapperMode wrapperMode) {
+ this.wrapperMode = wrapperMode;
+ }
+
+ public boolean isWrapperArray() {
+ return wrapperArray;
+ }
+
+ public void setWrapperArray(boolean wrapperArray) {
+ this.wrapperArray = wrapperArray;
+ }
+
+ public JsonQuotesType getQuotesType() {
+ return quotesType;
+ }
+
+ public void setQuotesType(JsonQuotesType quotesType) {
+ this.quotesType = quotesType;
+ }
+
+ public boolean isQuotesOnScalarString() {
+ return quotesOnScalarString;
+ }
+
+ public void setQuotesOnScalarString(boolean quotesOnScalarString) {
+ this.quotesOnScalarString = quotesOnScalarString;
+ }
+
+ public ScalarsType getScalarsType() {
+ return scalarsType;
+ }
+
+ public void setScalarsType(ScalarsType type) {
+ this.scalarsType = type;
+ }
+
+ public boolean isEmpty() {
+ return keyValuePairs.isEmpty();
+ }
+
+ public JsonAggregateOnNullType getOnNullType() {
+ return onNullType;
+ }
+
+ public void setOnNullType(JsonAggregateOnNullType onNullType) {
+ this.onNullType = onNullType;
+ }
+
+ public JsonFunction withOnNullType(JsonAggregateOnNullType onNullType) {
+ this.setOnNullType(onNullType);
+ return this;
+ }
+
+ public JsonAggregateUniqueKeysType getUniqueKeysType() {
+ return uniqueKeysType;
+ }
+
+ public void setUniqueKeysType(JsonAggregateUniqueKeysType uniqueKeysType) {
+ this.uniqueKeysType = uniqueKeysType;
+ }
+
+ public JsonFunction withUniqueKeysType(JsonAggregateUniqueKeysType uniqueKeysType) {
+ this.setUniqueKeysType(uniqueKeysType);
+ return this;
+ }
+
+ public JsonFunctionType getType() {
+ return functionType;
+ }
+
+ public void setType(JsonFunctionType type) {
+ this.functionType =
+ Objects.requireNonNull(type,
+ "The Type of the JSON Aggregate Function must not be null");
+ }
+
+ public void setType(String typeName) {
+ this.functionType = JsonFunctionType.valueOf(
+ Objects.requireNonNull(typeName,
+ "The Type of the JSON Aggregate Function must not be null")
+ .toUpperCase());
+ }
+
+ public JsonFunction withType(JsonFunctionType type) {
+ this.setType(type);
+ return this;
+ }
+
+ public JsonFunction withType(String typeName) {
+ this.setType(typeName);
+ return this;
+ }
+
+ public boolean isStrict() {
+ return isStrict;
+ }
+
+ public void setStrict(boolean strict) {
+ isStrict = strict;
+ }
+
+ public JsonFunction withStrict(boolean strict) {
+ this.setStrict(strict);
+ return this;
+ }
+
+ @Override
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
+ }
+
+ // avoid countless Builder --> String conversion
+ public StringBuilder append(StringBuilder builder) {
+ switch (functionType) {
+ case OBJECT:
+ case POSTGRES_OBJECT:
+ case MYSQL_OBJECT:
+ appendObject(builder);
+ break;
+ case ARRAY:
+ appendArray(builder);
+ break;
+ case VALUE:
+ appendValue(builder);
+ break;
+ case QUERY:
+ appendQuery(builder);
+ break;
+ case EXISTS:
+ appendExists(builder);
+ break;
+ default:
+ // this should never happen really
+ }
+ return builder;
+ }
+
+ @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
+ public StringBuilder appendObject(StringBuilder builder) {
+ builder.append("JSON_OBJECT( ");
+ int i = 0;
+ for (JsonKeyValuePair keyValuePair : keyValuePairs) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ keyValuePair.append(builder);
+ i++;
+ }
+
+ appendOnNullType(builder);
+ if (isStrict) {
+ builder.append(" STRICT");
+ }
+ appendUniqueKeys(builder);
+ appendReturningClause(builder, true);
+
+ builder.append(" ) ");
+
+ return builder;
+ }
+
+ private void appendOnNullType(StringBuilder builder) {
+ if (onNullType != null) {
+ switch (onNullType) {
+ case NULL:
+ builder.append(" NULL ON NULL");
+ break;
+ case ABSENT:
+ builder.append(" ABSENT ON NULL");
+ break;
+ default:
+ // this should never happen
+ }
+ }
+ }
+
+ private void appendUniqueKeys(StringBuilder builder) {
+ if (uniqueKeysType != null) {
+ switch (uniqueKeysType) {
+ case WITH:
+ builder.append(" WITH UNIQUE KEYS");
+ break;
+ case WITHOUT:
+ builder.append(" WITHOUT UNIQUE KEYS");
+ break;
+ default:
+ // this should never happen
+ }
+ }
+ }
+
+ @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
+ public StringBuilder appendArray(StringBuilder builder) {
+ builder.append("JSON_ARRAY( ");
+ int i = 0;
+
+ for (JsonFunctionExpression expr : expressions) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ expr.append(builder);
+ i++;
+ }
+
+ appendOnNullType(builder);
+ appendReturningClause(builder, true);
+ builder.append(") ");
+
+ return builder;
+ }
+
+ @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
+ public StringBuilder appendValue(StringBuilder builder) {
+ builder.append("JSON_VALUE(");
+ appendValueOrQueryPrefix(builder);
+
+ if (returningType != null) {
+ builder.append(" RETURNING ").append(returningType);
+ }
+
+ appendOnResponseClause(builder, onEmptyBehavior, "EMPTY");
+ appendOnResponseClause(builder, onErrorBehavior, "ERROR");
+
+ builder.append(")");
+ return builder;
+ }
+
+ @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
+ public StringBuilder appendQuery(StringBuilder builder) {
+ builder.append("JSON_QUERY(");
+ appendValueOrQueryPrefix(builder);
+
+ appendReturningClause(builder, true);
+
+ appendWrapperClause(builder);
+ appendQuotesClause(builder);
+ appendOnResponseClause(builder, onEmptyBehavior, "EMPTY");
+ appendOnResponseClause(builder, onErrorBehavior, "ERROR");
+
+ for (String additionalQueryPathArgument : additionalQueryPathArguments) {
+ builder.append(", ").append(additionalQueryPathArgument);
+ }
+
+ builder.append(")");
+ return builder;
+ }
+
+ @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
+ public StringBuilder appendExists(StringBuilder builder) {
+ builder.append("JSON_EXISTS(");
+ appendValueOrQueryPrefix(builder);
+ appendOnResponseClause(builder, onErrorBehavior, "ERROR");
+ builder.append(")");
+ return builder;
+ }
+
+ private void appendValueOrQueryPrefix(StringBuilder builder) {
+ if (inputExpression != null) {
+ inputExpression.append(builder);
+ }
+
+ if (jsonPathExpression != null) {
+ if (inputExpression != null) {
+ builder.append(", ");
+ }
+ builder.append(jsonPathExpression);
+ }
+
+ if (!passingExpressions.isEmpty()) {
+ builder.append(" PASSING ");
+ boolean comma = false;
+ for (Expression passingExpression : passingExpressions) {
+ if (comma) {
+ builder.append(", ");
+ } else {
+ comma = true;
+ }
+ builder.append(passingExpression);
+ }
+ }
+ }
+
+ private void appendOnResponseClause(StringBuilder builder, JsonOnResponseBehavior behavior,
+ String clause) {
+ if (behavior != null) {
+ builder.append(" ");
+ behavior.append(builder);
+ builder.append(" ON ").append(clause);
+ }
+ }
+
+ private void appendReturningClause(StringBuilder builder, boolean formatJsonAllowed) {
+ if (returningType != null) {
+ builder.append(" RETURNING ").append(returningType);
+ if (formatJsonAllowed && returningFormatJson) {
+ builder.append(" FORMAT JSON");
+ if (returningEncoding != null) {
+ builder.append(" ENCODING ").append(returningEncoding);
+ }
+ }
+ }
+ }
+
+ private void appendWrapperClause(StringBuilder builder) {
+ if (wrapperType != null) {
+ builder.append(" ").append(wrapperType);
+ if (wrapperMode != null) {
+ builder.append(" ").append(wrapperMode);
+ }
+ if (wrapperArray) {
+ builder.append(" ARRAY");
+ }
+ builder.append(" WRAPPER");
+ }
+ }
+
+ private void appendQuotesClause(StringBuilder builder) {
+ if (quotesType != null) {
+ builder.append(" ").append(quotesType).append(" QUOTES");
+ if (quotesOnScalarString) {
+ builder.append(" ON SCALAR STRING");
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ return append(builder).toString();
+ }
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonFunctionExpression.java b/src/main/java/net/sf/jsqlparser/expression/JsonFunctionExpression.java
index e23aa2751..738c09fc2 100644
--- a/src/main/java/net/sf/jsqlparser/expression/JsonFunctionExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/JsonFunctionExpression.java
@@ -14,7 +14,6 @@
import java.util.Objects;
/**
- *
* @author Andreas Reichel
*/
@@ -22,10 +21,12 @@ public class JsonFunctionExpression implements Serializable {
private final Expression expression;
private boolean usingFormatJson = false;
+ private String encoding;
public JsonFunctionExpression(Expression expression) {
this.expression = Objects.requireNonNull(expression, "The EXPRESSION must not be null");
}
+
public Expression getExpression() {
return expression;
}
@@ -37,14 +38,34 @@ public boolean isUsingFormatJson() {
public void setUsingFormatJson(boolean usingFormatJson) {
this.usingFormatJson = usingFormatJson;
}
-
+
public JsonFunctionExpression withUsingFormatJson(boolean usingFormatJson) {
this.setUsingFormatJson(usingFormatJson);
return this;
}
-
+
+ public String getEncoding() {
+ return encoding;
+ }
+
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ public JsonFunctionExpression withEncoding(String encoding) {
+ this.setEncoding(encoding);
+ return this;
+ }
+
public StringBuilder append(StringBuilder builder) {
- return builder.append(getExpression()).append(isUsingFormatJson() ? " FORMAT JSON" : "");
+ builder.append(getExpression());
+ if (isUsingFormatJson()) {
+ builder.append(" FORMAT JSON");
+ if (encoding != null) {
+ builder.append(" ENCODING ").append(encoding);
+ }
+ }
+ return builder;
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonFunctionType.java b/src/main/java/net/sf/jsqlparser/expression/JsonFunctionType.java
index 4502b3ca6..ebd497e79 100644
--- a/src/main/java/net/sf/jsqlparser/expression/JsonFunctionType.java
+++ b/src/main/java/net/sf/jsqlparser/expression/JsonFunctionType.java
@@ -11,11 +11,22 @@
package net.sf.jsqlparser.expression;
/**
- *
* @author Andreas Reichel
*/
public enum JsonFunctionType {
- OBJECT, ARRAY, POSTGRES_OBJECT, MYSQL_OBJECT;
+ OBJECT, ARRAY, VALUE, QUERY, EXISTS,
+
+ /**
+ * Not used anymore
+ */
+ @Deprecated
+ POSTGRES_OBJECT,
+
+ /**
+ * Not used anymore
+ */
+ @Deprecated
+ MYSQL_OBJECT;
public static JsonFunctionType from(String type) {
return Enum.valueOf(JsonFunctionType.class, type.toUpperCase());
diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePair.java b/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePair.java
index b85274caa..18fb4752d 100644
--- a/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePair.java
+++ b/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePair.java
@@ -14,114 +14,168 @@
import java.util.Objects;
/**
- *
* @author Andreas Reichel
*/
public class JsonKeyValuePair implements Serializable {
- private final String key;
- private boolean usingKeyKeyword = false;
- private final Object value;
- private boolean usingValueKeyword = false;
- private boolean usingFormatJson = false;
-
- public JsonKeyValuePair(String key, Object value, boolean usingKeyKeyword,
- boolean usingValueKeyword) {
- this.key = Objects.requireNonNull(key, "The KEY of the Pair must not be null");
- this.value = value;
- this.usingKeyKeyword = usingKeyKeyword;
- this.usingValueKeyword = usingValueKeyword;
- }
-
- public boolean isUsingKeyKeyword() {
- return usingKeyKeyword;
- }
-
- public void setUsingKeyKeyword(boolean usingKeyKeyword) {
- this.usingKeyKeyword = usingKeyKeyword;
- }
-
- public JsonKeyValuePair withUsingKeyKeyword(boolean usingKeyKeyword) {
- this.setUsingKeyKeyword(usingKeyKeyword);
- return this;
- }
-
- public boolean isUsingValueKeyword() {
- return usingValueKeyword;
- }
-
- public void setUsingValueKeyword(boolean usingValueKeyword) {
- this.usingValueKeyword = usingValueKeyword;
- }
-
- public JsonKeyValuePair withUsingValueKeyword(boolean usingValueKeyword) {
- this.setUsingValueKeyword(usingValueKeyword);
- return this;
- }
-
- public boolean isUsingFormatJson() {
- return usingFormatJson;
- }
-
- public void setUsingFormatJson(boolean usingFormatJson) {
- this.usingFormatJson = usingFormatJson;
- }
-
- public JsonKeyValuePair withUsingFormatJson(boolean usingFormatJson) {
- this.setUsingFormatJson(usingFormatJson);
- return this;
- }
-
- @Override
- public int hashCode() {
- int hash = 7;
- hash = 83 * hash + Objects.hashCode(this.key);
- return hash;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final JsonKeyValuePair other = (JsonKeyValuePair) obj;
- return Objects.equals(this.key, other.key);
- }
-
- public String getKey() {
- return key;
- }
-
- public Object getValue() {
- return value;
- }
-
- public StringBuilder append(StringBuilder builder) {
- if (isUsingValueKeyword()) {
- if (isUsingKeyKeyword()) {
- builder.append("KEY ");
- }
- builder.append(getKey()).append(" VALUE ").append(getValue());
- } else {
- builder.append(getKey()).append(":").append(getValue());
- }
-
- if (isUsingFormatJson()) {
- builder.append(" FORMAT JSON");
- }
-
- return builder;
- }
-
- @Override
- public String toString() {
- return append(new StringBuilder()).toString();
- }
+ private final Object key;
+ private final Object value;
+ private boolean usingKeyKeyword;
+ private JsonKeyValuePairSeparator separator;
+ private boolean usingFormatJson = false;
+ private String encoding;
+
+ /**
+ * Please use the Constructor with {@link JsonKeyValuePairSeparator} parameter.
+ */
+ @Deprecated
+ public JsonKeyValuePair(Object key, Object value, boolean usingKeyKeyword,
+ boolean usingValueKeyword) {
+ this(key, value, usingKeyKeyword, usingValueKeyword ? JsonKeyValuePairSeparator.VALUE
+ : JsonKeyValuePairSeparator.COLON);
+ }
+
+ public JsonKeyValuePair(Object key, Object value, boolean usingKeyKeyword,
+ JsonKeyValuePairSeparator separator) {
+ this.key = Objects.requireNonNull(key, "The KEY of the Pair must not be null");
+ this.value = value;
+ this.usingKeyKeyword = usingKeyKeyword;
+ this.separator =
+ Objects.requireNonNull(separator, "The KeyValuePairSeparator must not be NULL");
+ }
+
+ public boolean isUsingKeyKeyword() {
+ return usingKeyKeyword;
+ }
+
+ public void setUsingKeyKeyword(boolean usingKeyKeyword) {
+ this.usingKeyKeyword = usingKeyKeyword;
+ }
+
+ public JsonKeyValuePair withUsingKeyKeyword(boolean usingKeyKeyword) {
+ this.setUsingKeyKeyword(usingKeyKeyword);
+ return this;
+ }
+
+ /**
+ * Use {@link #getSeparator()}
+ */
+ @Deprecated
+ public boolean isUsingValueKeyword() {
+ return separator == JsonKeyValuePairSeparator.VALUE;
+ }
+
+ /**
+ * Use {@link #setSeparator(JsonKeyValuePairSeparator)}
+ */
+ @Deprecated
+ public void setUsingValueKeyword(boolean usingValueKeyword) {
+ separator = usingValueKeyword ? JsonKeyValuePairSeparator.VALUE
+ : JsonKeyValuePairSeparator.COLON;
+ }
+
+ /**
+ * Use {@link #withSeparator(JsonKeyValuePairSeparator)}
+ */
+ @Deprecated
+ public JsonKeyValuePair withUsingValueKeyword(boolean usingValueKeyword) {
+ this.setUsingValueKeyword(usingValueKeyword);
+ return this;
+ }
+
+ public JsonKeyValuePairSeparator getSeparator() {
+ return separator;
+ }
+
+ public void setSeparator(JsonKeyValuePairSeparator separator) {
+ this.separator = separator;
+ }
+
+ public JsonKeyValuePair withSeparator(JsonKeyValuePairSeparator separator) {
+ this.setSeparator(separator);
+ return this;
+ }
+
+ public boolean isUsingFormatJson() {
+ return usingFormatJson;
+ }
+
+ public void setUsingFormatJson(boolean usingFormatJson) {
+ this.usingFormatJson = usingFormatJson;
+ }
+
+ public JsonKeyValuePair withUsingFormatJson(boolean usingFormatJson) {
+ this.setUsingFormatJson(usingFormatJson);
+ return this;
+ }
+
+ public String getEncoding() {
+ return encoding;
+ }
+
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ public JsonKeyValuePair withEncoding(String encoding) {
+ this.setEncoding(encoding);
+ return this;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 83 * hash + Objects.hashCode(this.key);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final JsonKeyValuePair other = (JsonKeyValuePair) obj;
+ return Objects.equals(this.key, other.key);
+ }
+
+ public Object getKey() {
+ return key;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public StringBuilder append(StringBuilder builder) {
+ if (isUsingKeyKeyword() && getSeparator() == JsonKeyValuePairSeparator.VALUE) {
+ builder.append("KEY ");
+ }
+ builder.append(getKey());
+
+ if (getValue() != null) {
+ builder.append(getSeparator().getSeparatorString());
+ builder.append(getValue());
+ }
+
+ if (isUsingFormatJson()) {
+ builder.append(" FORMAT JSON");
+ if (encoding != null) {
+ builder.append(" ENCODING ").append(encoding);
+ }
+ }
+
+ return builder;
+ }
+
+ @Override
+ public String toString() {
+ return append(new StringBuilder()).toString();
+ }
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePairSeparator.java b/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePairSeparator.java
new file mode 100644
index 000000000..e4e998aa5
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePairSeparator.java
@@ -0,0 +1,33 @@
+/*-
+ * #%L
+ * JSQLParser library
+ * %%
+ * Copyright (C) 2004 - 2025 JSQLParser
+ * %%
+ * Dual licensed under GNU LGPL 2.1 or Apache License 2.0
+ * #L%
+ */
+package net.sf.jsqlparser.expression;
+
+/**
+ * Describes the string used to separate the key from the value.
+ */
+public enum JsonKeyValuePairSeparator {
+ VALUE(" VALUE "), COLON(":"),
+
+ // Used in MySQL dialect
+ COMMA(","),
+
+ // Is used in case they KeyValuePair has only a key and no value
+ NOT_USED("");
+
+ private final String separator;
+
+ JsonKeyValuePairSeparator(String separator) {
+ this.separator = separator;
+ }
+
+ public String getSeparatorString() {
+ return separator;
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonTableFunction.java b/src/main/java/net/sf/jsqlparser/expression/JsonTableFunction.java
new file mode 100644
index 000000000..5ee166e6f
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/JsonTableFunction.java
@@ -0,0 +1,864 @@
+/*-
+ * #%L
+ * JSQLParser library
+ * %%
+ * Copyright (C) 2004 - 2026 JSQLParser
+ * %%
+ * Dual licensed under GNU LGPL 2.1 or Apache License 2.0
+ * #L%
+ */
+package net.sf.jsqlparser.expression;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
+import net.sf.jsqlparser.statement.create.table.ColDataType;
+
+public class JsonTableFunction extends Function {
+
+ private Expression jsonInputExpression;
+ private Expression jsonPathExpression;
+ private String pathName;
+ private final List passingClauses = new ArrayList<>();
+ private JsonTableColumnsClause columnsClause;
+ private JsonTablePlanClause planClause;
+ private JsonTableOnErrorClause onErrorClause;
+ private JsonTableParsingTypeClause parsingTypeClause;
+ private JsonTableOnEmptyClause onEmptyClause;
+ private boolean formatJson;
+
+ public enum JsonTablePlanOperator {
+ COMMA(", "), INNER(" INNER "), OUTER(" OUTER "), CROSS(" CROSS "), UNION(" UNION ");
+
+ private final String display;
+
+ JsonTablePlanOperator(String display) {
+ this.display = display;
+ }
+
+ public String getDisplay() {
+ return display;
+ }
+ }
+
+ public enum JsonTableOnErrorType {
+ ERROR, NULL, EMPTY, TRUE, FALSE
+ }
+
+ public enum JsonTableOnEmptyType {
+ ERROR, NULL, EMPTY, TRUE, FALSE
+ }
+
+ public enum JsonTableParsingType {
+ STRICT, LAX
+ }
+
+ public static class JsonTablePassingClause extends ASTNodeAccessImpl implements Serializable {
+ private Expression valueExpression;
+ private String parameterName;
+
+ public JsonTablePassingClause() {}
+
+ public JsonTablePassingClause(Expression valueExpression, String parameterName) {
+ this.valueExpression = valueExpression;
+ this.parameterName = parameterName;
+ }
+
+ public Expression getValueExpression() {
+ return valueExpression;
+ }
+
+ public JsonTablePassingClause setValueExpression(Expression valueExpression) {
+ this.valueExpression = valueExpression;
+ return this;
+ }
+
+ public String getParameterName() {
+ return parameterName;
+ }
+
+ public JsonTablePassingClause setParameterName(String parameterName) {
+ this.parameterName = parameterName;
+ return this;
+ }
+
+ public void collectExpressions(List expressions) {
+ if (valueExpression != null) {
+ expressions.add(valueExpression);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return valueExpression + " AS " + parameterName;
+ }
+ }
+
+ public static class JsonTableWrapperClause extends ASTNodeAccessImpl implements Serializable {
+ private boolean beforePathExpression;
+ private JsonFunction.JsonWrapperType wrapperType;
+ private JsonFunction.JsonWrapperMode wrapperMode;
+ private boolean array;
+
+ /**
+ * Creates a wrapper clause. Depending on the dialect, this clause can come before or after
+ * the PATH expression.
+ *
+ * - Trino: after PATH
+ * - Oracle: before PATH
+ *
+ *
+ * @param beforePathExpression A flag to determine wether the clause is rendered before or
+ * after the PATH expression
+ */
+ public JsonTableWrapperClause(boolean beforePathExpression) {
+ this.beforePathExpression = beforePathExpression;
+ }
+
+ public boolean isBeforePathExpression() {
+ return beforePathExpression;
+ }
+
+ public JsonFunction.JsonWrapperType getWrapperType() {
+ return wrapperType;
+ }
+
+ public JsonTableWrapperClause setWrapperType(JsonFunction.JsonWrapperType wrapperType) {
+ this.wrapperType = wrapperType;
+ return this;
+ }
+
+ public JsonFunction.JsonWrapperMode getWrapperMode() {
+ return wrapperMode;
+ }
+
+ public JsonTableWrapperClause setWrapperMode(JsonFunction.JsonWrapperMode wrapperMode) {
+ this.wrapperMode = wrapperMode;
+ return this;
+ }
+
+ public boolean isArray() {
+ return array;
+ }
+
+ public JsonTableWrapperClause setArray(boolean array) {
+ this.array = array;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(wrapperType);
+ if (wrapperMode != null) {
+ builder.append(" ").append(wrapperMode);
+ }
+ if (array) {
+ builder.append(" ARRAY");
+ }
+ builder.append(" WRAPPER");
+ return builder.toString();
+ }
+ }
+
+ public static class JsonTableQuotesClause extends ASTNodeAccessImpl implements Serializable {
+ private JsonFunction.JsonQuotesType quotesType;
+ private boolean onScalarString;
+
+ public JsonFunction.JsonQuotesType getQuotesType() {
+ return quotesType;
+ }
+
+ public JsonTableQuotesClause setQuotesType(JsonFunction.JsonQuotesType quotesType) {
+ this.quotesType = quotesType;
+ return this;
+ }
+
+ public boolean isOnScalarString() {
+ return onScalarString;
+ }
+
+ public JsonTableQuotesClause setOnScalarString(boolean onScalarString) {
+ this.onScalarString = onScalarString;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(quotesType).append(" QUOTES");
+ if (onScalarString) {
+ builder.append(" ON SCALAR STRING");
+ }
+ return builder.toString();
+ }
+ }
+
+ public static class JsonTableOnErrorClause extends ASTNodeAccessImpl implements Serializable {
+ private JsonTableOnErrorType type;
+ private boolean beforeColumns = true;
+
+ public JsonTableOnErrorClause(boolean beforeColumns) {
+ this.beforeColumns = beforeColumns;
+ }
+
+ public boolean isBeforeColumns() {
+ return beforeColumns;
+ }
+
+ public JsonTableOnErrorType getType() {
+ return type;
+ }
+
+ public JsonTableOnErrorClause setType(JsonTableOnErrorType type) {
+ this.type = type;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return type + " ON ERROR";
+ }
+ }
+
+ public static class JsonTableOnEmptyClause extends ASTNodeAccessImpl implements Serializable {
+ private JsonTableOnEmptyType type;
+
+ public JsonTableOnEmptyType getType() {
+ return type;
+ }
+
+ public JsonTableOnEmptyClause setType(JsonTableOnEmptyType type) {
+ this.type = type;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return type + " ON EMPTY";
+ }
+ }
+
+ public static class JsonTableParsingTypeClause extends ASTNodeAccessImpl
+ implements Serializable {
+ private JsonTableParsingType type;
+
+ public JsonTableParsingType getType() {
+ return type;
+ }
+
+ public JsonTableParsingTypeClause setType(JsonTableParsingType type) {
+ this.type = type;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "TYPE(" + type + ")";
+ }
+ }
+
+ public static class JsonTablePlanTerm extends ASTNodeAccessImpl implements Serializable {
+ private JsonTablePlanExpression nestedPlanExpression;
+ private String name;
+ private Expression expression;
+
+ public JsonTablePlanExpression getNestedPlanExpression() {
+ return nestedPlanExpression;
+ }
+
+ public JsonTablePlanTerm setNestedPlanExpression(
+ JsonTablePlanExpression nestedPlanExpression) {
+ this.nestedPlanExpression = nestedPlanExpression;
+ return this;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public JsonTablePlanTerm setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Expression getExpression() {
+ return expression;
+ }
+
+ public JsonTablePlanTerm setExpression(Expression expression) {
+ this.expression = expression;
+ return this;
+ }
+
+ public void collectExpressions(List expressions) {
+ if (expression != null) {
+ expressions.add(expression);
+ }
+ if (nestedPlanExpression != null) {
+ nestedPlanExpression.collectExpressions(expressions);
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (nestedPlanExpression != null) {
+ return "(" + nestedPlanExpression + ")";
+ }
+ if (name != null) {
+ return name;
+ }
+ return expression != null ? expression.toString() : "";
+ }
+ }
+
+ public static class JsonTablePlanExpression extends ASTNodeAccessImpl implements Serializable {
+ private final List terms = new ArrayList<>();
+ private final List operators = new ArrayList<>();
+
+ public List getTerms() {
+ return terms;
+ }
+
+ public JsonTablePlanExpression addTerm(JsonTablePlanTerm term) {
+ terms.add(term);
+ return this;
+ }
+
+ public List getOperators() {
+ return operators;
+ }
+
+ public JsonTablePlanExpression addOperator(JsonTablePlanOperator operator) {
+ operators.add(operator);
+ return this;
+ }
+
+ public void collectExpressions(List expressions) {
+ for (JsonTablePlanTerm term : terms) {
+ if (term != null) {
+ term.collectExpressions(expressions);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ if (!terms.isEmpty()) {
+ builder.append(terms.get(0));
+ }
+ for (int i = 0; i < operators.size() && i + 1 < terms.size(); i++) {
+ builder.append(operators.get(i).getDisplay()).append(terms.get(i + 1));
+ }
+ return builder.toString();
+ }
+ }
+
+ public static class JsonTablePlanClause extends ASTNodeAccessImpl implements Serializable {
+ private boolean defaultPlan;
+ private JsonTablePlanExpression planExpression;
+
+ public boolean isDefaultPlan() {
+ return defaultPlan;
+ }
+
+ public JsonTablePlanClause setDefaultPlan(boolean defaultPlan) {
+ this.defaultPlan = defaultPlan;
+ return this;
+ }
+
+ public JsonTablePlanExpression getPlanExpression() {
+ return planExpression;
+ }
+
+ public JsonTablePlanClause setPlanExpression(JsonTablePlanExpression planExpression) {
+ this.planExpression = planExpression;
+ return this;
+ }
+
+ public void collectExpressions(List expressions) {
+ if (planExpression != null) {
+ planExpression.collectExpressions(expressions);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder("PLAN");
+ if (defaultPlan) {
+ builder.append(" DEFAULT");
+ }
+ builder.append(" (").append(planExpression).append(")");
+ return builder.toString();
+ }
+ }
+
+ public abstract static class JsonTableColumnDefinition extends ASTNodeAccessImpl
+ implements Serializable {
+ public abstract void collectExpressions(List expressions);
+ }
+
+ public static class JsonTableNestedColumnDefinition extends JsonTableColumnDefinition {
+ private boolean pathKeyword;
+ private Expression pathExpression;
+ private String pathName;
+ private JsonTableColumnsClause columnsClause;
+
+ public boolean isPathKeyword() {
+ return pathKeyword;
+ }
+
+ public JsonTableNestedColumnDefinition setPathKeyword(boolean pathKeyword) {
+ this.pathKeyword = pathKeyword;
+ return this;
+ }
+
+ public Expression getPathExpression() {
+ return pathExpression;
+ }
+
+ public JsonTableNestedColumnDefinition setPathExpression(Expression pathExpression) {
+ this.pathExpression = pathExpression;
+ return this;
+ }
+
+ public String getPathName() {
+ return pathName;
+ }
+
+ public JsonTableNestedColumnDefinition setPathName(String pathName) {
+ this.pathName = pathName;
+ return this;
+ }
+
+ public JsonTableColumnsClause getColumnsClause() {
+ return columnsClause;
+ }
+
+ public JsonTableNestedColumnDefinition setColumnsClause(
+ JsonTableColumnsClause columnsClause) {
+ this.columnsClause = columnsClause;
+ return this;
+ }
+
+ @Override
+ public void collectExpressions(List expressions) {
+ if (pathExpression != null) {
+ expressions.add(pathExpression);
+ }
+ if (columnsClause != null) {
+ columnsClause.collectExpressions(expressions);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder("NESTED");
+ if (pathKeyword) {
+ builder.append(" PATH");
+ }
+ builder.append(" ").append(pathExpression);
+ if (pathName != null) {
+ builder.append(" AS ").append(pathName);
+ }
+ builder.append(" ").append(columnsClause);
+ return builder.toString();
+ }
+ }
+
+ public static class JsonTableValueColumnDefinition extends JsonTableColumnDefinition {
+ private String columnName;
+ private boolean forOrdinality;
+ private ColDataType dataType;
+ private boolean formatJson;
+ private boolean exists;
+ private boolean onEmptyAfterOnError;
+ private String encoding;
+ private Expression pathExpression;
+ private JsonTableWrapperClause wrapperClause;
+ private JsonTableQuotesClause quotesClause;
+ private JsonFunction.JsonOnResponseBehavior onEmptyBehavior;
+ private JsonFunction.JsonOnResponseBehavior onErrorBehavior;
+ private JsonFunction.ScalarsType scalarsType;
+
+ public String getColumnName() {
+ return columnName;
+ }
+
+ public JsonTableValueColumnDefinition setColumnName(String columnName) {
+ this.columnName = columnName;
+ return this;
+ }
+
+ public boolean isExists() {
+ return exists;
+ }
+
+ public JsonTableValueColumnDefinition setExistsKeyword(boolean exists) {
+ this.exists = exists;
+ return this;
+ }
+
+ public JsonTableValueColumnDefinition setOnEmptyAfterOnError(boolean b) {
+ this.onEmptyAfterOnError = b;
+ return this;
+ }
+
+ public boolean isForOrdinality() {
+ return forOrdinality;
+ }
+
+ public JsonTableValueColumnDefinition setForOrdinality(boolean forOrdinality) {
+ this.forOrdinality = forOrdinality;
+ return this;
+ }
+
+ public ColDataType getDataType() {
+ return dataType;
+ }
+
+ public JsonTableValueColumnDefinition setDataType(ColDataType dataType) {
+ this.dataType = dataType;
+ return this;
+ }
+
+ public boolean isFormatJson() {
+ return formatJson;
+ }
+
+ public JsonTableValueColumnDefinition setFormatJson(boolean formatJson) {
+ this.formatJson = formatJson;
+ return this;
+ }
+
+ public String getEncoding() {
+ return encoding;
+ }
+
+ public JsonTableValueColumnDefinition setEncoding(String encoding) {
+ this.encoding = encoding;
+ return this;
+ }
+
+ public Expression getPathExpression() {
+ return pathExpression;
+ }
+
+ public JsonTableValueColumnDefinition setPathExpression(Expression pathExpression) {
+ this.pathExpression = pathExpression;
+ return this;
+ }
+
+ public JsonTableWrapperClause getWrapperClause() {
+ return wrapperClause;
+ }
+
+ public JsonTableValueColumnDefinition setWrapperClause(
+ JsonTableWrapperClause wrapperClause) {
+ this.wrapperClause = wrapperClause;
+ return this;
+ }
+
+ public JsonTableQuotesClause getQuotesClause() {
+ return quotesClause;
+ }
+
+ public JsonTableValueColumnDefinition setQuotesClause(JsonTableQuotesClause quotesClause) {
+ this.quotesClause = quotesClause;
+ return this;
+ }
+
+ public JsonFunction.JsonOnResponseBehavior getOnEmptyBehavior() {
+ return onEmptyBehavior;
+ }
+
+ public JsonTableValueColumnDefinition setOnEmptyBehavior(
+ JsonFunction.JsonOnResponseBehavior onEmptyBehavior) {
+ this.onEmptyBehavior = onEmptyBehavior;
+ return this;
+ }
+
+ public JsonFunction.JsonOnResponseBehavior getOnErrorBehavior() {
+ return onErrorBehavior;
+ }
+
+ public JsonTableValueColumnDefinition setOnErrorBehavior(
+ JsonFunction.JsonOnResponseBehavior onErrorBehavior) {
+ this.onErrorBehavior = onErrorBehavior;
+ return this;
+ }
+
+ public void setScalarsType(JsonFunction.ScalarsType scalarsType) {
+ this.scalarsType = scalarsType;
+ }
+
+ public JsonFunction.ScalarsType getScalarsType() {
+ return scalarsType;
+ }
+
+ @Override
+ public void collectExpressions(List expressions) {
+ if (pathExpression != null) {
+ expressions.add(pathExpression);
+ }
+ if (onEmptyBehavior != null && onEmptyBehavior.getExpression() != null) {
+ expressions.add(onEmptyBehavior.getExpression());
+ }
+ if (onErrorBehavior != null && onErrorBehavior.getExpression() != null) {
+ expressions.add(onErrorBehavior.getExpression());
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder(columnName);
+ if (forOrdinality) {
+ builder.append(" FOR ORDINALITY");
+ return builder.toString();
+ }
+ if (exists) {
+ builder.append(" EXISTS");
+ }
+ if (dataType != null) {
+ builder.append(" ").append(dataType);
+ }
+ if (formatJson) {
+ builder.append(" FORMAT JSON");
+ if (encoding != null) {
+ builder.append(" ENCODING ").append(encoding);
+ }
+ }
+ if (scalarsType != null) {
+ builder.append(" ");
+ builder.append(scalarsType);
+ builder.append(" SCALARS");
+ }
+ if (wrapperClause != null && wrapperClause.isBeforePathExpression()) {
+ builder.append(" ").append(wrapperClause);
+ }
+ if (pathExpression != null) {
+ builder.append(" PATH ").append(pathExpression);
+ }
+ if (wrapperClause != null && !wrapperClause.isBeforePathExpression()) {
+ builder.append(" ").append(wrapperClause);
+ }
+ if (quotesClause != null) {
+ builder.append(" ").append(quotesClause);
+ }
+ if (onEmptyBehavior != null && !onEmptyAfterOnError) {
+ builder.append(" ").append(onEmptyBehavior).append(" ON EMPTY");
+ }
+ if (onErrorBehavior != null) {
+ builder.append(" ").append(onErrorBehavior).append(" ON ERROR");
+ }
+ if (onEmptyBehavior != null && onEmptyAfterOnError) {
+ builder.append(" ").append(onEmptyBehavior).append(" ON EMPTY");
+ }
+ return builder.toString();
+ }
+ }
+
+ public static class JsonTableColumnsClause extends ASTNodeAccessImpl implements Serializable {
+ private final List columnDefinitions = new ArrayList<>();
+
+ public List getColumnDefinitions() {
+ return columnDefinitions;
+ }
+
+ public JsonTableColumnsClause addColumnDefinition(
+ JsonTableColumnDefinition columnDefinition) {
+ columnDefinitions.add(columnDefinition);
+ return this;
+ }
+
+ public void collectExpressions(List expressions) {
+ for (JsonTableColumnDefinition columnDefinition : columnDefinitions) {
+ if (columnDefinition != null) {
+ columnDefinition.collectExpressions(expressions);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder("COLUMNS (");
+ boolean first = true;
+ for (JsonTableColumnDefinition columnDefinition : columnDefinitions) {
+ if (!first) {
+ builder.append(", ");
+ }
+ builder.append(columnDefinition);
+ first = false;
+ }
+ builder.append(")");
+ return builder.toString();
+ }
+ }
+
+ public JsonTableFunction() {
+ setName("JSON_TABLE");
+ }
+
+ public boolean getFormatJson() {
+ return formatJson;
+ }
+
+ public JsonTableFunction setFormatJson(boolean formatJson) {
+ this.formatJson = formatJson;
+ return this;
+ }
+
+ public Expression getJsonInputExpression() {
+ return jsonInputExpression;
+ }
+
+ public JsonTableFunction setJsonInputExpression(Expression jsonInputExpression) {
+ this.jsonInputExpression = jsonInputExpression;
+ return this;
+ }
+
+ public Expression getJsonPathExpression() {
+ return jsonPathExpression;
+ }
+
+ public JsonTableFunction setJsonPathExpression(Expression jsonPathExpression) {
+ this.jsonPathExpression = jsonPathExpression;
+ return this;
+ }
+
+ public String getPathName() {
+ return pathName;
+ }
+
+ public JsonTableFunction setPathName(String pathName) {
+ this.pathName = pathName;
+ return this;
+ }
+
+ public List getPassingClauses() {
+ return passingClauses;
+ }
+
+ public JsonTableFunction addPassingClause(JsonTablePassingClause passingClause) {
+ passingClauses.add(Objects.requireNonNull(passingClause, "passingClause"));
+ return this;
+ }
+
+ public JsonTableColumnsClause getColumnsClause() {
+ return columnsClause;
+ }
+
+ public JsonTableFunction setColumnsClause(JsonTableColumnsClause columnsClause) {
+ this.columnsClause = columnsClause;
+ return this;
+ }
+
+ public JsonTablePlanClause getPlanClause() {
+ return planClause;
+ }
+
+ public JsonTableFunction setPlanClause(JsonTablePlanClause planClause) {
+ this.planClause = planClause;
+ return this;
+ }
+
+ public JsonTableOnErrorClause getOnErrorClause() {
+ return onErrorClause;
+ }
+
+ public JsonTableFunction setOnErrorClause(JsonTableOnErrorClause onErrorClause) {
+ this.onErrorClause = onErrorClause;
+ return this;
+ }
+
+ public JsonTableParsingTypeClause getParsingTypeClause() {
+ return parsingTypeClause;
+ }
+
+ public JsonTableFunction setParsingTypeClause(JsonTableParsingTypeClause parsingTypeClause) {
+ this.parsingTypeClause = parsingTypeClause;
+ return this;
+ }
+
+ public JsonTableOnEmptyClause getOnEmptyClause() {
+ return onEmptyClause;
+ }
+
+ public JsonTableFunction setOnEmptyClause(JsonTableOnEmptyClause onEmptyClause) {
+ this.onEmptyClause = onEmptyClause;
+ return this;
+ }
+
+ public List getAllExpressions() {
+ List expressions = new ArrayList<>();
+ if (jsonInputExpression != null) {
+ expressions.add(jsonInputExpression);
+ }
+ if (jsonPathExpression != null) {
+ expressions.add(jsonPathExpression);
+ }
+ for (JsonTablePassingClause passingClause : passingClauses) {
+ passingClause.collectExpressions(expressions);
+ }
+ if (columnsClause != null) {
+ columnsClause.collectExpressions(expressions);
+ }
+ if (planClause != null) {
+ planClause.collectExpressions(expressions);
+ }
+ return expressions;
+ }
+
+ @Override
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder("JSON_TABLE(");
+ builder.append(jsonInputExpression);
+ if (formatJson) {
+ builder.append(" FORMAT JSON");
+ }
+ if (jsonPathExpression != null) {
+ builder.append(", ").append(jsonPathExpression);
+ }
+ if (pathName != null) {
+ builder.append(" AS ").append(pathName);
+ }
+ if (!passingClauses.isEmpty()) {
+ builder.append(" PASSING ");
+ boolean first = true;
+ for (JsonTablePassingClause passingClause : passingClauses) {
+ if (!first) {
+ builder.append(", ");
+ }
+ builder.append(passingClause);
+ first = false;
+ }
+ }
+ if (onErrorClause != null && onErrorClause.isBeforeColumns()) {
+ builder.append(" ").append(onErrorClause);
+ }
+ if (parsingTypeClause != null) {
+ builder.append(" ").append(parsingTypeClause);
+ }
+ if (onEmptyClause != null) {
+ builder.append(" ").append(onEmptyClause);
+ }
+ builder.append(" ").append(columnsClause);
+ if (planClause != null) {
+ builder.append(" ").append(planClause);
+ }
+ if (onErrorClause != null && !onErrorClause.isBeforeColumns()) {
+ builder.append(" ").append(onErrorClause);
+ }
+ builder.append(")");
+ return builder.toString();
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/KeepExpression.java b/src/main/java/net/sf/jsqlparser/expression/KeepExpression.java
index 2712a0e46..b8e493244 100644
--- a/src/main/java/net/sf/jsqlparser/expression/KeepExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/KeepExpression.java
@@ -14,6 +14,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.statement.select.OrderByElement;
@@ -24,8 +25,8 @@ public class KeepExpression extends ASTNodeAccessImpl implements Expression {
private boolean first = false;
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public List getOrderByElements() {
@@ -94,13 +95,15 @@ public KeepExpression withFirst(boolean first) {
}
public KeepExpression addOrderByElements(OrderByElement... orderByElements) {
- List collection = Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new);
+ List collection =
+ Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new);
Collections.addAll(collection, orderByElements);
return this.withOrderByElements(collection);
}
public KeepExpression addOrderByElements(Collection extends OrderByElement> orderByElements) {
- List collection = Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new);
+ List collection =
+ Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new);
collection.addAll(orderByElements);
return this.withOrderByElements(collection);
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/KeyExpression.java b/src/main/java/net/sf/jsqlparser/expression/KeyExpression.java
new file mode 100644
index 000000000..2bb063875
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/KeyExpression.java
@@ -0,0 +1,44 @@
+/*-
+ * #%L
+ * JSQLParser library
+ * %%
+ * Copyright (C) 2004 - 2026 JSQLParser
+ * %%
+ * Dual licensed under GNU LGPL 2.1 or Apache License 2.0
+ * #L%
+ */
+package net.sf.jsqlparser.expression;
+
+import java.util.Objects;
+import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
+
+/**
+ * Dialect specific expression for constructs such as {@code KEY chain.entity}.
+ */
+public class KeyExpression extends ASTNodeAccessImpl implements Expression {
+ private final Expression expression;
+
+ public KeyExpression(Expression expression) {
+ this.expression = Objects.requireNonNull(expression,
+ "The EXPRESSION of the KEY expression must not be null");
+ }
+
+ 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("KEY ").append(expression);
+ return builder;
+ }
+
+ @Override
+ public String toString() {
+ return appendTo(new StringBuilder()).toString();
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java b/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java
index a9207b214..e2819060f 100644
--- a/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java
@@ -9,9 +9,11 @@
*/
package net.sf.jsqlparser.expression;
+import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
public class LambdaExpression extends ASTNodeAccessImpl implements Expression {
@@ -19,7 +21,7 @@ public class LambdaExpression extends ASTNodeAccessImpl implements Expression {
private Expression expression;
public LambdaExpression(String identifier, Expression expression) {
- this.identifiers = Arrays.asList(identifier);
+ this.identifiers = Collections.singletonList(identifier);
this.expression = expression;
}
@@ -28,6 +30,15 @@ public LambdaExpression(List identifiers, Expression expression) {
this.expression = expression;
}
+ public static LambdaExpression from(ExpressionList extends Expression> expressionList,
+ Expression expression) {
+ List identifiers = new ArrayList<>(expressionList.size());
+ for (Expression variable : expressionList) {
+ identifiers.add(variable.toString());
+ }
+ return new LambdaExpression(identifiers, expression);
+ }
+
public List getIdentifiers() {
return identifiers;
}
@@ -66,7 +77,7 @@ public String toString() {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/LongValue.java b/src/main/java/net/sf/jsqlparser/expression/LongValue.java
index 730a8871e..eeba186cc 100644
--- a/src/main/java/net/sf/jsqlparser/expression/LongValue.java
+++ b/src/main/java/net/sf/jsqlparser/expression/LongValue.java
@@ -41,22 +41,22 @@ public LongValue(long value) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public long getValue() {
return Long.parseLong(stringValue);
}
- public BigInteger getBigIntegerValue() {
- return new BigInteger(stringValue);
- }
-
public void setValue(long d) {
stringValue = String.valueOf(d);
}
+ public BigInteger getBigIntegerValue() {
+ return new BigInteger(stringValue);
+ }
+
public LongValue withValue(long d) {
setValue(d);
return this;
diff --git a/src/main/java/net/sf/jsqlparser/expression/LowExpression.java b/src/main/java/net/sf/jsqlparser/expression/LowExpression.java
new file mode 100644
index 000000000..2d2882a53
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/LowExpression.java
@@ -0,0 +1,42 @@
+/*-
+ * #%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 LowExpression extends ASTNodeAccessImpl implements Expression {
+ private Expression expression;
+
+ public LowExpression() {
+ // empty constructor
+ }
+
+ public LowExpression(Expression expression) {
+ this.expression = expression;
+ }
+
+ @Override
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
+ }
+
+ public Expression getExpression() {
+ return expression;
+ }
+
+ public void setExpression(Expression expression) {
+ this.expression = expression;
+ }
+
+ @Override
+ public String toString() {
+ return "LOW " + expression.toString();
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/MySQLGroupConcat.java b/src/main/java/net/sf/jsqlparser/expression/MySQLGroupConcat.java
index 49161bbee..aa4a53357 100644
--- a/src/main/java/net/sf/jsqlparser/expression/MySQLGroupConcat.java
+++ b/src/main/java/net/sf/jsqlparser/expression/MySQLGroupConcat.java
@@ -59,8 +59,8 @@ public void setSeparator(String separator) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/NextValExpression.java b/src/main/java/net/sf/jsqlparser/expression/NextValExpression.java
index 4838bbcf4..a56723851 100644
--- a/src/main/java/net/sf/jsqlparser/expression/NextValExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/NextValExpression.java
@@ -1,8 +1,8 @@
-/* -
+/*-
* #%L
* JSQLParser library
* %%
- * Copyright (C) 2004 - 2019 JSQLParser
+ * Copyright (C) 2004 - 2024 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
@@ -11,11 +11,13 @@
import java.util.List;
import java.util.regex.Pattern;
+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
public class NextValExpression extends ASTNodeAccessImpl implements Expression {
- public static final Pattern NEXT_VALUE_PATTERN = Pattern.compile("NEXT\\s+VALUE\\s+FOR", Pattern.CASE_INSENSITIVE);
+ public static final Pattern NEXT_VALUE_PATTERN =
+ Pattern.compile("NEXT\\s+VALUE\\s+FOR", Pattern.CASE_INSENSITIVE);
private final List nameList;
private boolean usingNextValueFor = false;
@@ -63,7 +65,7 @@ public String toString() {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/NotExpression.java b/src/main/java/net/sf/jsqlparser/expression/NotExpression.java
index d61ae2bb9..bb2769fdd 100644
--- a/src/main/java/net/sf/jsqlparser/expression/NotExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/NotExpression.java
@@ -42,8 +42,8 @@ public final void setExpression(Expression expression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/NullValue.java b/src/main/java/net/sf/jsqlparser/expression/NullValue.java
index b6397030f..fb096eff6 100644
--- a/src/main/java/net/sf/jsqlparser/expression/NullValue.java
+++ b/src/main/java/net/sf/jsqlparser/expression/NullValue.java
@@ -14,8 +14,8 @@
public class NullValue extends ASTNodeAccessImpl implements Expression {
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/NumericBind.java b/src/main/java/net/sf/jsqlparser/expression/NumericBind.java
index 8f5ac4088..f38ff15d4 100644
--- a/src/main/java/net/sf/jsqlparser/expression/NumericBind.java
+++ b/src/main/java/net/sf/jsqlparser/expression/NumericBind.java
@@ -24,8 +24,8 @@ public void setBindId(int bindId) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/OracleHierarchicalExpression.java b/src/main/java/net/sf/jsqlparser/expression/OracleHierarchicalExpression.java
index a3644e441..693128d03 100644
--- a/src/main/java/net/sf/jsqlparser/expression/OracleHierarchicalExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/OracleHierarchicalExpression.java
@@ -13,10 +13,10 @@
public class OracleHierarchicalExpression extends ASTNodeAccessImpl implements Expression {
+ boolean connectFirst = false;
private Expression startExpression;
private Expression connectExpression;
private boolean noCycle = false;
- boolean connectFirst = false;
public Expression getStartExpression() {
return startExpression;
@@ -51,8 +51,8 @@ public void setConnectFirst(boolean connectFirst) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
@@ -65,11 +65,11 @@ public String toString() {
}
b.append(connectExpression.toString());
if (startExpression != null) {
- b.append(" START WITH ").append(startExpression.toString());
+ b.append(" START WITH ").append(startExpression);
}
} else {
if (startExpression != null) {
- b.append(" START WITH ").append(startExpression.toString());
+ b.append(" START WITH ").append(startExpression);
}
b.append(" CONNECT BY ");
if (isNoCycle()) {
diff --git a/src/main/java/net/sf/jsqlparser/expression/OracleHint.java b/src/main/java/net/sf/jsqlparser/expression/OracleHint.java
index c229e880e..4ab164f98 100644
--- a/src/main/java/net/sf/jsqlparser/expression/OracleHint.java
+++ b/src/main/java/net/sf/jsqlparser/expression/OracleHint.java
@@ -24,7 +24,7 @@ public class OracleHint extends ASTNodeAccessImpl implements Expression {
private static final Pattern SINGLE_LINE = Pattern.compile("--\\+ *([^ ].*[^ ])");
private static final Pattern MULTI_LINE =
- Pattern.compile("\\/\\*\\+ *([^ ].*[^ ]) *\\*+\\/", Pattern.MULTILINE | Pattern.DOTALL);
+ Pattern.compile("/\\*\\+ *([^ ].*[^ ]) *\\*+/", Pattern.MULTILINE | Pattern.DOTALL);
private String value;
private boolean singleLine = false;
@@ -33,6 +33,17 @@ public static boolean isHintMatch(String comment) {
return SINGLE_LINE.matcher(comment).find() || MULTI_LINE.matcher(comment).find();
}
+ public static OracleHint getHintFromSelectBody(Select selectBody) {
+
+ if (selectBody instanceof PlainSelect) {
+ return ((PlainSelect) selectBody).getOracleHint();
+ } else if (selectBody instanceof ParenthesedSelect) {
+ return getHintFromSelectBody(((ParenthesedSelect) selectBody).getSelect());
+ } else {
+ return null;
+ }
+ }
+
public final void setComment(String comment) {
Matcher m;
m = SINGLE_LINE.matcher(comment);
@@ -65,8 +76,8 @@ public void setSingleLine(boolean singleLine) {
}
@Override
- public void accept(ExpressionVisitor visitor) {
- visitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
@@ -87,15 +98,4 @@ public OracleHint withSingleLine(boolean singleLine) {
this.setSingleLine(singleLine);
return this;
}
-
- public static OracleHint getHintFromSelectBody(Select selectBody) {
-
- if (selectBody instanceof PlainSelect) {
- return ((PlainSelect) selectBody).getOracleHint();
- } else if (selectBody instanceof ParenthesedSelect) {
- return getHintFromSelectBody(((ParenthesedSelect) selectBody).getSelect());
- } else {
- return null;
- }
- }
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/OracleNamedFunctionParameter.java b/src/main/java/net/sf/jsqlparser/expression/OracleNamedFunctionParameter.java
index 51a7a433c..0dd76b5f6 100644
--- a/src/main/java/net/sf/jsqlparser/expression/OracleNamedFunctionParameter.java
+++ b/src/main/java/net/sf/jsqlparser/expression/OracleNamedFunctionParameter.java
@@ -10,10 +10,10 @@
package net.sf.jsqlparser.expression;
import java.util.Objects;
+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
/**
- *
* @author Andreas Reichel
*/
public class OracleNamedFunctionParameter extends ASTNodeAccessImpl implements Expression {
@@ -21,8 +21,10 @@ public class OracleNamedFunctionParameter extends ASTNodeAccessImpl implements E
private final Expression expression;
public OracleNamedFunctionParameter(String name, Expression expression) {
- this.name = Objects.requireNonNull(name, "The NAME of the OracleNamedFunctionParameter must not be null.");
- this.expression = Objects.requireNonNull(expression, "The EXPRESSION of the OracleNamedFunctionParameter must not be null.");
+ this.name = Objects.requireNonNull(name,
+ "The NAME of the OracleNamedFunctionParameter must not be null.");
+ this.expression = Objects.requireNonNull(expression,
+ "The EXPRESSION of the OracleNamedFunctionParameter must not be null.");
}
public String getName() {
@@ -34,18 +36,18 @@ public Expression getExpression() {
}
@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(name)
- .append(" => ")
- .append(expression);
-
+ .append(" => ")
+ .append(expression);
+
return builder;
}
-
+
@Override
public String toString() {
return appendTo(new StringBuilder()).toString();
diff --git a/src/main/java/net/sf/jsqlparser/expression/OrderByClause.java b/src/main/java/net/sf/jsqlparser/expression/OrderByClause.java
index 7c71ddfa0..fbf21de87 100644
--- a/src/main/java/net/sf/jsqlparser/expression/OrderByClause.java
+++ b/src/main/java/net/sf/jsqlparser/expression/OrderByClause.java
@@ -15,6 +15,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
+
import net.sf.jsqlparser.statement.select.OrderByElement;
public class OrderByClause implements Serializable {
@@ -46,13 +47,15 @@ public OrderByClause withOrderByElements(List orderByElements) {
}
public OrderByClause addOrderByElements(OrderByElement... orderByElements) {
- List collection = Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new);
+ List collection =
+ Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new);
Collections.addAll(collection, orderByElements);
return this.withOrderByElements(collection);
}
public OrderByClause addOrderByElements(Collection extends OrderByElement> orderByElements) {
- List collection = Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new);
+ List collection =
+ Optional.ofNullable(getOrderByElements()).orElseGet(ArrayList::new);
collection.addAll(orderByElements);
return this.withOrderByElements(collection);
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/OverlapsCondition.java b/src/main/java/net/sf/jsqlparser/expression/OverlapsCondition.java
index f9e41b4bc..09ccd6183 100644
--- a/src/main/java/net/sf/jsqlparser/expression/OverlapsCondition.java
+++ b/src/main/java/net/sf/jsqlparser/expression/OverlapsCondition.java
@@ -12,36 +12,30 @@
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
-public class OverlapsCondition extends ASTNodeAccessImpl implements Expression{
+public class OverlapsCondition extends ASTNodeAccessImpl implements Expression {
+ private final ExpressionList> left;
+ private final ExpressionList> right;
-
- private ExpressionList left;
- private ExpressionList right;
-
-
- public OverlapsCondition(ExpressionList left, ExpressionList right) {
+ public OverlapsCondition(ExpressionList> left, ExpressionList> right) {
this.left = left;
this.right = right;
}
- public ExpressionList getLeft() {
+ public ExpressionList> getLeft() {
return left;
}
- public ExpressionList getRight() {
+ public ExpressionList> getRight() {
return right;
}
@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 String.format("%s OVERLAPS %s"
- , left.toString()
- , right.toString()
- );
+ return String.format("%s OVERLAPS %s", left.toString(), right.toString());
}
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/PartitionByClause.java b/src/main/java/net/sf/jsqlparser/expression/PartitionByClause.java
index 0b0f70663..6ad41e994 100644
--- a/src/main/java/net/sf/jsqlparser/expression/PartitionByClause.java
+++ b/src/main/java/net/sf/jsqlparser/expression/PartitionByClause.java
@@ -14,37 +14,51 @@
import java.io.Serializable;
-public class PartitionByClause implements Serializable {
- ExpressionList partitionExpressionList;
+public class PartitionByClause extends ExpressionList implements Serializable {
boolean brackets = false;
- public ExpressionList getPartitionExpressionList() {
- return partitionExpressionList;
+ @Deprecated
+ public ExpressionList getPartitionExpressionList() {
+ return this;
}
-
- public void setPartitionExpressionList(ExpressionList partitionExpressionList) {
+
+ @Deprecated
+ public void setPartitionExpressionList(ExpressionList partitionExpressionList) {
setPartitionExpressionList(partitionExpressionList, false);
}
- public void setPartitionExpressionList(ExpressionList partitionExpressionList, boolean brackets) {
- this.partitionExpressionList = partitionExpressionList;
+ @Deprecated
+ public void setPartitionExpressionList(ExpressionList partitionExpressionList,
+ boolean brackets) {
+ setExpressions(partitionExpressionList, brackets);
+ }
+
+ public PartitionByClause setExpressions(ExpressionList partitionExpressionList,
+ boolean brackets) {
+ clear();
+ if (partitionExpressionList != null) {
+ addAll(partitionExpressionList);
+ }
this.brackets = brackets;
+ return this;
}
public void toStringPartitionBy(StringBuilder b) {
- if (partitionExpressionList != null && !partitionExpressionList.getExpressions().isEmpty()) {
+ if (!isEmpty()) {
b.append("PARTITION BY ");
- b.append(PlainSelect.
- getStringList(partitionExpressionList.getExpressions(), true, brackets));
+ b.append(PlainSelect.getStringList(this, true,
+ brackets));
b.append(" ");
}
}
-
+
public boolean isBrackets() {
return brackets;
}
- public PartitionByClause withPartitionExpressionList(ExpressionList partitionExpressionList) {
+ @Deprecated
+ public PartitionByClause withPartitionExpressionList(
+ ExpressionList partitionExpressionList) {
this.setPartitionExpressionList(partitionExpressionList);
return this;
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/PostgresNamedFunctionParameter.java b/src/main/java/net/sf/jsqlparser/expression/PostgresNamedFunctionParameter.java
new file mode 100644
index 000000000..573ad60f2
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/PostgresNamedFunctionParameter.java
@@ -0,0 +1,55 @@
+/*-
+ * #%L
+ * JSQLParser library
+ * %%
+ * Copyright (C) 2004 - 2021 JSQLParser
+ * %%
+ * Dual licensed under GNU LGPL 2.1 or Apache License 2.0
+ * #L%
+ */
+package net.sf.jsqlparser.expression;
+
+import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
+
+import java.util.Objects;
+
+/**
+ * @author Andreas Reichel
+ */
+public class PostgresNamedFunctionParameter extends ASTNodeAccessImpl implements Expression {
+ private final String name;
+ private final Expression expression;
+
+ public PostgresNamedFunctionParameter(String name, Expression expression) {
+ this.name = Objects.requireNonNull(name,
+ "The NAME of the PostgresNamedFunctionParameter must not be null.");
+ this.expression = Objects.requireNonNull(expression,
+ "The EXPRESSION of the PostgresNamedFunctionParameter must not be null.");
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ 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(name)
+ .append(" := ")
+ .append(expression);
+
+ return builder;
+ }
+
+ @Override
+ public String toString() {
+ return appendTo(new StringBuilder()).toString();
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/PreferringClause.java b/src/main/java/net/sf/jsqlparser/expression/PreferringClause.java
new file mode 100644
index 000000000..2db468dbb
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/PreferringClause.java
@@ -0,0 +1,66 @@
+/*-
+ * #%L
+ * JSQLParser library
+ * %%
+ * Copyright (C) 2004 - 2019 JSQLParser
+ * %%
+ * Dual licensed under GNU LGPL 2.1 or Apache License 2.0
+ * #L%
+ */
+package net.sf.jsqlparser.expression;
+
+import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
+
+import java.io.Serializable;
+
+public class PreferringClause implements Serializable {
+ private Expression preferring;
+ private PartitionByClause partitionBy;
+
+ public PreferringClause(Expression preferring) {
+ this.preferring = preferring;
+ }
+
+ public void setPartitionExpressionList(ExpressionList expressionList,
+ boolean brackets) {
+ if (this.partitionBy == null) {
+ this.partitionBy = new PartitionByClause();
+ }
+ partitionBy.setExpressions(expressionList, brackets);
+ }
+
+ public void toStringPreferring(StringBuilder b) {
+ b.append("PREFERRING ");
+ b.append(preferring.toString());
+
+ if (partitionBy != null) {
+ b.append(" ");
+ partitionBy.toStringPartitionBy(b);
+ }
+ }
+
+ public Expression getPreferring() {
+ return preferring;
+ }
+
+ public PreferringClause setPreferring(Expression preferring) {
+ this.preferring = preferring;
+ return this;
+ }
+
+ public PartitionByClause getPartitionBy() {
+ return partitionBy;
+ }
+
+ public PreferringClause setPartitionBy(PartitionByClause partitionBy) {
+ this.partitionBy = partitionBy;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ toStringPreferring(sb);
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/RangeExpression.java b/src/main/java/net/sf/jsqlparser/expression/RangeExpression.java
index 69cba377d..dd05827d6 100644
--- a/src/main/java/net/sf/jsqlparser/expression/RangeExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/RangeExpression.java
@@ -44,7 +44,7 @@ public String toString() {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/RawFunction.java b/src/main/java/net/sf/jsqlparser/expression/RawFunction.java
new file mode 100644
index 000000000..1c2d5b874
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/RawFunction.java
@@ -0,0 +1,41 @@
+/*-
+ * #%L
+ * JSQLParser library
+ * %%
+ * Copyright (C) 2004 - 2026 JSQLParser
+ * %%
+ * Dual licensed under GNU LGPL 2.1 or Apache License 2.0
+ * #L%
+ */
+package net.sf.jsqlparser.expression;
+
+/**
+ * Function with a raw argument body preserved as-is for deparsing.
+ */
+public class RawFunction extends Function {
+ private String rawArguments;
+
+ public RawFunction() {}
+
+ public RawFunction(String name, String rawArguments) {
+ setName(name);
+ this.rawArguments = rawArguments;
+ }
+
+ public String getRawArguments() {
+ return rawArguments;
+ }
+
+ public void setRawArguments(String rawArguments) {
+ this.rawArguments = rawArguments;
+ }
+
+ @Override
+ public String toString() {
+ String name = getName();
+ if (rawArguments == null) {
+ return name + "()";
+ }
+ return name + "(" + rawArguments + ")";
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/RowConstructor.java b/src/main/java/net/sf/jsqlparser/expression/RowConstructor.java
index 6eabf3b70..2f5844ea0 100644
--- a/src/main/java/net/sf/jsqlparser/expression/RowConstructor.java
+++ b/src/main/java/net/sf/jsqlparser/expression/RowConstructor.java
@@ -36,8 +36,13 @@ public String toString() {
return (name != null ? name : "") + super.toString();
}
- public RowConstructor withName(String name) {
+ public RowConstructor> withName(String name) {
this.setName(name);
return this;
}
+
+ @Override
+ public K accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
+ }
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/RowGetExpression.java b/src/main/java/net/sf/jsqlparser/expression/RowGetExpression.java
index 16376a470..0aaefa1aa 100644
--- a/src/main/java/net/sf/jsqlparser/expression/RowGetExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/RowGetExpression.java
@@ -21,8 +21,8 @@ public RowGetExpression(Expression expression, String columnName) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/SQLServerHints.java b/src/main/java/net/sf/jsqlparser/expression/SQLServerHints.java
index 84b7c2f38..34d14964b 100644
--- a/src/main/java/net/sf/jsqlparser/expression/SQLServerHints.java
+++ b/src/main/java/net/sf/jsqlparser/expression/SQLServerHints.java
@@ -18,8 +18,7 @@ public class SQLServerHints implements Serializable {
private Boolean noLock;
private String indexName;
- public SQLServerHints() {
- }
+ public SQLServerHints() {}
public SQLServerHints withNoLock() {
this.noLock = true;
diff --git a/src/main/java/net/sf/jsqlparser/expression/SignedExpression.java b/src/main/java/net/sf/jsqlparser/expression/SignedExpression.java
index dabc2f9c5..725d449e8 100644
--- a/src/main/java/net/sf/jsqlparser/expression/SignedExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/SignedExpression.java
@@ -48,8 +48,8 @@ public final void setExpression(Expression expression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/SpannerInterleaveIn.java b/src/main/java/net/sf/jsqlparser/expression/SpannerInterleaveIn.java
index 18cb16ac4..0bf49925d 100644
--- a/src/main/java/net/sf/jsqlparser/expression/SpannerInterleaveIn.java
+++ b/src/main/java/net/sf/jsqlparser/expression/SpannerInterleaveIn.java
@@ -16,14 +16,6 @@
public class SpannerInterleaveIn {
- public enum OnDelete {
- CASCADE, NO_ACTION;
-
- public static OnDelete from(String action) {
- return Enum.valueOf(OnDelete.class, action.toUpperCase());
- }
- }
-
private Table table;
private OnDelete onDelete;
@@ -77,4 +69,12 @@ public SpannerInterleaveIn withOnDelete(OnDelete action) {
this.setOnDelete(action);
return this;
}
+
+ public enum OnDelete {
+ CASCADE, NO_ACTION;
+
+ public static OnDelete from(String action) {
+ return Enum.valueOf(OnDelete.class, action.toUpperCase());
+ }
+ }
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/StringValue.java b/src/main/java/net/sf/jsqlparser/expression/StringValue.java
index 743efea46..a16536fab 100644
--- a/src/main/java/net/sf/jsqlparser/expression/StringValue.java
+++ b/src/main/java/net/sf/jsqlparser/expression/StringValue.java
@@ -20,11 +20,11 @@
*/
public final class StringValue extends ASTNodeAccessImpl implements Expression {
- private String value = "";
- private String prefix = null;
-
public static final List ALLOWED_PREFIXES =
Arrays.asList("N", "U", "E", "R", "B", "RB", "_utf8", "Q");
+ private String value = "";
+ private String prefix = null;
+ private String quoteStr = "'";
public StringValue() {
// empty constructor
@@ -36,6 +36,11 @@ public StringValue(String escapedValue) {
&& escapedValue.endsWith("'")) {
value = escapedValue.substring(1, escapedValue.length() - 1);
return;
+ } else if (escapedValue.length() >= 4 && escapedValue.startsWith("$$")
+ && escapedValue.endsWith("$$")) {
+ value = escapedValue.substring(2, escapedValue.length() - 2);
+ quoteStr = "$$";
+ return;
}
if (escapedValue.length() > 2) {
@@ -57,10 +62,27 @@ public String getValue() {
return value;
}
+ public void setValue(String string) {
+ value = string;
+ }
+
public String getPrefix() {
return prefix;
}
+ public void setPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+
+ public String getQuoteStr() {
+ return quoteStr;
+ }
+
+ public StringValue setQuoteStr(String quoteStr) {
+ this.quoteStr = quoteStr;
+ return this;
+ }
+
public String getNotExcapedValue() {
StringBuilder buffer = new StringBuilder(value);
int index = 0;
@@ -73,22 +95,14 @@ public String getNotExcapedValue() {
return buffer.toString();
}
- public void setValue(String string) {
- value = string;
- }
-
- public void setPrefix(String prefix) {
- this.prefix = prefix;
- }
-
@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 (prefix != null ? prefix : "") + "'" + value + "'";
+ return (prefix != null ? prefix : "") + quoteStr + value + quoteStr;
}
public StringValue withPrefix(String prefix) {
diff --git a/src/main/java/net/sf/jsqlparser/expression/StructType.java b/src/main/java/net/sf/jsqlparser/expression/StructType.java
index a9b88ab7c..4bd38a693 100644
--- a/src/main/java/net/sf/jsqlparser/expression/StructType.java
+++ b/src/main/java/net/sf/jsqlparser/expression/StructType.java
@@ -19,26 +19,26 @@
/*
* STRUCT
- *
+ *
* Type Declaration Meaning STRUCT Simple struct with a single unnamed 64-bit integer field.
* STRUCT Simple struct with a single parameterized string field named x. STRUCT> A struct with a nested struct named x inside it. The struct x has two
* fields, y and z, both of which are 64-bit integers. STRUCT> A struct
* containing an array named inner_array that holds 64-bit integer elements.
- *
+ *
* STRUCT( expr1 [AS field_name] [, ... ])
- *
+ *
* Syntax Output Type STRUCT(1,2,3) STRUCT STRUCT() STRUCT<> STRUCT('abc')
* STRUCT STRUCT(1, t.str_col) STRUCT STRUCT(1 AS a, 'abc' AS b)
* STRUCT STRUCT(str_col AS abc) STRUCT
- *
- *
+ *
+ *
* Struct Literals
- *
+ *
* Example Output Type (1, 2, 3) STRUCT (1, 'abc') STRUCT
* STRUCT(1 AS foo, 'abc' AS bar) STRUCT STRUCT(1, 'abc')
* STRUCT STRUCT(1) STRUCT STRUCT(1) STRUCT
- *
+ *
*/
public class StructType extends ASTNodeAccessImpl implements Expression {
private Dialect dialect = Dialect.BIG_QUERY;;
@@ -188,8 +188,8 @@ public String toString() {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public enum Dialect {
diff --git a/src/main/java/net/sf/jsqlparser/expression/TimeKeyExpression.java b/src/main/java/net/sf/jsqlparser/expression/TimeKeyExpression.java
index f2c4cfa65..759da0e7a 100644
--- a/src/main/java/net/sf/jsqlparser/expression/TimeKeyExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/TimeKeyExpression.java
@@ -24,8 +24,8 @@ public TimeKeyExpression(final String value) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public String getStringValue() {
diff --git a/src/main/java/net/sf/jsqlparser/expression/TimeValue.java b/src/main/java/net/sf/jsqlparser/expression/TimeValue.java
index f87970fa1..2b3f74394 100644
--- a/src/main/java/net/sf/jsqlparser/expression/TimeValue.java
+++ b/src/main/java/net/sf/jsqlparser/expression/TimeValue.java
@@ -25,15 +25,15 @@ public TimeValue() {
}
public TimeValue(String value) {
- if (value == null || value.length() == 0) {
+ if (value == null || value.isEmpty()) {
throw new IllegalArgumentException("value can neither be null nor empty.");
}
this.value = Time.valueOf(value.substring(1, value.length() - 1));
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public Time getValue() {
diff --git a/src/main/java/net/sf/jsqlparser/expression/TimestampValue.java b/src/main/java/net/sf/jsqlparser/expression/TimestampValue.java
index c6e84a4ea..a06082304 100644
--- a/src/main/java/net/sf/jsqlparser/expression/TimestampValue.java
+++ b/src/main/java/net/sf/jsqlparser/expression/TimestampValue.java
@@ -19,26 +19,26 @@
*/
public final class TimestampValue extends ASTNodeAccessImpl implements Expression {
+ private static final char QUOTATION = '\'';
private Timestamp value;
private String rawValue;
- private static final char QUOTATION = '\'';
public TimestampValue() {
// empty constructor
}
public TimestampValue(String value) {
- // if (value == null) {
- // throw new IllegalArgumentException("null string");
- // } else {
- // setRawValue(value);
- // }
- setRawValue(Objects.requireNonNull(value, "The Timestamp string value must not be null."));
+ // if (value == null) {
+ // throw new IllegalArgumentException("null string");
+ // } else {
+ // setRawValue(value);
+ // }
+ setRawValue(Objects.requireNonNull(value, "The Timestamp string value must not be null."));
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public Timestamp getValue() {
diff --git a/src/main/java/net/sf/jsqlparser/expression/TimezoneExpression.java b/src/main/java/net/sf/jsqlparser/expression/TimezoneExpression.java
index 1cc10c924..a67572ace 100644
--- a/src/main/java/net/sf/jsqlparser/expression/TimezoneExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/TimezoneExpression.java
@@ -17,8 +17,8 @@
public class TimezoneExpression extends ASTNodeAccessImpl implements Expression {
- private Expression leftExpression;
private final ExpressionList timezoneExpressions = new ExpressionList<>();
+ private Expression leftExpression;
public TimezoneExpression() {
leftExpression = null;
@@ -39,8 +39,8 @@ public TimezoneExpression setLeftExpression(Expression expression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public List getTimezoneExpressions() {
diff --git a/src/main/java/net/sf/jsqlparser/expression/TranscodingFunction.java b/src/main/java/net/sf/jsqlparser/expression/TranscodingFunction.java
index 6b656aa2d..b68f1dfb7 100644
--- a/src/main/java/net/sf/jsqlparser/expression/TranscodingFunction.java
+++ b/src/main/java/net/sf/jsqlparser/expression/TranscodingFunction.java
@@ -12,17 +12,35 @@
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.statement.create.table.ColDataType;
+import java.util.Objects;
+
public class TranscodingFunction extends ASTNodeAccessImpl implements Expression {
+ private String keyword = "CONVERT";
private boolean isTranscodeStyle = true;
private ColDataType colDataType;
private Expression expression;
private String transcodingName;
+ public TranscodingFunction(String keyword, Expression expression, String transcodingName) {
+ this.keyword = Objects.requireNonNullElse(keyword, "CONVERT").toUpperCase();
+ this.expression = expression;
+ this.transcodingName = transcodingName;
+ }
+
public TranscodingFunction(Expression expression, String transcodingName) {
this.expression = expression;
this.transcodingName = transcodingName;
}
+ public TranscodingFunction(String keyword, ColDataType colDataType, Expression expression,
+ String transcodingName) {
+ this.keyword = Objects.requireNonNullElse(keyword, "CONVERT").toUpperCase();
+ this.colDataType = colDataType;
+ this.expression = expression;
+ this.transcodingName = transcodingName;
+ this.isTranscodeStyle = false;
+ }
+
public TranscodingFunction(ColDataType colDataType, Expression expression,
String transcodingName) {
this.colDataType = colDataType;
@@ -35,6 +53,15 @@ public TranscodingFunction() {
this(null, null);
}
+ public String getKeyword() {
+ return keyword;
+ }
+
+ public TranscodingFunction setKeyword(String keyword) {
+ this.keyword = Objects.requireNonNullElse(keyword, "CONVERT").toUpperCase();
+ return this;
+ }
+
public Expression getExpression() {
return expression;
}
@@ -80,21 +107,23 @@ public TranscodingFunction setTranscodeStyle(boolean transcodeStyle) {
return this;
}
- 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) {
if (isTranscodeStyle) {
return builder
- .append("CONVERT( ")
+ .append(keyword)
+ .append("( ")
.append(expression)
.append(" USING ")
.append(transcodingName)
.append(" )");
} else {
return builder
- .append("CONVERT( ")
+ .append(keyword)
+ .append("( ")
.append(colDataType)
.append(", ")
.append(expression)
diff --git a/src/main/java/net/sf/jsqlparser/expression/TrimFunction.java b/src/main/java/net/sf/jsqlparser/expression/TrimFunction.java
index def6ec3d1..e8ea0305d 100644
--- a/src/main/java/net/sf/jsqlparser/expression/TrimFunction.java
+++ b/src/main/java/net/sf/jsqlparser/expression/TrimFunction.java
@@ -12,10 +12,6 @@
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
public class TrimFunction extends ASTNodeAccessImpl implements Expression {
- public enum TrimSpecification {
- LEADING, TRAILING, BOTH
- }
-
private TrimSpecification trimSpecification;
private Expression expression;
private Expression fromExpression;
@@ -92,8 +88,8 @@ public TrimFunction withUsingFromKeyword(boolean useFromKeyword) {
}
@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) {
@@ -121,4 +117,8 @@ public StringBuilder appendTo(StringBuilder builder) {
public String toString() {
return appendTo(new StringBuilder()).toString();
}
+
+ public enum TrimSpecification {
+ LEADING, TRAILING, BOTH
+ }
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/UserVariable.java b/src/main/java/net/sf/jsqlparser/expression/UserVariable.java
index f7abde5f8..b0599a3c5 100644
--- a/src/main/java/net/sf/jsqlparser/expression/UserVariable.java
+++ b/src/main/java/net/sf/jsqlparser/expression/UserVariable.java
@@ -24,7 +24,7 @@ public UserVariable() {
}
public UserVariable(String name) {
- this.name = name;
+ setName(name);
}
public String getName() {
@@ -32,12 +32,20 @@ public String getName() {
}
public void setName(String name) {
- this.name = name;
+ if (name.startsWith("@@")) {
+ this.name = name.substring(2);
+ doubleAdd = true;
+ } else if (name.startsWith("@")) {
+ this.name = name.substring(1);
+ doubleAdd = false;
+ } else {
+ this.name = name;
+ }
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public boolean isDoubleAdd() {
diff --git a/src/main/java/net/sf/jsqlparser/expression/VariableAssignment.java b/src/main/java/net/sf/jsqlparser/expression/VariableAssignment.java
index a92f639e2..2ad773205 100644
--- a/src/main/java/net/sf/jsqlparser/expression/VariableAssignment.java
+++ b/src/main/java/net/sf/jsqlparser/expression/VariableAssignment.java
@@ -50,9 +50,9 @@ public String toString() {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
-
+
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/WhenClause.java b/src/main/java/net/sf/jsqlparser/expression/WhenClause.java
index 7f13fb523..5ed58de11 100644
--- a/src/main/java/net/sf/jsqlparser/expression/WhenClause.java
+++ b/src/main/java/net/sf/jsqlparser/expression/WhenClause.java
@@ -27,8 +27,8 @@ public WhenClause(Expression whenExpression, Expression thenExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public Expression getThenExpression() {
diff --git a/src/main/java/net/sf/jsqlparser/expression/WindowDefinition.java b/src/main/java/net/sf/jsqlparser/expression/WindowDefinition.java
index b15ec6fcb..60760baee 100644
--- a/src/main/java/net/sf/jsqlparser/expression/WindowDefinition.java
+++ b/src/main/java/net/sf/jsqlparser/expression/WindowDefinition.java
@@ -11,6 +11,7 @@
import java.io.Serializable;
import java.util.List;
+
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.statement.select.OrderByElement;
@@ -50,12 +51,13 @@ public ExpressionList getPartitionExpressionList() {
return partitionBy.getPartitionExpressionList();
}
- 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) {
+ partitionBy.setExpressions(partitionExpressionList, brackets);
}
public String getWindowName() {
@@ -65,7 +67,7 @@ public String getWindowName() {
public void setWindowName(String windowName) {
this.windowName = windowName;
}
-
+
public WindowDefinition withWindowName(String windowName) {
setWindowName(windowName);
return this;
diff --git a/src/main/java/net/sf/jsqlparser/expression/WindowElement.java b/src/main/java/net/sf/jsqlparser/expression/WindowElement.java
index 89c85e79a..97260ce97 100644
--- a/src/main/java/net/sf/jsqlparser/expression/WindowElement.java
+++ b/src/main/java/net/sf/jsqlparser/expression/WindowElement.java
@@ -13,14 +13,6 @@
public class WindowElement implements Serializable {
- public enum Type {
- ROWS, RANGE;
-
- public static Type from(String type) {
- return Enum.valueOf(Type.class, type.toUpperCase());
- }
- }
-
private Type type;
private WindowOffset offset;
private WindowRange range;
@@ -77,4 +69,12 @@ public WindowElement withRange(WindowRange range) {
return this;
}
+ public enum Type {
+ ROWS, RANGE;
+
+ public static Type from(String type) {
+ return Enum.valueOf(Type.class, type.toUpperCase());
+ }
+ }
+
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/WindowOffset.java b/src/main/java/net/sf/jsqlparser/expression/WindowOffset.java
index 843f14150..0303b4f06 100644
--- a/src/main/java/net/sf/jsqlparser/expression/WindowOffset.java
+++ b/src/main/java/net/sf/jsqlparser/expression/WindowOffset.java
@@ -13,14 +13,6 @@
public class WindowOffset implements Serializable {
- public enum Type {
- PRECEDING, FOLLOWING, CURRENT, EXPR;
-
- public static Type from(String type) {
- return Enum.valueOf(Type.class, type.toUpperCase());
- }
- }
-
private Expression expression;
private Type type;
@@ -83,4 +75,12 @@ public E getExpression(Class type) {
return type.cast(getExpression());
}
+ public enum Type {
+ PRECEDING, FOLLOWING, CURRENT, EXPR;
+
+ public static Type from(String type) {
+ return Enum.valueOf(Type.class, type.toUpperCase());
+ }
+ }
+
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/WindowRange.java b/src/main/java/net/sf/jsqlparser/expression/WindowRange.java
index 5c2568258..fc5f0af36 100644
--- a/src/main/java/net/sf/jsqlparser/expression/WindowRange.java
+++ b/src/main/java/net/sf/jsqlparser/expression/WindowRange.java
@@ -34,12 +34,10 @@ public void setStart(WindowOffset start) {
@Override
public String toString() {
- StringBuilder buffer = new StringBuilder();
- buffer.append(" BETWEEN");
- buffer.append(start);
- buffer.append(" AND");
- buffer.append(end);
- return buffer.toString();
+ return " BETWEEN" +
+ start +
+ " AND" +
+ end;
}
public WindowRange withStart(WindowOffset start) {
diff --git a/src/main/java/net/sf/jsqlparser/expression/XMLSerializeExpr.java b/src/main/java/net/sf/jsqlparser/expression/XMLSerializeExpr.java
index 89f59242b..d2534e62d 100644
--- a/src/main/java/net/sf/jsqlparser/expression/XMLSerializeExpr.java
+++ b/src/main/java/net/sf/jsqlparser/expression/XMLSerializeExpr.java
@@ -10,7 +10,9 @@
package net.sf.jsqlparser.expression;
import java.util.List;
+
import static java.util.stream.Collectors.joining;
+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.statement.create.table.ColDataType;
import net.sf.jsqlparser.statement.select.OrderByElement;
@@ -22,8 +24,8 @@ public class XMLSerializeExpr extends ASTNodeAccessImpl implements Expression {
private ColDataType dataType;
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public Expression getExpression() {
@@ -49,11 +51,12 @@ public ColDataType getDataType() {
public void setDataType(ColDataType dataType) {
this.dataType = dataType;
}
-
+
@Override
public String toString() {
return "xmlserialize(xmlagg(xmltext(" + expression + ")"
- + (orderByElements != null ? " ORDER BY " + orderByElements.stream().map(item -> item.toString()).collect(joining(", ")) : "")
+ + (orderByElements != null ? " ORDER BY " + orderByElements.stream()
+ .map(OrderByElement::toString).collect(joining(", ")) : "")
+ ") AS " + dataType + ")";
}
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Addition.java b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Addition.java
index 0492a5540..fca4fd08d 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Addition.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Addition.java
@@ -22,8 +22,8 @@ public Addition(Expression leftExpression, Expression rightExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseAnd.java b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseAnd.java
index 4104bfda1..f5eac9390 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseAnd.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseAnd.java
@@ -22,8 +22,8 @@ public BitwiseAnd(Expression leftExpression, Expression rightExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseLeftShift.java b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseLeftShift.java
index 21e08f0ee..0f2094ce9 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseLeftShift.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseLeftShift.java
@@ -22,8 +22,8 @@ public BitwiseLeftShift(Expression leftExpression, Expression rightExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseOr.java b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseOr.java
index dad377195..2d11d9e6f 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseOr.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseOr.java
@@ -22,8 +22,8 @@ public BitwiseOr(Expression leftExpression, Expression rightExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseRightShift.java b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseRightShift.java
index bbcaccc48..13b5dbdd3 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseRightShift.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseRightShift.java
@@ -22,8 +22,8 @@ public BitwiseRightShift(Expression leftExpression, Expression rightExpression)
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseXor.java b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseXor.java
index 6837eedaa..89cbcb64a 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseXor.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/BitwiseXor.java
@@ -22,8 +22,8 @@ public BitwiseXor(Expression leftExpression, Expression rightExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Concat.java b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Concat.java
index 39960b35f..1ad8bb119 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Concat.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Concat.java
@@ -22,8 +22,8 @@ public Concat(Expression leftExpression, Expression rightExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Division.java b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Division.java
index c07b71235..a963d63f3 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Division.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Division.java
@@ -22,8 +22,8 @@ public Division(Expression leftExpression, Expression rightExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/IntegerDivision.java b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/IntegerDivision.java
index 351ad764b..73489eb8d 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/IntegerDivision.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/IntegerDivision.java
@@ -22,8 +22,8 @@ public IntegerDivision(Expression leftExpression, Expression rightExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Modulo.java b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Modulo.java
index 31831a51b..63482d2a2 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Modulo.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Modulo.java
@@ -25,8 +25,8 @@ public Modulo(Expression leftExpression, Expression rightExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Multiplication.java b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Multiplication.java
index 7fdf26900..774db570b 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Multiplication.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Multiplication.java
@@ -22,8 +22,8 @@ public Multiplication(Expression leftExpression, Expression rightExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Subtraction.java b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Subtraction.java
index cff5b4041..dc2b74c7b 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Subtraction.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Subtraction.java
@@ -22,8 +22,8 @@ public Subtraction(Expression leftExpression, Expression rightExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/conditional/AndExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/conditional/AndExpression.java
index 38152158b..0d9d36377 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/conditional/AndExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/conditional/AndExpression.java
@@ -25,17 +25,17 @@ public AndExpression(Expression leftExpression, Expression rightExpression) {
setRightExpression(rightExpression);
}
- public void setUseOperator(boolean useOperator) {
- this.useOperator = useOperator;
- }
-
public boolean isUseOperator() {
return useOperator;
}
+ public void setUseOperator(boolean useOperator) {
+ this.useOperator = useOperator;
+ }
+
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/conditional/OrExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/conditional/OrExpression.java
index 11503b475..f08cc7de2 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/conditional/OrExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/conditional/OrExpression.java
@@ -35,8 +35,8 @@ public OrExpression withRightExpression(Expression expression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/conditional/XorExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/conditional/XorExpression.java
index 00e93fc5a..9bab8b53f 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/conditional/XorExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/conditional/XorExpression.java
@@ -35,8 +35,8 @@ public XorExpression withRightExpression(Expression expression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/Between.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/Between.java
index e220a1dcb..8998863ef 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/Between.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/Between.java
@@ -22,47 +22,70 @@ public class Between extends ASTNodeAccessImpl implements Expression {
private boolean not = false;
private Expression betweenExpressionStart;
private Expression betweenExpressionEnd;
+ private boolean usingSymmetric = false;
+ private boolean usingAsymmetric = false;
public Expression getBetweenExpressionEnd() {
return betweenExpressionEnd;
}
+ public void setBetweenExpressionEnd(Expression expression) {
+ betweenExpressionEnd = expression;
+ }
+
public Expression getBetweenExpressionStart() {
return betweenExpressionStart;
}
+ public void setBetweenExpressionStart(Expression expression) {
+ betweenExpressionStart = expression;
+ }
+
public Expression getLeftExpression() {
return leftExpression;
}
+ public void setLeftExpression(Expression expression) {
+ leftExpression = expression;
+ }
+
public boolean isNot() {
return not;
}
- public void setBetweenExpressionEnd(Expression expression) {
- betweenExpressionEnd = expression;
+ public void setNot(boolean b) {
+ not = b;
}
- public void setBetweenExpressionStart(Expression expression) {
- betweenExpressionStart = expression;
+ public boolean isUsingSymmetric() {
+ return usingSymmetric;
}
- public void setLeftExpression(Expression expression) {
- leftExpression = expression;
+ public Between setUsingSymmetric(boolean usingSymmetric) {
+ this.usingSymmetric = usingSymmetric;
+ return this;
}
- public void setNot(boolean b) {
- not = b;
+ public boolean isUsingAsymmetric() {
+ return usingAsymmetric;
+ }
+
+ public Between setUsingAsymmetric(boolean usingAsymmetric) {
+ this.usingAsymmetric = usingAsymmetric;
+ return this;
}
@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 leftExpression + " " + (not ? "NOT " : "") + "BETWEEN " + betweenExpressionStart + " AND "
+ return leftExpression + " " + (not ? "NOT " : "") + "BETWEEN "
+ + (usingSymmetric ? "SYMMETRIC " : "") + (usingAsymmetric ? "ASYMMETRIC " : "")
+ + betweenExpressionStart
+ + " AND "
+ betweenExpressionEnd;
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ContainedBy.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ContainedBy.java
index b0a5abcbb..15562a408 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ContainedBy.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ContainedBy.java
@@ -18,8 +18,8 @@ public ContainedBy() {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/Contains.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/Contains.java
index c362dc2be..dbfda1027 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/Contains.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/Contains.java
@@ -18,8 +18,8 @@ public Contains() {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/CosineSimilarity.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/CosineSimilarity.java
new file mode 100644
index 000000000..00aad962d
--- /dev/null
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/CosineSimilarity.java
@@ -0,0 +1,28 @@
+/*-
+ * #%L
+ * JSQLParser library
+ * %%
+ * Copyright (C) 2004 - 2022 JSQLParser
+ * %%
+ * Dual licensed under GNU LGPL 2.1 or Apache License 2.0
+ * #L%
+ */
+package net.sf.jsqlparser.expression.operators.relational;
+
+import net.sf.jsqlparser.expression.ExpressionVisitor;
+
+public class CosineSimilarity extends ComparisonOperator {
+
+ public CosineSimilarity() {
+ super("<=>");
+ }
+
+ public CosineSimilarity(String operator) {
+ super(operator);
+ }
+
+ @Override
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
+ }
+}
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/DoubleAnd.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/DoubleAnd.java
index c060cbc52..372e123b1 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/DoubleAnd.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/DoubleAnd.java
@@ -18,7 +18,7 @@ public DoubleAnd() {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/EqualsTo.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/EqualsTo.java
index e9e33ac60..8f80f1be8 100755
--- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/EqualsTo.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/EqualsTo.java
@@ -25,8 +25,8 @@ public EqualsTo(Expression left, Expression right) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExcludesExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExcludesExpression.java
index bd9c1de75..847ff087c 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExcludesExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExcludesExpression.java
@@ -29,15 +29,15 @@ public Expression getLeftExpression() {
return leftExpression;
}
+ public final void setLeftExpression(Expression expression) {
+ leftExpression = expression;
+ }
+
public ExcludesExpression withLeftExpression(Expression expression) {
this.setLeftExpression(expression);
return this;
}
- public final void setLeftExpression(Expression expression) {
- leftExpression = expression;
- }
-
public Expression getRightExpression() {
return rightExpression;
}
@@ -47,8 +47,8 @@ public void setRightExpression(Expression rightExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExistsExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExistsExpression.java
index 099fb054f..c8d83f1d5 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExistsExpression.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExistsExpression.java
@@ -35,8 +35,8 @@ public void setNot(boolean b) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
public String getStringExpression() {
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExpressionList.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExpressionList.java
index 090d2707b..5efb04359 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExpressionList.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExpressionList.java
@@ -11,7 +11,7 @@
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
-import net.sf.jsqlparser.parser.SimpleNode;
+import net.sf.jsqlparser.parser.Node;
import java.io.Serializable;
import java.util.ArrayList;
@@ -24,7 +24,7 @@
*/
public class ExpressionList extends ArrayList
implements Expression, Serializable {
- private transient SimpleNode node;
+ private transient Node node;
public ExpressionList(Collection extends T> expressions) {
addAll(expressions);
@@ -94,18 +94,19 @@ public String toString() {
return appendTo(new StringBuilder()).toString();
}
- @Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
- }
@Override
- public SimpleNode getASTNode() {
+ public Node getASTNode() {
return node;
}
@Override
- public void setASTNode(SimpleNode node) {
+ public void setASTNode(Node node) {
this.node = node;
}
+
+ @Override
+ public K accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
+ }
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/FullTextSearch.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/FullTextSearch.java
index 83c1f7b3a..0bf79f0ec 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/FullTextSearch.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/FullTextSearch.java
@@ -9,6 +9,10 @@
*/
package net.sf.jsqlparser.expression.operators.relational;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Optional;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.JdbcNamedParameter;
@@ -17,11 +21,6 @@
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.schema.Column;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Optional;
-
public class FullTextSearch extends ASTNodeAccessImpl implements Expression {
private ExpressionList _matchColumns;
@@ -32,41 +31,45 @@ public FullTextSearch() {
}
+ public ExpressionList getMatchColumns() {
+ return this._matchColumns;
+ }
+
public void setMatchColumns(ExpressionList columns) {
this._matchColumns = columns;
}
- public ExpressionList getMatchColumns() {
- return this._matchColumns;
+ public Expression getAgainstValue() {
+ return this._againstValue;
}
- public void setAgainstValue(StringValue val) {
+ public void setAgainstValue(Expression val) {
this._againstValue = val;
}
+ public void setAgainstValue(StringValue val) {
+ setAgainstValue((Expression) val);
+ }
+
public void setAgainstValue(JdbcNamedParameter val) {
- this._againstValue = val;
+ setAgainstValue((Expression) val);
}
public void setAgainstValue(JdbcParameter val) {
- this._againstValue = val;
+ setAgainstValue((Expression) val);
}
- public Expression getAgainstValue() {
- return this._againstValue;
+ public String getSearchModifier() {
+ return this._searchModifier;
}
public void setSearchModifier(String val) {
this._searchModifier = val;
}
- public String getSearchModifier() {
- return this._searchModifier;
- }
-
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
@@ -92,6 +95,10 @@ public FullTextSearch withMatchColumns(ExpressionList matchColumns) {
}
public FullTextSearch withAgainstValue(StringValue againstValue) {
+ return withAgainstValue((Expression) againstValue);
+ }
+
+ public FullTextSearch withAgainstValue(Expression againstValue) {
this.setAgainstValue(againstValue);
return this;
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/GeometryDistance.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/GeometryDistance.java
index 8fceadd3f..9f8438ab6 100644
--- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/GeometryDistance.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/GeometryDistance.java
@@ -22,7 +22,7 @@ public GeometryDistance(String operator) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
}
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/GreaterThan.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/GreaterThan.java
index 5b94c6301..3599ba45d 100755
--- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/GreaterThan.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/GreaterThan.java
@@ -23,8 +23,8 @@ public GreaterThan(Expression leftExpression, Expression rightExpression) {
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor expressionVisitor, S context) {
+ return expressionVisitor.visit(this, context);
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/GreaterThanEquals.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/GreaterThanEquals.java
index 506c60efb..39d1c8c97 100755
--- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/GreaterThanEquals.java
+++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/GreaterThanEquals.java
@@ -27,8 +27,8 @@ public GreaterThanEquals(Expression leftExpression, Expression rightExpression)
}
@Override
- public void accept(ExpressionVisitor expressionVisitor) {
- expressionVisitor.visit(this);
+ public T accept(ExpressionVisitor