diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 1d566e3ef..3c265b631 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [8] + java: [11] name: Java ${{ matrix.java }} building ... steps: diff --git a/.github/workflows/maven_deploy.yml b/.github/workflows/maven_deploy.yml index c14858ffb..740e80cb1 100644 --- a/.github/workflows/maven_deploy.yml +++ b/.github/workflows/maven_deploy.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [8] + java: [11] name: Java ${{ matrix.java }} building ... steps: diff --git a/README.md b/README.md index b223c27fa..d3606bf56 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,8 @@ -# [JSqlParser 4.8 Website](https://jsqlparser.github.io/JSqlParser) drawing +# [JSqlParser 4.9 Website](https://jsqlparser.github.io/JSqlParser) drawing ![Build Status](https://github.com/JSQLParser/JSqlParser/actions/workflows/maven.yml/badge.svg) - -[![Build Status (Legacy)](https://travis-ci.com/JSQLParser/JSqlParser.svg?branch=master)](https://travis-ci.com/JSQLParser/JSqlParser) [![Coverage Status](https://coveralls.io/repos/JSQLParser/JSqlParser/badge.svg?branch=master)](https://coveralls.io/r/JSQLParser/JSqlParser?branch=master) -[![Codacy Badge](https://app.codacy.com/project/badge/Grade/6f9a2d7eb98f45969749e101322634a1)](https://www.codacy.com/gh/JSQLParser/JSqlParser/dashboard?utm_source=github.com&utm_medium=referral&utm_content=JSQLParser/JSqlParser&utm_campaign=Badge_Grade) -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.jsqlparser/jsqlparser/badge.svg)](http://maven-badges.herokuapp.com/maven-central/com.github.jsqlparser/jsqlparser) -[![Javadocs](https://www.javadoc.io/badge/com.github.jsqlparser/jsqlparser.svg)](https://www.javadoc.io/doc/com.github.jsqlparser/jsqlparser) - +[![Build Status (Legacy)](https://travis-ci.com/JSQLParser/JSqlParser.svg?branch=master)](https://travis-ci.com/JSQLParser/JSqlParser) [![Coverage Status](https://coveralls.io/repos/JSQLParser/JSqlParser/badge.svg?branch=master)](https://coveralls.io/r/JSQLParser/JSqlParser?branch=master) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/6f9a2d7eb98f45969749e101322634a1)](https://www.codacy.com/gh/JSQLParser/JSqlParser/dashboard?utm_source=github.com&utm_medium=referral&utm_content=JSQLParser/JSqlParser&utm_campaign=Badge_Grade) +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.jsqlparser/jsqlparser/badge.svg)](http://maven-badges.herokuapp.com/maven-central/com.github.jsqlparser/jsqlparser) [![Javadocs](https://www.javadoc.io/badge/com.github.jsqlparser/jsqlparser.svg)](https://www.javadoc.io/doc/com.github.jsqlparser/jsqlparser) [![Gitter](https://badges.gitter.im/JSQLParser/JSqlParser.svg)](https://gitter.im/JSQLParser/JSqlParser?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) ## Summary @@ -50,14 +46,16 @@ Assertions.assertEquals("b", b.getColumnName()); } ``` +JSQLParser-4.9 is the last JDK8 compatible version. The upcoming JSQLParser-5.0 will depend on JDK11 and introduces API breaking changes to the AST Visitors. Please see the Migration Guide for the details. + ## [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 ...` | - +| 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` | **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)). diff --git a/build.gradle b/build.gradle index 771048f7c..144479930 100644 --- a/build.gradle +++ b/build.gradle @@ -88,15 +88,15 @@ configurations { dependencies { testImplementation 'commons-io:commons-io:2.+' testImplementation 'org.apache.commons:commons-text:+' - testImplementation 'org.mockito:mockito-core:4.+' - testImplementation 'org.assertj:assertj-core:3.+' - testImplementation 'org.hamcrest:hamcrest-core:2.+' - testImplementation 'org.apache.commons:commons-lang3:3.+' - testImplementation 'com.h2database:h2:2.+' + testImplementation 'org.mockito:mockito-core:+' + testImplementation 'org.assertj:assertj-core:+' + testImplementation 'org.hamcrest:hamcrest-core:+' + testImplementation 'org.apache.commons:commons-lang3:+' + testImplementation 'com.h2database:h2:+' // for JaCoCo Reports - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.+' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.+' + testImplementation 'org.junit.jupiter:junit-jupiter-api:+' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:+' testImplementation 'org.junit.jupiter:junit-jupiter-params:+' // https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter @@ -122,8 +122,8 @@ java { withSourcesJar() withJavadocJar() - sourceCompatibility = '1.8' - targetCompatibility = '1.8' + sourceCompatibility = '11' + targetCompatibility = '11' // needed for XML-Doclet to work (since Doclet changed again with Java 13) toolchain { languageVersion.set(JavaLanguageVersion.of(11)) @@ -131,10 +131,11 @@ java { } compileJava { - options.release = 8 + options.release = 11 } javadoc { + include("build/generated/javacc/net/sf/jsqlparser/parser/*.java" ) if(JavaVersion.current().isJava9Compatible()) { options.addBooleanOption('html5', true) } @@ -196,6 +197,14 @@ coveralls { } jacocoTestReport { + // Jacoco can't handle the TokenManager class + afterEvaluate { + classDirectories.setFrom(files(classDirectories.files.collect { + fileTree(dir: it, exclude: [ + "**CCJSqlParserTokenManager**" + ]) + })) + } dependsOn test // tests are required to run before generating the report reports { xml.required = false @@ -204,24 +213,25 @@ jacocoTestReport { } } jacocoTestCoverageVerification { + // Jacoco can't handle the TokenManager class + afterEvaluate { + classDirectories.setFrom(files(classDirectories.files.collect { + fileTree(dir: it, exclude: [ + "**CCJSqlParserTokenManager**" + ]) + })) + } violationRules { rule { //element = 'CLASS' limit { //@todo: temporarily reduced it 80%, we need to bring that back to 84% accepting the Keywords PR - minimum = 0.80 + minimum = 0.50 } 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.**' ] } rule { @@ -231,19 +241,12 @@ jacocoTestCoverageVerification { value = 'MISSEDCOUNT' //@todo: temporarily increased to 7000, we need to bring that down to 5500 after accepting the Keywords PR - maximum = 7000 + maximum = 20000 } 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.**' ] } // rule { @@ -253,17 +256,10 @@ jacocoTestCoverageVerification { // value = 'MISSEDRATIO' // maximum = 0.3 // } -// excludes = [ +// 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.**' // ] // } } @@ -333,6 +329,7 @@ tasks.withType(Checkstyle).configureEach { xml.required = false html.required = true } + excludes = [ "**/module-info.java" ] } tasks.register('renderRR') { @@ -348,12 +345,15 @@ tasks.register('renderRR') { src 'http://manticore-projects.com/download/convert.war' dest "$buildDir/rr/convert.war" overwrite false + onlyIfModified true } download.run { src 'http://manticore-projects.com/download/rr.war' dest "$buildDir/rr/rr.war" overwrite false + onlyIfModified true + tempAndMove true } javaexec { @@ -453,7 +453,7 @@ xslt { } tasks.register('sphinx', Exec) { - dependsOn(gitChangelogTask, renderRR, xslt, updateKeywords, xmldoc) + dependsOn(gitChangelogTask, renderRR, xslt, xmldoc) String PROLOG = """ .. |_| unicode:: U+00A0 @@ -494,7 +494,7 @@ tasks.register('sphinx', Exec) { } publish { - dependsOn(check, gitChangelogTask, renderRR, xslt, updateKeywords, xmldoc) + dependsOn(check, gitChangelogTask, renderRR, xslt, xmldoc) } publishing { @@ -605,5 +605,6 @@ tasks.register('upload') { } } } -upload.dependsOn(check, assemble, gitChangelogTask, renderRR, xslt, updateKeywords, xmldoc) +check.dependsOn jacocoTestCoverageVerification +upload.dependsOn(check, assemble, gitChangelogTask, renderRR, xslt, xmldoc) diff --git a/config/pmd/ruleset.xml b/config/pmd/ruleset.xml index 6b8c681a6..acca2d6e9 100644 --- a/config/pmd/ruleset.xml +++ b/config/pmd/ruleset.xml @@ -31,9 +31,6 @@ under the License. - - - @@ -49,7 +46,6 @@ under the License. - @@ -67,16 +63,7 @@ under the License. - - - @@ -84,7 +71,6 @@ under the License. - diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7f93135c4..e6441136f 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..a4413138c 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-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 0adc8e1a5..b740cf133 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,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/HEAD/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/. @@ -145,7 +145,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 +153,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 @@ -202,11 +202,11 @@ 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, 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" \ diff --git a/gradlew.bat b/gradlew.bat index 6689b85be..7101f8e46 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ 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. +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 @@ -57,11 +57,11 @@ 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. +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 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 f03dba3d2..3dde1be38 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.github.jsqlparser jsqlparser - 4.9 + 5.0 JSQLParser library 2004 @@ -29,50 +29,50 @@ net.java.dev.javacc javacc - 7.0.13 + [7.0.13,) test commons-io commons-io - 2.11.0 + [2.15.1,) test org.junit.jupiter junit-jupiter - 5.9.2 + [5.10.2,) test org.mockito mockito-core - 4.8.0 + [5.11.0,) test org.mockito mockito-junit-jupiter - 4.8.0 + [5.11.0,) test org.assertj assertj-core - 3.23.1 + [3.25.3,) test org.apache.commons commons-lang3 - 3.12.0 + [3.14.0,) test com.h2database h2 - 2.1.214 + [2.2.224,) test @@ -107,7 +107,7 @@ scm:git:https://github.com/JSQLParser/JSqlParser.git scm:git:ssh://git@github.com:JSQLParser/JSqlParser.git https://github.com/JSQLParser/JSqlParser.git - jsqlparser-4.9 + jsqlparser-5.0 @@ -133,7 +133,7 @@ org.apache.maven.plugins maven-pmd-plugin - 3.19.0 + 3.21.2 @@ -169,16 +169,6 @@ pmd-java ${pmdVersion} - - net.sourceforge.pmd - pmd-javascript - ${pmdVersion} - - - net.sourceforge.pmd - pmd-jsp - ${pmdVersion} - @@ -205,8 +195,8 @@ maven-compiler-plugin 3.10.1 - 1.8 - 1.8 + 11 + 11 true ${project.build.sourceEncoding} true @@ -279,7 +269,11 @@ org.apache.maven.plugins maven-release-plugin - + 3.0.0-M7 true @@ -331,6 +325,7 @@ org.apache.maven.plugins maven-jar-plugin + 3.3.0 @@ -383,9 +378,15 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.3 + 3.2.5 false + + false + + --add-opens=java.base/java.lang=ALL-UNNAMED + --add-opens=java.base/java.util=ALL-UNNAMED + @@ -539,14 +540,14 @@ !skipCheckSources - [1.8,) + [11,) org.apache.maven.plugins maven-checkstyle-plugin - 3.1.0 + 3.3.1 verify-style @@ -560,6 +561,7 @@ true true ${project.build.sourceDirectory} + **/module-info.java @@ -598,7 +600,7 @@ com.puppycrawl.tools checkstyle - 8.29 + ${checkStyleVersion} @@ -622,7 +624,8 @@ UTF-8 - 6.53.0 + 6.55.0 + 10.14.0 JSqlParser parses an SQL statement and translate it into a hierarchy of Java classes. diff --git a/settings.gradle b/settings.gradle index 523623eb1..78feb00f5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,4 +2,4 @@ * This file was generated by the Gradle 'init' task. */ -rootProject.name = 'jsqlparser' +rootProject.name = 'JSQLFormatter' diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java new file mode 100644 index 000000000..66fe1cb80 --- /dev/null +++ b/src/main/java/module-info.java @@ -0,0 +1,55 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +module net.sf.jsqlparser { + requires java.sql; + requires java.logging; + + exports net.sf.jsqlparser; + exports net.sf.jsqlparser.expression; + exports net.sf.jsqlparser.expression.operators.arithmetic; + exports net.sf.jsqlparser.expression.operators.conditional; + exports net.sf.jsqlparser.expression.operators.relational; + exports net.sf.jsqlparser.parser; + exports net.sf.jsqlparser.parser.feature; + exports net.sf.jsqlparser.schema; + exports net.sf.jsqlparser.statement; + exports net.sf.jsqlparser.statement.alter; + exports net.sf.jsqlparser.statement.alter.sequence; + exports net.sf.jsqlparser.statement.analyze; + exports net.sf.jsqlparser.statement.comment; + exports net.sf.jsqlparser.statement.create.function; + exports net.sf.jsqlparser.statement.create.index; + exports net.sf.jsqlparser.statement.create.procedure; + exports net.sf.jsqlparser.statement.create.schema; + exports net.sf.jsqlparser.statement.create.sequence; + exports net.sf.jsqlparser.statement.create.synonym; + exports net.sf.jsqlparser.statement.create.table; + exports net.sf.jsqlparser.statement.create.view; + exports net.sf.jsqlparser.statement.delete; + exports net.sf.jsqlparser.statement.drop; + exports net.sf.jsqlparser.statement.execute; + exports net.sf.jsqlparser.statement.grant; + exports net.sf.jsqlparser.statement.insert; + exports net.sf.jsqlparser.statement.merge; + exports net.sf.jsqlparser.statement.refresh; + exports net.sf.jsqlparser.statement.select; + exports net.sf.jsqlparser.statement.show; + exports net.sf.jsqlparser.statement.truncate; + exports net.sf.jsqlparser.statement.update; + exports net.sf.jsqlparser.statement.upsert; + exports net.sf.jsqlparser.util; + exports net.sf.jsqlparser.util.cnfexpression; + exports net.sf.jsqlparser.util.deparser; + exports net.sf.jsqlparser.util.validation; + exports net.sf.jsqlparser.util.validation.allowedtypes; + exports net.sf.jsqlparser.util.validation.feature; + exports net.sf.jsqlparser.util.validation.metadata; + exports net.sf.jsqlparser.util.validation.validator; +} diff --git a/src/main/java/net/sf/jsqlparser/Model.java b/src/main/java/net/sf/jsqlparser/Model.java index d96535bad..4ad52f429 100644 --- a/src/main/java/net/sf/jsqlparser/Model.java +++ b/src/main/java/net/sf/jsqlparser/Model.java @@ -12,8 +12,12 @@ import java.io.Serializable; /** - *

A marker interface for jsqlparser-model-classes.

- *

The datastructure where the sql syntax is represented by a tree consists of {@link Model}'s

+ *

+ * A marker interface for jsqlparser-model-classes. + *

+ *

+ * The datastructure where the sql syntax is represented by a tree consists of {@link Model}'s + *

*/ public interface Model extends Serializable { diff --git a/src/main/java/net/sf/jsqlparser/expression/Alias.java b/src/main/java/net/sf/jsqlparser/expression/Alias.java index 539d97eb2..cd50e12cc 100644 --- a/src/main/java/net/sf/jsqlparser/expression/Alias.java +++ b/src/main/java/net/sf/jsqlparser/expression/Alias.java @@ -16,6 +16,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; + import net.sf.jsqlparser.statement.create.table.ColDataType; public class Alias implements Serializable { @@ -62,14 +63,14 @@ public String toString() { String alias = (useAs ? " AS " : " ") + name; if (aliasColumns != null && !aliasColumns.isEmpty()) { - String ac = ""; + StringBuilder ac = new StringBuilder(); for (AliasColumn col : aliasColumns) { if (ac.length() > 0) { - ac += ", "; + ac.append(", "); } - ac += col.name; + ac.append(col.name); if (col.colDataType != null) { - ac += " " + col.colDataType.toString(); + ac.append(" ").append(col.colDataType.toString()); } } alias += "(" + ac + ")"; @@ -94,13 +95,15 @@ public Alias withAliasColumns(List aliasColumns) { } public Alias addAliasColumns(AliasColumn... aliasColumns) { - List collection = Optional.ofNullable(getAliasColumns()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getAliasColumns()).orElseGet(ArrayList::new); Collections.addAll(collection, aliasColumns); return this.withAliasColumns(collection); } public Alias addAliasColumns(Collection aliasColumns) { - List collection = Optional.ofNullable(getAliasColumns()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getAliasColumns()).orElseGet(ArrayList::new); collection.addAll(aliasColumns); return this.withAliasColumns(collection); } diff --git a/src/main/java/net/sf/jsqlparser/expression/AllValue.java b/src/main/java/net/sf/jsqlparser/expression/AllValue.java index 39c64fb75..14f924ab8 100644 --- a/src/main/java/net/sf/jsqlparser/expression/AllValue.java +++ b/src/main/java/net/sf/jsqlparser/expression/AllValue.java @@ -14,8 +14,8 @@ public class AllValue 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/AnalyticExpression.java b/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java index fc7d7d466..4cbb4e1d0 100644 --- a/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java @@ -11,6 +11,7 @@ import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import net.sf.jsqlparser.statement.select.Limit; import net.sf.jsqlparser.statement.select.OrderByElement; import java.util.List; @@ -19,14 +20,14 @@ /** * Analytic function. The name of the function is variable but the parameters following the special - * analytic function path. e.g. row_number() over (order by test). Additional there can be an - * expression for an analytical aggregate like sum(col) or the "all collumns" wildcard like - * count(*). + * analytic function path. e.g. row_number() over (order by test). Additionally, there can be an + * expression for an analytical aggregate like sum(col) or the "all columns" wildcard like count(*). * * @author tw */ public class AnalyticExpression extends ASTNodeAccessImpl implements Expression { + private String name; private Expression expression; private Expression offset; @@ -36,45 +37,55 @@ public class AnalyticExpression extends ASTNodeAccessImpl implements Expression private AnalyticType type = AnalyticType.OVER; private boolean distinct = false; private boolean unique = false; - private boolean ignoreNulls = false; // IGNORE NULLS inside function parameters private boolean ignoreNullsOutside = false; // IGNORE NULLS outside function parameters private Expression filterExpression = null; private List funcOrderBy = null; private String windowName = null; // refers to an external window definition (paritionBy, - // orderBy, windowElement) + // orderBy, windowElement) private WindowDefinition windowDef = new WindowDefinition(); + private Function.HavingClause havingClause; + + private Function.NullHandling nullHandling = null; + + private Limit limit = null; + public AnalyticExpression() {} public AnalyticExpression(Function function) { - name = function.getName(); - allColumns = function.isAllColumns(); - distinct = function.isDistinct(); - unique = function.isUnique(); - funcOrderBy = function.getOrderByElements(); + this.name = String.join(" ", function.getMultipartName()); + this.allColumns = function.isAllColumns(); + this.distinct = function.isDistinct(); + this.unique = function.isUnique(); + ExpressionList list = function.getParameters(); if (list != null) { - if (list.getExpressions().size() > 3) { + if (list.size() > 3) { throw new IllegalArgumentException( "function object not valid to initialize analytic expression"); } expression = list.get(0); - if (list.getExpressions().size() > 1) { + if (list.size() > 1) { offset = list.get(1); } - if (list.getExpressions().size() > 2) { + if (list.size() > 2) { defaultValue = list.get(2); } } - ignoreNulls = function.isIgnoreNulls(); - keep = function.getKeep(); + this.havingClause = function.getHavingClause(); + this.ignoreNullsOutside = function.isIgnoreNullsOutside(); + this.nullHandling = function.getNullHandling(); + this.funcOrderBy = function.getOrderByElements(); + this.limit = function.getLimit(); + this.keep = function.getKeep(); } + @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } public List getOrderByElements() { @@ -93,15 +104,15 @@ public void setKeep(KeepExpression keep) { this.keep = keep; } - public ExpressionList getPartitionExpressionList() { + public ExpressionList getPartitionExpressionList() { return windowDef.partitionBy.getPartitionExpressionList(); } - public void setPartitionExpressionList(ExpressionList partitionExpressionList) { + public void setPartitionExpressionList(ExpressionList partitionExpressionList) { setPartitionExpressionList(partitionExpressionList, false); } - public void setPartitionExpressionList(ExpressionList partitionExpressionList, + public void setPartitionExpressionList(ExpressionList partitionExpressionList, boolean brackets) { windowDef.partitionBy.setPartitionExpressionList(partitionExpressionList, brackets); } @@ -175,11 +186,11 @@ public void setUnique(boolean unique) { } public boolean isIgnoreNulls() { - return ignoreNulls; + return this.nullHandling == Function.NullHandling.IGNORE_NULLS; } public void setIgnoreNulls(boolean ignoreNulls) { - this.ignoreNulls = ignoreNulls; + this.nullHandling = ignoreNulls ? Function.NullHandling.IGNORE_NULLS : null; } public boolean isIgnoreNullsOutside() { @@ -206,6 +217,41 @@ public void setWindowDefinition(WindowDefinition windowDef) { this.windowDef = windowDef; } + + public Function.HavingClause getHavingClause() { + return havingClause; + } + + public AnalyticExpression setHavingClause(Function.HavingClause havingClause) { + this.havingClause = havingClause; + return this; + } + + public AnalyticExpression setHavingClause(String havingType, Expression expression) { + this.havingClause = new Function.HavingClause( + Function.HavingClause.HavingType.valueOf(havingType.trim().toUpperCase()), + expression); + return this; + } + + public Function.NullHandling getNullHandling() { + return nullHandling; + } + + public AnalyticExpression setNullHandling(Function.NullHandling nullHandling) { + this.nullHandling = nullHandling; + return this; + } + + public Limit getLimit() { + return limit; + } + + public AnalyticExpression setLimit(Limit limit) { + this.limit = limit; + return this; + } + @Override @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity", "PMD.MissingBreakInSwitch"}) @@ -217,40 +263,64 @@ public String toString() { b.append("DISTINCT "); } if (expression != null) { - b.append(expression.toString()); + b.append(expression); if (offset != null) { - b.append(", ").append(offset.toString()); + b.append(", ").append(offset); if (defaultValue != null) { - b.append(", ").append(defaultValue.toString()); + b.append(", ").append(defaultValue); } } } else if (isAllColumns()) { b.append("*"); } - if (isIgnoreNulls()) { - b.append(" IGNORE NULLS"); + + if (havingClause != null) { + havingClause.appendTo(b); + } + + if (nullHandling != null && !ignoreNullsOutside) { + switch (nullHandling) { + case IGNORE_NULLS: + b.append(" IGNORE NULLS"); + break; + case RESPECT_NULLS: + b.append(" RESPECT NULLS"); + break; + } } + if (funcOrderBy != null) { b.append(" ORDER BY "); b.append(funcOrderBy.stream().map(OrderByElement::toString).collect(joining(", "))); } + if (limit != null) { + b.append(limit); + } + b.append(") "); if (keep != null) { - b.append(keep.toString()).append(" "); + b.append(keep).append(" "); } if (filterExpression != null) { b.append("FILTER (WHERE "); - b.append(filterExpression.toString()); + b.append(filterExpression); b.append(")"); if (type != AnalyticType.FILTER_ONLY) { b.append(" "); } } - if (isIgnoreNullsOutside()) { - b.append("IGNORE NULLS "); + if (nullHandling != null && ignoreNullsOutside) { + switch (nullHandling) { + case IGNORE_NULLS: + b.append(" IGNORE NULLS "); + break; + case RESPECT_NULLS: + b.append(" RESPECT NULLS "); + break; + } } switch (type) { diff --git a/src/main/java/net/sf/jsqlparser/expression/AnyComparisonExpression.java b/src/main/java/net/sf/jsqlparser/expression/AnyComparisonExpression.java index f7a9368c0..cf3ba46d5 100644 --- a/src/main/java/net/sf/jsqlparser/expression/AnyComparisonExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/AnyComparisonExpression.java @@ -32,8 +32,8 @@ public Select getSelect() { @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } public AnyType getAnyType() { diff --git a/src/main/java/net/sf/jsqlparser/expression/ArrayConstructor.java b/src/main/java/net/sf/jsqlparser/expression/ArrayConstructor.java index 267708dc4..c7fe031ab 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ArrayConstructor.java +++ b/src/main/java/net/sf/jsqlparser/expression/ArrayConstructor.java @@ -16,6 +16,15 @@ public class ArrayConstructor extends ASTNodeAccessImpl implements Expression { private ExpressionList expressions; private boolean arrayKeyword; + public ArrayConstructor(ExpressionList expressions, boolean arrayKeyword) { + this.expressions = expressions; + this.arrayKeyword = arrayKeyword; + } + + public ArrayConstructor(Expression... expressions) { + this(new ExpressionList(expressions), false); + } + public ExpressionList getExpressions() { return expressions; } @@ -32,14 +41,9 @@ public void setArrayKeyword(boolean arrayKeyword) { this.arrayKeyword = arrayKeyword; } - public ArrayConstructor(ExpressionList expressions, boolean arrayKeyword) { - this.expressions = expressions; - this.arrayKeyword = arrayKeyword; - } - @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/ArrayExpression.java b/src/main/java/net/sf/jsqlparser/expression/ArrayExpression.java index aef63b8f6..e86f34cad 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ArrayExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/ArrayExpression.java @@ -23,13 +23,23 @@ public ArrayExpression() { // empty constructor } - public ArrayExpression(Expression objExpression, Expression indexExpression, Expression startIndexExpression, Expression stopIndexExpression) { + public ArrayExpression(Expression objExpression, Expression indexExpression, + Expression startIndexExpression, Expression stopIndexExpression) { this.objExpression = objExpression; this.indexExpression = indexExpression; this.startIndexExpression = startIndexExpression; this.stopIndexExpression = stopIndexExpression; } + public ArrayExpression(Expression objExpression, Expression indexExpression) { + this(objExpression, indexExpression, null, null); + } + + public ArrayExpression(Expression objExpression, Expression startIndexExpression, + Expression stopIndexExpression) { + this(objExpression, null, startIndexExpression, stopIndexExpression); + } + public Expression getObjExpression() { return objExpression; } @@ -63,8 +73,8 @@ public void setStopIndexExpression(Expression stopIndexExpression) { } @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } @Override @@ -90,7 +100,8 @@ public ArrayExpression withIndexExpression(Expression indexExpression) { return this; } - public ArrayExpression withRangeExpression(Expression startIndexExpression, Expression stopIndexExpression) { + public ArrayExpression withRangeExpression(Expression startIndexExpression, + Expression stopIndexExpression) { this.setStartIndexExpression(startIndexExpression); this.setStopIndexExpression(stopIndexExpression); return this; diff --git a/src/main/java/net/sf/jsqlparser/expression/BinaryExpression.java b/src/main/java/net/sf/jsqlparser/expression/BinaryExpression.java index 848783206..ffd9c2d84 100644 --- a/src/main/java/net/sf/jsqlparser/expression/BinaryExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/BinaryExpression.java @@ -9,8 +9,27 @@ */ package net.sf.jsqlparser.expression; +import net.sf.jsqlparser.expression.operators.arithmetic.Addition; +import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd; +import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift; +import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr; +import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseRightShift; +import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor; +import net.sf.jsqlparser.expression.operators.arithmetic.Concat; +import net.sf.jsqlparser.expression.operators.arithmetic.Division; +import net.sf.jsqlparser.expression.operators.arithmetic.IntegerDivision; +import net.sf.jsqlparser.expression.operators.arithmetic.Modulo; +import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication; +import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.conditional.XorExpression; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.Iterator; + /** * A basic class for binary expressions, that is expressions having a left member and a right member * which are in turn expressions. @@ -20,39 +39,219 @@ public abstract class BinaryExpression extends ASTNodeAccessImpl implements Expr private Expression leftExpression; private Expression rightExpression; - public BinaryExpression() { + public BinaryExpression() {} + + public BinaryExpression(Expression leftExpression, Expression rightExpression) { + this.leftExpression = leftExpression; + this.rightExpression = rightExpression; + } + + public static Expression build(Class clz, Expression... expressions) + throws NoSuchMethodException, InvocationTargetException, InstantiationException, + IllegalAccessException { + switch (expressions.length) { + case 0: + return new NullValue(); + case 1: + return expressions[0]; + default: + Iterator it = Arrays.stream(expressions).iterator(); + + Expression leftExpression = it.next(); + Expression rightExpression = it.next(); + BinaryExpression binaryExpression = + clz.getConstructor(Expression.class, Expression.class) + .newInstance(leftExpression, rightExpression); + + while (it.hasNext()) { + rightExpression = it.next(); + binaryExpression = clz.getConstructor(Expression.class, Expression.class) + .newInstance(binaryExpression, rightExpression); + } + return binaryExpression; + } + } + + public static Expression add(Expression... expressions) { + try { + return build(Addition.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression bitAnd(Expression... expressions) { + try { + return build(BitwiseAnd.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression bitShiftLeft(Expression... expressions) { + try { + return build(BitwiseLeftShift.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression multiply(Expression... expressions) { + try { + return build(Multiplication.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression bitOr(Expression... expressions) { + try { + return build(BitwiseOr.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression bitShiftRight(Expression... expressions) { + try { + return build(BitwiseRightShift.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression bitXor(Expression... expressions) { + try { + return build(BitwiseXor.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression concat(Expression... expressions) { + try { + return build(Concat.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression divide(Expression... expressions) { + try { + return build(Division.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression divideInt(Expression... expressions) { + try { + return build(IntegerDivision.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression modulo(Expression... expressions) { + try { + return build(Modulo.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression subtract(Expression... expressions) { + try { + return build(Subtraction.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression or(Expression... expressions) { + try { + return build(OrExpression.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression xor(Expression... expressions) { + try { + return build(XorExpression.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression and(Expression... expressions) { + try { + return build(AndExpression.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } } public Expression getLeftExpression() { return leftExpression; } + public void setLeftExpression(Expression expression) { + leftExpression = expression; + } + public Expression getRightExpression() { return rightExpression; } + public void setRightExpression(Expression expression) { + rightExpression = expression; + } + public BinaryExpression withLeftExpression(Expression expression) { setLeftExpression(expression); return this; } - public void setLeftExpression(Expression expression) { - leftExpression = expression; - } - public BinaryExpression withRightExpression(Expression expression) { setRightExpression(expression); return this; } - public void setRightExpression(Expression expression) { - rightExpression = expression; - } - @Override public String toString() { return // (not ? "NOT " : "") + - getLeftExpression() + " " + getStringExpression() + " " + getRightExpression(); + getLeftExpression() + " " + getStringExpression() + " " + getRightExpression(); } public abstract String getStringExpression(); diff --git a/src/main/java/net/sf/jsqlparser/expression/CaseExpression.java b/src/main/java/net/sf/jsqlparser/expression/CaseExpression.java index 371c40bf0..10fd7d56d 100644 --- a/src/main/java/net/sf/jsqlparser/expression/CaseExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/CaseExpression.java @@ -10,36 +10,43 @@ package net.sf.jsqlparser.expression; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; + import net.sf.jsqlparser.parser.ASTNodeAccessImpl; import net.sf.jsqlparser.statement.select.PlainSelect; /** * CASE/WHEN expression. + *

+ * Syntax: * - * Syntax:


+ * 
+ * 
  * CASE
  * WHEN condition THEN expression
  * [WHEN condition THEN expression]...
  * [ELSE expression]
  * END
- * 
+ *
+ *
* *
* or
*
* - *

+ * 
+ * 
  * CASE expression
  * WHEN condition THEN expression
  * [WHEN condition THEN expression]...
  * [ELSE expression]
  * END
- * 
- * + *
+ *
*/ public class CaseExpression extends ASTNodeAccessImpl implements Expression { @@ -48,9 +55,21 @@ public class CaseExpression extends ASTNodeAccessImpl implements Expression { private List whenClauses; private Expression elseExpression; + public CaseExpression() {} + + public CaseExpression(WhenClause... whenClauses) { + this.whenClauses = Arrays.asList(whenClauses); + } + + public CaseExpression(Expression elseExpression, WhenClause... whenClauses) { + this.elseExpression = elseExpression; + this.whenClauses = Arrays.asList(whenClauses); + } + + @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } public Expression getSwitchExpression() { @@ -91,9 +110,11 @@ public void setWhenClauses(List whenClauses) { @Override public String toString() { - return (usingBrackets ? "(" : "") + "CASE " + ((switchExpression != null) ? switchExpression + " " : "") + return (usingBrackets ? "(" : "") + "CASE " + + ((switchExpression != null) ? switchExpression + " " : "") + PlainSelect.getStringList(whenClauses, false, false) + " " - + ((elseExpression != null) ? "ELSE " + elseExpression + " " : "") + "END" + (usingBrackets ? ")" : ""); + + ((elseExpression != null) ? "ELSE " + elseExpression + " " : "") + "END" + + (usingBrackets ? ")" : ""); } public CaseExpression withSwitchExpression(Expression switchExpression) { @@ -101,6 +122,10 @@ public CaseExpression withSwitchExpression(Expression switchExpression) { return this; } + public CaseExpression withWhenClauses(WhenClause... whenClauses) { + return this.withWhenClauses(Arrays.asList(whenClauses)); + } + public CaseExpression withWhenClauses(List whenClauses) { this.setWhenClauses(whenClauses); return this; @@ -112,13 +137,15 @@ public CaseExpression withElseExpression(Expression elseExpression) { } public CaseExpression addWhenClauses(WhenClause... whenClauses) { - List collection = Optional.ofNullable(getWhenClauses()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getWhenClauses()).orElseGet(ArrayList::new); Collections.addAll(collection, whenClauses); return this.withWhenClauses(collection); } public CaseExpression addWhenClauses(Collection whenClauses) { - List collection = Optional.ofNullable(getWhenClauses()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getWhenClauses()).orElseGet(ArrayList::new); collection.addAll(whenClauses); return this.withWhenClauses(collection); } @@ -131,25 +158,25 @@ public E getElseExpression(Class type) { return type.cast(getElseExpression()); } - /** - * @return the usingBrackets - */ - public boolean isUsingBrackets() { - return usingBrackets; - } - - /** - * @param usingBrackets the usingBrackets to set - */ - public void setUsingBrackets(boolean usingBrackets) { - this.usingBrackets = usingBrackets; - } - - /** - * @param usingBrackets the usingBrackets to set - */ - public CaseExpression withUsingBrackets(boolean usingBrackets) { - this.usingBrackets=usingBrackets; - return this; + /** + * @return the usingBrackets + */ + public boolean isUsingBrackets() { + return usingBrackets; + } + + /** + * @param usingBrackets the usingBrackets to set + */ + public void setUsingBrackets(boolean usingBrackets) { + this.usingBrackets = usingBrackets; + } + + /** + * @param usingBrackets the usingBrackets to set + */ + public CaseExpression withUsingBrackets(boolean usingBrackets) { + this.usingBrackets = usingBrackets; + return this; } } diff --git a/src/main/java/net/sf/jsqlparser/expression/CastExpression.java b/src/main/java/net/sf/jsqlparser/expression/CastExpression.java index d928a26b2..8325e493a 100644 --- a/src/main/java/net/sf/jsqlparser/expression/CastExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/CastExpression.java @@ -15,14 +15,68 @@ import net.sf.jsqlparser.statement.select.Select; import java.util.ArrayList; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class CastExpression extends ASTNodeAccessImpl implements Expression { + private final static Pattern PATTERN = + Pattern.compile("(^[a-z0-9_]*){1}", Pattern.CASE_INSENSITIVE); public String keyword; private Expression leftExpression; private ColDataType colDataType = null; private ArrayList columnDefinitions = new ArrayList<>(); - private boolean useCastKeyword = true; + + private boolean isImplicitCast = false; + + // BigQuery specific FORMAT clause: + // https://cloud.google.com/bigquery/docs/reference/standard-sql/conversion_functions#cast_as_date + private String format = null; + + public CastExpression(String keyword, Expression leftExpression, String dataType) { + this.keyword = keyword; + this.leftExpression = leftExpression; + this.colDataType = new ColDataType(dataType); + } + + // Implicit Cast + public CastExpression(String dataType, String value) { + this.keyword = null; + this.isImplicitCast = true; + this.colDataType = new ColDataType(dataType); + this.leftExpression = new StringValue(value); + } + + public CastExpression(ColDataType colDataType, String value) { + this.keyword = null; + this.isImplicitCast = true; + this.colDataType = colDataType; + this.leftExpression = new StringValue(value); + } + + public CastExpression(ColDataType colDataType, Long value) { + this.keyword = null; + this.isImplicitCast = true; + this.colDataType = colDataType; + this.leftExpression = new LongValue(value); + } + + public CastExpression(ColDataType colDataType, Double value) { + this.keyword = null; + this.isImplicitCast = true; + this.colDataType = colDataType; + this.leftExpression = new DoubleValue(value); + } + + public CastExpression(Expression leftExpression, String dataType) { + this.keyword = null; + this.leftExpression = leftExpression; + this.colDataType = new ColDataType(dataType); + } + public CastExpression(String keyword) { this.keyword = keyword; @@ -32,18 +86,64 @@ public CastExpression() { this("CAST"); } - public ColDataType getColDataType() { - return colDataType; + public static boolean isOf(ColDataType colDataType, DataType... types) { + return Set.of(types).contains(DataType.from(colDataType.getDataType())); } - public ArrayList getColumnDefinitions() { - return columnDefinitions; + public static boolean isTime(ColDataType colDataType) { + return isOf(colDataType, DataType.TIME, DataType.TIME_WITH_TIME_ZONE, + DataType.TIME_WITHOUT_TIME_ZONE); + } + + public static boolean isTimeStamp(ColDataType colDataType) { + return isOf(colDataType, DataType.TIMESTAMP_NS, DataType.TIMESTAMP, + DataType.TIMESTAMP_WITHOUT_TIME_ZONE, + DataType.DATETIME, DataType.TIMESTAMP_MS, DataType.TIMESTAMP_S, + DataType.TIMESTAMPTZ, DataType.TIMESTAMP_WITH_TIME_ZONE); + } + + public static boolean isDate(ColDataType colDataType) { + return isOf(colDataType, DataType.DATE); + } + + public static boolean isBLOB(ColDataType colDataType) { + return isOf(colDataType, DataType.BLOB, DataType.BYTEA, DataType.BINARY, DataType.VARBINARY, + DataType.BYTES, DataType.VARBYTE); + } + + public static boolean isFloat(ColDataType colDataType) { + return isOf(colDataType, DataType.REAL, DataType.FLOAT4, DataType.FLOAT, DataType.DOUBLE, + DataType.DOUBLE_PRECISION, DataType.FLOAT8); + } + + public static boolean isInteger(ColDataType colDataType) { + return isOf(colDataType, DataType.TINYINT, DataType.INT1, DataType.SMALLINT, DataType.INT2, + DataType.SHORT, DataType.INTEGER, DataType.INT4, DataType.INT, DataType.SIGNED, + DataType.BIGINT, DataType.INT8, DataType.LONG, DataType.HUGEINT, DataType.UTINYINT, + DataType.USMALLINT, DataType.UINTEGER, DataType.UBIGINT, DataType.UHUGEINT); + } + + public static boolean isDecimal(ColDataType colDataType) { + return isOf(colDataType, DataType.DECIMAL, DataType.NUMBER, DataType.NUMERIC); + } + + public static boolean isText(ColDataType colDataType) { + return isOf(colDataType, DataType.VARCHAR, DataType.NVARCHAR, DataType.CHAR, DataType.NCHAR, + DataType.BPCHAR, DataType.STRING, DataType.TEXT, DataType.CLOB); + } + + public ColDataType getColDataType() { + return colDataType; } public void setColDataType(ColDataType colDataType) { this.colDataType = colDataType; } + public ArrayList getColumnDefinitions() { + return columnDefinitions; + } + public void addColumnDefinition(ColumnDefinition columnDefinition) { this.columnDefinitions.add(columnDefinition); } @@ -56,26 +156,58 @@ public void setLeftExpression(Expression expression) { leftExpression = expression; } + public boolean isImplicitCast() { + return isImplicitCast; + } + + public CastExpression setImplicitCast(boolean implicitCast) { + isImplicitCast = implicitCast; + return this; + } + @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } + @Deprecated public boolean isUseCastKeyword() { - return useCastKeyword; + return keyword != null && !keyword.isEmpty(); } + @Deprecated public void setUseCastKeyword(boolean useCastKeyword) { - this.useCastKeyword = useCastKeyword; + if (useCastKeyword) { + if (keyword == null || keyword.isEmpty()) { + keyword = "CAST"; + } + } else { + keyword = null; + } + } + + public String getFormat() { + return format; + } + + public CastExpression setFormat(String format) { + this.format = format; + return this; } @Override public String toString() { - if (useCastKeyword) { + String formatStr = format != null && !format.isEmpty() + ? " FORMAT " + format + : ""; + if (isImplicitCast) { + return colDataType + " " + leftExpression; + } else if (keyword != null && !keyword.isEmpty()) { return columnDefinitions.size() > 1 ? keyword + "(" + leftExpression + " AS ROW(" - + Select.getStringList(columnDefinitions) + "))" - : keyword + "(" + leftExpression + " AS " + colDataType.toString() + ")"; + + Select.getStringList(columnDefinitions) + ")" + formatStr + ")" + : keyword + "(" + leftExpression + " AS " + colDataType.toString() + formatStr + + ")"; } else { return leftExpression + "::" + colDataType.toString(); } @@ -99,4 +231,65 @@ public CastExpression withLeftExpression(Expression leftExpression) { public E getLeftExpression(Class type) { return type.cast(getLeftExpression()); } + + public boolean isOf(CastExpression anotherCast) { + return this.colDataType.equals(anotherCast.colDataType); + } + + public boolean isOf(DataType... types) { + return Set.of(types).contains(DataType.from(colDataType.getDataType())); + } + + public boolean isTime() { + return isTime(this.colDataType); + } + + public boolean isTimeStamp() { + return isTimeStamp(this.colDataType); + } + + public boolean isDate() { + return isDate(this.colDataType); + } + + public boolean isBLOB() { + return isBLOB(this.colDataType); + } + + public boolean isFloat() { + return isFloat(this.colDataType); + } + + public boolean isInteger() { + return isInteger(this.colDataType); + } + + public boolean isDecimal() { + return isDecimal(this.colDataType); + } + + public boolean isText() { + return isText(this.colDataType); + } + + public enum DataType { + ARRAY, BIT, BITSTRING, BLOB, BYTEA, BINARY, VARBINARY, BYTES, BOOLEAN, BOOL, ENUM, INTERVAL, LIST, MAP, STRUCT, TINYINT, INT1, SMALLINT, INT2, SHORT, INTEGER, INT4, INT, SIGNED, BIGINT, INT8, LONG, HUGEINT, UTINYINT, USMALLINT, UINTEGER, UBIGINT, UHUGEINT, DECIMAL, NUMBER, NUMERIC, REAL, FLOAT4, FLOAT, DOUBLE, DOUBLE_PRECISION, FLOAT8, FLOAT64, UUID, VARCHAR, NVARCHAR, CHAR, NCHAR, BPCHAR, STRING, TEXT, CLOB, DATE, TIME, TIME_WITHOUT_TIME_ZONE, TIMETZ, TIME_WITH_TIME_ZONE, TIMESTAMP_NS, TIMESTAMP, TIMESTAMP_WITHOUT_TIME_ZONE, DATETIME, TIMESTAMP_MS, TIMESTAMP_S, TIMESTAMPTZ, TIMESTAMP_WITH_TIME_ZONE, UNKNOWN, VARBYTE; + + public static DataType from(String typeStr) { + Matcher matcher = PATTERN.matcher(typeStr.trim().replaceAll("\\s+", "_").toUpperCase()); + if (matcher.find()) { + try { + return Enum.valueOf(DataType.class, matcher.group(0)); + } catch (Exception ex) { + Logger.getLogger(CastExpression.class.getName()).log(Level.FINE, + "Type " + typeStr + " unknown", ex); + return DataType.UNKNOWN; + } + } else { + Logger.getLogger(CastExpression.class.getName()).log(Level.FINE, + "Type " + typeStr + " unknown"); + return DataType.UNKNOWN; + } + } + } } diff --git a/src/main/java/net/sf/jsqlparser/expression/CollateExpression.java b/src/main/java/net/sf/jsqlparser/expression/CollateExpression.java index 07c2b8616..8a419b241 100644 --- a/src/main/java/net/sf/jsqlparser/expression/CollateExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/CollateExpression.java @@ -26,8 +26,8 @@ public CollateExpression(Expression leftExpression, String collate) { } @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } public Expression getLeftExpression() { diff --git a/src/main/java/net/sf/jsqlparser/expression/ConnectByRootOperator.java b/src/main/java/net/sf/jsqlparser/expression/ConnectByRootOperator.java index 817023422..6942f0787 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ConnectByRootOperator.java +++ b/src/main/java/net/sf/jsqlparser/expression/ConnectByRootOperator.java @@ -26,18 +26,19 @@ package net.sf.jsqlparser.expression; import java.util.Objects; + import net.sf.jsqlparser.parser.ASTNodeAccessImpl; import net.sf.jsqlparser.schema.Column; /** - * * @author are */ public class ConnectByRootOperator extends ASTNodeAccessImpl implements Expression { private final Column column; public ConnectByRootOperator(Column column) { - this.column = Objects.requireNonNull(column, "The COLUMN of the ConnectByRoot Operator must not be null"); + this.column = Objects.requireNonNull(column, + "The COLUMN of the ConnectByRoot Operator must not be null"); } public Column getColumn() { @@ -45,15 +46,15 @@ public Column getColumn() { } @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } - + public StringBuilder appendTo(StringBuilder builder) { builder.append("CONNECT_BY_ROOT ").append(column); return builder; } - + @Override public String toString() { return appendTo(new StringBuilder()).toString(); diff --git a/src/main/java/net/sf/jsqlparser/expression/DateTimeLiteralExpression.java b/src/main/java/net/sf/jsqlparser/expression/DateTimeLiteralExpression.java index 9290e882b..3510fe6d3 100644 --- a/src/main/java/net/sf/jsqlparser/expression/DateTimeLiteralExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/DateTimeLiteralExpression.java @@ -33,8 +33,8 @@ public void setType(DateTime type) { } @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } @Override @@ -53,7 +53,7 @@ public DateTimeLiteralExpression withType(DateTime type) { } public enum DateTime { - DATE, TIME, TIMESTAMP, TIMESTAMPTZ; + DATE, DATETIME, TIME, TIMESTAMP, TIMESTAMPTZ; public static DateTime from(String dateTimeStr) { return Enum.valueOf(DateTime.class, dateTimeStr.toUpperCase()); diff --git a/src/main/java/net/sf/jsqlparser/expression/DateValue.java b/src/main/java/net/sf/jsqlparser/expression/DateValue.java index 8c28a5fdd..d03a73c66 100644 --- a/src/main/java/net/sf/jsqlparser/expression/DateValue.java +++ b/src/main/java/net/sf/jsqlparser/expression/DateValue.java @@ -38,8 +38,8 @@ public DateValue(String value) { } @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } public Date getValue() { diff --git a/src/main/java/net/sf/jsqlparser/expression/DoubleValue.java b/src/main/java/net/sf/jsqlparser/expression/DoubleValue.java index 910ad722e..8d25aa61a 100644 --- a/src/main/java/net/sf/jsqlparser/expression/DoubleValue.java +++ b/src/main/java/net/sf/jsqlparser/expression/DoubleValue.java @@ -16,7 +16,7 @@ */ public class DoubleValue extends ASTNodeAccessImpl implements Expression { - private double value; + private Double value; private String stringValue; public DoubleValue() { @@ -35,17 +35,23 @@ public DoubleValue(final String value) { this.stringValue = val; } + public DoubleValue(final double value) { + this.value = value; + this.stringValue = String.valueOf(value); + } + @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } public double getValue() { return value; } - public void setValue(double d) { + public void setValue(Double d) { value = d; + stringValue = String.valueOf(value); } @Override @@ -53,7 +59,7 @@ public String toString() { return stringValue; } - public DoubleValue withValue(double value) { + public DoubleValue withValue(Double value) { this.setValue(value); return this; } diff --git a/src/main/java/net/sf/jsqlparser/expression/Expression.java b/src/main/java/net/sf/jsqlparser/expression/Expression.java index daeb2da83..a4807583a 100644 --- a/src/main/java/net/sf/jsqlparser/expression/Expression.java +++ b/src/main/java/net/sf/jsqlparser/expression/Expression.java @@ -14,6 +14,13 @@ public interface Expression extends ASTNodeAccess, Model { - void accept(ExpressionVisitor expressionVisitor); + T accept(ExpressionVisitor expressionVisitor, S context); + + default void accept(ExpressionVisitor expressionVisitor) { + this.accept(expressionVisitor, null); + } + + ; + } diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java index d0fe61a91..985547fc6 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java @@ -29,6 +29,7 @@ import net.sf.jsqlparser.expression.operators.relational.Contains; import net.sf.jsqlparser.expression.operators.relational.DoubleAnd; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; +import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression; import net.sf.jsqlparser.expression.operators.relational.ExistsExpression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.FullTextSearch; @@ -36,6 +37,7 @@ import net.sf.jsqlparser.expression.operators.relational.GreaterThan; import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals; import net.sf.jsqlparser.expression.operators.relational.InExpression; +import net.sf.jsqlparser.expression.operators.relational.IncludesExpression; import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression; import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression; import net.sf.jsqlparser.expression.operators.relational.IsNullExpression; @@ -56,194 +58,587 @@ import net.sf.jsqlparser.statement.select.ParenthesedSelect; import net.sf.jsqlparser.statement.select.Select; -public interface ExpressionVisitor { +public interface ExpressionVisitor { - void visit(BitwiseRightShift aThis); + T visit(BitwiseRightShift bitwiseRightShift, S context); - void visit(BitwiseLeftShift aThis); + default void visit(BitwiseRightShift bitwiseRightShift) { + this.visit(bitwiseRightShift, null); + } - void visit(NullValue nullValue); + T visit(BitwiseLeftShift bitwiseLeftShift, S context); - void visit(Function function); + default void visit(BitwiseLeftShift bitwiseLeftShift) { + this.visit(bitwiseLeftShift, null); + } - void visit(SignedExpression signedExpression); + T visit(NullValue nullValue, S context); - void visit(JdbcParameter jdbcParameter); + default void visit(NullValue nullValue) { + this.visit(nullValue, null); + } - void visit(JdbcNamedParameter jdbcNamedParameter); + T visit(Function function, S context); - void visit(DoubleValue doubleValue); + default void visit(Function function) { + this.visit(function, null); + } - void visit(LongValue longValue); + T visit(SignedExpression signedExpression, S context); - void visit(HexValue hexValue); + default void visit(SignedExpression signedExpression) { + this.visit(signedExpression, null); + } - void visit(DateValue dateValue); + T visit(JdbcParameter jdbcParameter, S context); - void visit(TimeValue timeValue); + default void visit(JdbcParameter jdbcParameter) { + this.visit(jdbcParameter, null); + } - void visit(TimestampValue timestampValue); + T visit(JdbcNamedParameter jdbcNamedParameter, S context); - void visit(Parenthesis parenthesis); + default void visit(JdbcNamedParameter jdbcNamedParameter) { + this.visit(jdbcNamedParameter, null); + } - void visit(StringValue stringValue); + T visit(DoubleValue doubleValue, S context); - void visit(Addition addition); + default void visit(DoubleValue doubleValue) { + this.visit(doubleValue, null); + } - void visit(Division division); + T visit(LongValue longValue, S context); - void visit(IntegerDivision division); + default void visit(LongValue longValue) { + this.visit(longValue, null); + } - void visit(Multiplication multiplication); + T visit(HexValue hexValue, S context); - void visit(Subtraction subtraction); + default void visit(HexValue hexValue) { + this.visit(hexValue, null); + } - void visit(AndExpression andExpression); + T visit(DateValue dateValue, S context); - void visit(OrExpression orExpression); + default void visit(DateValue dateValue) { + this.visit(dateValue, null); + } - void visit(XorExpression orExpression); + T visit(TimeValue timeValue, S context); - void visit(Between between); + default void visit(TimeValue timeValue) { + this.visit(timeValue, null); + } - void visit(OverlapsCondition overlapsCondition); + T visit(TimestampValue timestampValue, S context); - void visit(EqualsTo equalsTo); + default void visit(TimestampValue timestampValue) { + this.visit(timestampValue, null); + } - void visit(GreaterThan greaterThan); + T visit(StringValue stringValue, S context); - void visit(GreaterThanEquals greaterThanEquals); + default void visit(StringValue stringValue) { + this.visit(stringValue, null); + } - void visit(InExpression inExpression); + T visit(Addition addition, S context); - void visit(FullTextSearch fullTextSearch); + default void visit(Addition addition) { + this.visit(addition, null); + } - void visit(IsNullExpression isNullExpression); + T visit(Division division, S context); - void visit(IsBooleanExpression isBooleanExpression); + default void visit(Division division) { + this.visit(division, null); + } - void visit(LikeExpression likeExpression); + T visit(IntegerDivision integerDivision, S context); - void visit(MinorThan minorThan); + default void visit(IntegerDivision integerDivision) { + this.visit(integerDivision, null); + } - void visit(MinorThanEquals minorThanEquals); + T visit(Multiplication multiplication, S context); - void visit(NotEqualsTo notEqualsTo); + default void visit(Multiplication multiplication) { + this.visit(multiplication, null); + } - void visit(DoubleAnd doubleAnd); + T visit(Subtraction subtraction, S context); - void visit(Contains contains); + default void visit(Subtraction subtraction) { + this.visit(subtraction, null); + } - void visit(ContainedBy containedBy); + T visit(AndExpression andExpression, S context); - void visit(ParenthesedSelect selectBody); + default void visit(AndExpression andExpression) { + this.visit(andExpression, null); + } - void visit(Column tableColumn); + T visit(OrExpression orExpression, S context); - void visit(CaseExpression caseExpression); + default void visit(OrExpression orExpression) { + this.visit(orExpression, null); + } - void visit(WhenClause whenClause); + T visit(XorExpression xorExpression, S context); - void visit(ExistsExpression existsExpression); + default void visit(XorExpression xorExpression) { + this.visit(xorExpression, null); + } - void visit(MemberOfExpression memberOfExpression); + T visit(Between between, S context); - void visit(AnyComparisonExpression anyComparisonExpression); + default void visit(Between between) { + this.visit(between, null); + } - void visit(Concat concat); + T visit(OverlapsCondition overlapsCondition, S context); - void visit(Matches matches); + default void visit(OverlapsCondition overlapsCondition) { + this.visit(overlapsCondition, null); + } - void visit(BitwiseAnd bitwiseAnd); + T visit(EqualsTo equalsTo, S context); - void visit(BitwiseOr bitwiseOr); + default void visit(EqualsTo equalsTo) { + this.visit(equalsTo, null); + } - void visit(BitwiseXor bitwiseXor); + T visit(GreaterThan greaterThan, S context); - void visit(CastExpression cast); + default void visit(GreaterThan greaterThan) { + this.visit(greaterThan, null); + } - void visit(Modulo modulo); + T visit(GreaterThanEquals greaterThanEquals, S context); - void visit(AnalyticExpression aexpr); + default void visit(GreaterThanEquals greaterThanEquals) { + this.visit(greaterThanEquals, null); + } - void visit(ExtractExpression eexpr); + T visit(InExpression inExpression, S context); - void visit(IntervalExpression iexpr); + default void visit(InExpression inExpression) { + this.visit(inExpression, null); + } - void visit(OracleHierarchicalExpression oexpr); + T visit(IncludesExpression includesExpression, S context); - void visit(RegExpMatchOperator rexpr); + default void visit(IncludesExpression includesExpression) { + this.visit(includesExpression, null); + } - void visit(JsonExpression jsonExpr); + T visit(ExcludesExpression excludesExpression, S context); - void visit(JsonOperator jsonExpr); + default void visit(ExcludesExpression excludesExpression) { + this.visit(excludesExpression, null); + } - void visit(UserVariable var); + T visit(FullTextSearch fullTextSearch, S context); - void visit(NumericBind bind); + default void visit(FullTextSearch fullTextSearch) { + this.visit(fullTextSearch, null); + } - void visit(KeepExpression aexpr); + T visit(IsNullExpression isNullExpression, S context); - void visit(MySQLGroupConcat groupConcat); + default void visit(IsNullExpression isNullExpression) { + this.visit(isNullExpression, null); + } - void visit(ExpressionList expressionList); + T visit(IsBooleanExpression isBooleanExpression, S context); - void visit(RowConstructor rowConstructor); + default void visit(IsBooleanExpression isBooleanExpression) { + this.visit(isBooleanExpression, null); + } - void visit(RowGetExpression rowGetExpression); + T visit(LikeExpression likeExpression, S context); - void visit(OracleHint hint); + default void visit(LikeExpression likeExpression) { + this.visit(likeExpression, null); + } - void visit(TimeKeyExpression timeKeyExpression); + T visit(MinorThan minorThan, S context); - void visit(DateTimeLiteralExpression literal); + default void visit(MinorThan minorThan) { + this.visit(minorThan, null); + } - void visit(NotExpression aThis); + T visit(MinorThanEquals minorThanEquals, S context); - void visit(NextValExpression aThis); + default void visit(MinorThanEquals minorThanEquals) { + this.visit(minorThanEquals, null); + } - void visit(CollateExpression aThis); + T visit(NotEqualsTo notEqualsTo, S context); - void visit(SimilarToExpression aThis); + default void visit(NotEqualsTo notEqualsTo) { + this.visit(notEqualsTo, null); + } - void visit(ArrayExpression aThis); + T visit(DoubleAnd doubleAnd, S context); - void visit(ArrayConstructor aThis); + default void visit(DoubleAnd doubleAnd) { + this.visit(doubleAnd, null); + } - void visit(VariableAssignment aThis); + T visit(Contains contains, S context); - void visit(XMLSerializeExpr aThis); + default void visit(Contains contains) { + this.visit(contains, null); + } - void visit(TimezoneExpression aThis); + T visit(ContainedBy containedBy, S context); - void visit(JsonAggregateFunction aThis); + default void visit(ContainedBy containedBy) { + this.visit(containedBy, null); + } - void visit(JsonFunction aThis); + T visit(ParenthesedSelect select, S context); - void visit(ConnectByRootOperator aThis); + default void visit(ParenthesedSelect select) { + this.visit(select, null); + } - void visit(OracleNamedFunctionParameter aThis); + T visit(Column column, S context); - void visit(AllColumns allColumns); + default void visit(Column column) { + this.visit(column, null); + } - void visit(AllTableColumns allTableColumns); + T visit(CaseExpression caseExpression, S context); - void visit(AllValue allValue); + default void visit(CaseExpression caseExpression) { + this.visit(caseExpression, null); + } - void visit(IsDistinctExpression isDistinctExpression); + T visit(WhenClause whenClause, S context); - void visit(GeometryDistance geometryDistance); + default void visit(WhenClause whenClause) { + this.visit(whenClause, null); + } - void visit(Select selectBody); + T visit(ExistsExpression existsExpression, S context); - void visit(TranscodingFunction transcodingFunction); + default void visit(ExistsExpression existsExpression) { + this.visit(existsExpression, null); + } - void visit(TrimFunction trimFunction); + T visit(MemberOfExpression memberOfExpression, S context); - void visit(RangeExpression rangeExpression); + default void visit(MemberOfExpression memberOfExpression) { + this.visit(memberOfExpression, null); + } - void visit(TSQLLeftJoin tsqlLeftJoin); + T visit(AnyComparisonExpression anyComparisonExpression, S context); - void visit(TSQLRightJoin tsqlRightJoin); + default void visit(AnyComparisonExpression anyComparisonExpression) { + this.visit(anyComparisonExpression, null); + } + T visit(Concat concat, S context); + + default void visit(Concat concat) { + this.visit(concat, null); + } + + T visit(Matches matches, S context); + + default void visit(Matches matches) { + this.visit(matches, null); + } + + T visit(BitwiseAnd bitwiseAnd, S context); + + default void visit(BitwiseAnd bitwiseAnd) { + this.visit(bitwiseAnd, null); + } + + T visit(BitwiseOr bitwiseOr, S context); + + default void visit(BitwiseOr bitwiseOr) { + this.visit(bitwiseOr, null); + } + + T visit(BitwiseXor bitwiseXor, S context); + + default void visit(BitwiseXor bitwiseXor) { + this.visit(bitwiseXor, null); + } + + T visit(CastExpression castExpression, S context); + + default void visit(CastExpression castExpression) { + this.visit(castExpression, null); + } + + T visit(Modulo modulo, S context); + + default void visit(Modulo modulo) { + this.visit(modulo, null); + } + + T visit(AnalyticExpression analyticExpression, S context); + + default void visit(AnalyticExpression analyticExpression) { + this.visit(analyticExpression, null); + } + + T visit(ExtractExpression extractExpression, S context); + + default void visit(ExtractExpression extractExpression) { + this.visit(extractExpression, null); + } + + T visit(IntervalExpression intervalExpression, S context); + + default void visit(IntervalExpression intervalExpression) { + this.visit(intervalExpression, null); + } + + T visit(OracleHierarchicalExpression hierarchicalExpression, S context); + + default void visit(OracleHierarchicalExpression hierarchicalExpression) { + this.visit(hierarchicalExpression, null); + } + + T visit(RegExpMatchOperator regExpMatchOperator, S context); + + default void visit(RegExpMatchOperator regExpMatchOperator) { + this.visit(regExpMatchOperator, null); + } + + T visit(JsonExpression jsonExpression, S context); + + default void visit(JsonExpression jsonExpression) { + this.visit(jsonExpression, null); + } + + T visit(JsonOperator jsonOperator, S context); + + default void visit(JsonOperator jsonOperator) { + this.visit(jsonOperator, null); + } + + T visit(UserVariable userVariable, S context); + + default void visit(UserVariable userVariable) { + this.visit(userVariable, null); + } + + T visit(NumericBind numericBind, S context); + + default void visit(NumericBind numericBind) { + this.visit(numericBind, null); + } + + T visit(KeepExpression keepExpression, S context); + + default void visit(KeepExpression keepExpression) { + this.visit(keepExpression, null); + } + + T visit(MySQLGroupConcat groupConcat, S context); + + default void visit(MySQLGroupConcat groupConcat) { + this.visit(groupConcat, null); + } + + T visit(ExpressionList expressionList, S context); + + default void visit(ExpressionList expressionList) { + this.visit(expressionList, null); + } + + T visit(RowConstructor rowConstructor, S context); + + default void visit(RowConstructor rowConstructor) { + this.visit(rowConstructor, null); + } + + T visit(RowGetExpression rowGetExpression, S context); + + default void visit(RowGetExpression rowGetExpression) { + this.visit(rowGetExpression, null); + } + + T visit(OracleHint hint, S context); + + default void visit(OracleHint hint) { + this.visit(hint, null); + } + + T visit(TimeKeyExpression timeKeyExpression, S context); + + default void visit(TimeKeyExpression timeKeyExpression) { + this.visit(timeKeyExpression, null); + } + + T visit(DateTimeLiteralExpression dateTimeLiteralExpression, S context); + + default void visit(DateTimeLiteralExpression dateTimeLiteralExpression) { + this.visit(dateTimeLiteralExpression, null); + } + + T visit(NotExpression notExpression, S context); + + default void visit(NotExpression notExpression) { + this.visit(notExpression, null); + } + + T visit(NextValExpression nextValExpression, S context); + + default void visit(NextValExpression nextValExpression) { + this.visit(nextValExpression, null); + } + + T visit(CollateExpression collateExpression, S context); + + default void visit(CollateExpression collateExpression) { + this.visit(collateExpression, null); + } + + T visit(SimilarToExpression similarToExpression, S context); + + default void visit(SimilarToExpression similarToExpression) { + this.visit(similarToExpression, null); + } + + T visit(ArrayExpression arrayExpression, S context); + + default void visit(ArrayExpression arrayExpression) { + this.visit(arrayExpression, null); + } + + T visit(ArrayConstructor arrayConstructor, S context); + + default void visit(ArrayConstructor arrayConstructor) { + this.visit(arrayConstructor, null); + } + + T visit(VariableAssignment variableAssignment, S context); + + default void visit(VariableAssignment variableAssignment) { + this.visit(variableAssignment, null); + } + + T visit(XMLSerializeExpr xmlSerializeExpr, S context); + + default void visit(XMLSerializeExpr xmlSerializeExpr) { + this.visit(xmlSerializeExpr, null); + } + + T visit(TimezoneExpression timezoneExpression, S context); + + default void visit(TimezoneExpression timezoneExpression) { + this.visit(timezoneExpression, null); + } + + T visit(JsonAggregateFunction jsonAggregateFunction, S context); + + default void visit(JsonAggregateFunction jsonAggregateFunction) { + this.visit(jsonAggregateFunction, null); + } + + T visit(JsonFunction jsonFunction, S context); + + default void visit(JsonFunction jsonFunction) { + this.visit(jsonFunction, null); + } + + T visit(ConnectByRootOperator connectByRootOperator, S context); + + default void visit(ConnectByRootOperator connectByRootOperator) { + this.visit(connectByRootOperator, null); + } + + T visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, S context); + + default void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter) { + this.visit(oracleNamedFunctionParameter, null); + } + + T visit(AllColumns allColumns, S context); + + default void visit(AllColumns allColumns) { + this.visit(allColumns, null); + } + + T visit(AllTableColumns allTableColumns, S context); + + default void visit(AllTableColumns allTableColumns) { + this.visit(allTableColumns, null); + } + + T visit(AllValue allValue, S context); + + default void visit(AllValue allValue) { + this.visit(allValue, null); + } + + T visit(IsDistinctExpression isDistinctExpression, S context); + + default void visit(IsDistinctExpression isDistinctExpression) { + this.visit(isDistinctExpression, null); + } + + T visit(GeometryDistance geometryDistance, S context); + + default void visit(GeometryDistance geometryDistance) { + this.visit(geometryDistance, null); + } + + T visit(Select select, S context); + + default void visit(Select select) { + this.visit(select, null); + } + + T visit(TranscodingFunction transcodingFunction, S context); + + default void visit(TranscodingFunction transcodingFunction) { + this.visit(transcodingFunction, null); + } + + T visit(TrimFunction trimFunction, S context); + + default void visit(TrimFunction trimFunction) { + this.visit(trimFunction, null); + } + + T visit(RangeExpression rangeExpression, S context); + + default void visit(RangeExpression rangeExpression) { + this.visit(rangeExpression, null); + } + + T visit(TSQLLeftJoin tsqlLeftJoin, S context); + + default void visit(TSQLLeftJoin tsqlLeftJoin) { + this.visit(tsqlLeftJoin, null); + } + + T visit(TSQLRightJoin tsqlRightJoin, S context); + + default void visit(TSQLRightJoin tsqlRightJoin) { + this.visit(tsqlRightJoin, null); + } + + T visit(StructType structType, S context); + + default void visit(StructType structType) { + this.visit(structType, null); + } + + T visit(LambdaExpression lambdaExpression, S context); + + default void visit(LambdaExpression lambdaExpression) { + this.visit(lambdaExpression, null); + } } diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index 7c8a25c3b..f2223f890 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -67,629 +67,761 @@ import java.util.Optional; @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.UncommentedEmptyMethodBody"}) -public class ExpressionVisitorAdapter - implements ExpressionVisitor, PivotVisitor, SelectItemVisitor { +public class ExpressionVisitorAdapter + implements ExpressionVisitor, PivotVisitor, SelectItemVisitor { - private SelectVisitor selectVisitor; + private SelectVisitor selectVisitor; - public SelectVisitor getSelectVisitor() { + public SelectVisitor getSelectVisitor() { return selectVisitor; } - public void setSelectVisitor(SelectVisitor selectVisitor) { + public void setSelectVisitor(SelectVisitor selectVisitor) { this.selectVisitor = selectVisitor; } @Override - public void visit(NullValue value) { + public T visit(NullValue nullValue, S context) { + return null; } @Override - public void visit(Function function) { + public T visit(Function function, S context) { if (function.getParameters() != null) { - function.getParameters().accept(this); + function.getParameters().accept(this, context); } if (function.getKeep() != null) { - function.getKeep().accept(this); + function.getKeep().accept(this, context); } if (function.getOrderByElements() != null) { for (OrderByElement orderByElement : function.getOrderByElements()) { - orderByElement.getExpression().accept(this); + orderByElement.getExpression().accept(this, context); } } + return null; } @Override - public void visit(SignedExpression expr) { - expr.getExpression().accept(this); + public T visit(SignedExpression signedExpression, S context) { + signedExpression.getExpression().accept(this, context); + return null; } @Override - public void visit(JdbcParameter parameter) { + public T visit(JdbcParameter jdbcParameter, S context) { + return null; } @Override - public void visit(JdbcNamedParameter parameter) { + public T visit(JdbcNamedParameter jdbcNamedParameter, S context) { + return null; } @Override - public void visit(DoubleValue value) { + public T visit(DoubleValue doubleValue, S context) { + return null; } @Override - public void visit(LongValue value) { + public T visit(LongValue longValue, S context) { + return null; } @Override - public void visit(DateValue value) { + public T visit(DateValue dateValue, S context) { + return null; } @Override - public void visit(TimeValue value) { + public T visit(TimeValue timeValue, S context) { + return null; } @Override - public void visit(TimestampValue value) { + public T visit(TimestampValue timestampValue, S context) { + return null; } @Override - public void visit(Parenthesis parenthesis) { - parenthesis.getExpression().accept(this); + public T visit(StringValue stringValue, S context) { + return null; } @Override - public void visit(StringValue value) { - + public T visit(Addition addition, S context) { + visitBinaryExpression(addition, context); + return null; } @Override - public void visit(Addition expr) { - visitBinaryExpression(expr); + public T visit(Division division, S context) { + visitBinaryExpression(division, context); + return null; } @Override - public void visit(Division expr) { - visitBinaryExpression(expr); + public T visit(IntegerDivision integerDivision, S context) { + visitBinaryExpression(integerDivision, context); + return null; } @Override - public void visit(IntegerDivision expr) { - visitBinaryExpression(expr); + public T visit(Multiplication multiplication, S context) { + visitBinaryExpression(multiplication, context); + return null; } @Override - public void visit(Multiplication expr) { - visitBinaryExpression(expr); + public T visit(Subtraction subtraction, S context) { + visitBinaryExpression(subtraction, context); + return null; } @Override - public void visit(Subtraction expr) { - visitBinaryExpression(expr); + public T visit(AndExpression andExpression, S context) { + visitBinaryExpression(andExpression, context); + return null; } @Override - public void visit(AndExpression expr) { - visitBinaryExpression(expr); + public T visit(OrExpression orExpression, S context) { + visitBinaryExpression(orExpression, context); + return null; } @Override - public void visit(OrExpression expr) { - visitBinaryExpression(expr); + public T visit(XorExpression xorExpression, S context) { + visitBinaryExpression(xorExpression, context); + return null; } @Override - public void visit(XorExpression expr) { - visitBinaryExpression(expr); + public T visit(Between between, S context) { + between.getLeftExpression().accept(this, context); + between.getBetweenExpressionStart().accept(this, context); + between.getBetweenExpressionEnd().accept(this, context); + return null; } - @Override - public void visit(Between expr) { - expr.getLeftExpression().accept(this); - expr.getBetweenExpressionStart().accept(this); - expr.getBetweenExpressionEnd().accept(this); + public T visit(OverlapsCondition overlapsCondition, S context) { + overlapsCondition.getLeft().accept(this, context); + overlapsCondition.getRight().accept(this, context); + return null; } - public void visit(OverlapsCondition overlapsCondition) { - overlapsCondition.getLeft().accept(this); - overlapsCondition.getRight().accept(this); + + @Override + public T visit(EqualsTo equalsTo, S context) { + visitBinaryExpression(equalsTo, context); + return null; } + @Override + public T visit(GreaterThan greaterThan, S context) { + visitBinaryExpression(greaterThan, context); + return null; + } @Override - public void visit(EqualsTo expr) { - visitBinaryExpression(expr); + public T visit(GreaterThanEquals greaterThanEquals, S context) { + visitBinaryExpression(greaterThanEquals, context); + return null; } @Override - public void visit(GreaterThan expr) { - visitBinaryExpression(expr); + public T visit(InExpression inExpression, S context) { + inExpression.getLeftExpression().accept(this, context); + inExpression.getRightExpression().accept(this, context); + return null; } @Override - public void visit(GreaterThanEquals expr) { - visitBinaryExpression(expr); + public T visit(IncludesExpression includesExpression, S context) { + includesExpression.getLeftExpression().accept(this, context); + includesExpression.getRightExpression().accept(this, context); + return null; } @Override - public void visit(InExpression expr) { - expr.getLeftExpression().accept(this); - expr.getRightExpression().accept(this); + public T visit(ExcludesExpression excludesExpression, S context) { + excludesExpression.getLeftExpression().accept(this, context); + excludesExpression.getRightExpression().accept(this, context); + return null; } @Override - public void visit(IsNullExpression expr) { - expr.getLeftExpression().accept(this); + public T visit(IsNullExpression isNullExpression, S context) { + isNullExpression.getLeftExpression().accept(this, context); + return null; } @Override - public void visit(FullTextSearch expr) { - for (Column col : expr.getMatchColumns()) { - col.accept(this); + public T visit(FullTextSearch fullTextSearch, S context) { + for (Column col : fullTextSearch.getMatchColumns()) { + col.accept(this, context); } + return null; } @Override - public void visit(IsBooleanExpression expr) { - expr.getLeftExpression().accept(this); + public T visit(IsBooleanExpression isBooleanExpression, S context) { + isBooleanExpression.getLeftExpression().accept(this, context); + return null; } @Override - public void visit(LikeExpression expr) { - visitBinaryExpression(expr); + public T visit(LikeExpression likeExpression, S context) { + visitBinaryExpression(likeExpression, context); + return null; } @Override - public void visit(MinorThan expr) { - visitBinaryExpression(expr); + public T visit(MinorThan minorThan, S context) { + visitBinaryExpression(minorThan, context); + return null; } @Override - public void visit(MinorThanEquals expr) { - visitBinaryExpression(expr); + public T visit(MinorThanEquals minorThanEquals, S context) { + visitBinaryExpression(minorThanEquals, context); + return null; } @Override - public void visit(NotEqualsTo expr) { - visitBinaryExpression(expr); + public T visit(NotEqualsTo notEqualsTo, S context) { + visitBinaryExpression(notEqualsTo, context); + return null; } @Override - public void visit(DoubleAnd expr) { - visitBinaryExpression(expr); + public T visit(DoubleAnd doubleAnd, S context) { + visitBinaryExpression(doubleAnd, context); + return null; } @Override - public void visit(Contains expr) { - visitBinaryExpression(expr); + public T visit(Contains contains, S context) { + visitBinaryExpression(contains, context); + return null; } @Override - public void visit(ContainedBy expr) { - visitBinaryExpression(expr); + public T visit(ContainedBy containedBy, S context) { + visitBinaryExpression(containedBy, context); + return null; } @Override - public void visit(Column column) { + public T visit(Column column, S context) { + return null; } @Override - public void visit(ParenthesedSelect selectBody) { - visit((Select) selectBody); - if (selectBody.getPivot() != null) { - selectBody.getPivot().accept(this); + public T visit(ParenthesedSelect select, S context) { + visit((Select) select, context); + if (select.getPivot() != null) { + select.getPivot().accept(this, context); } + return null; } @Override - public void visit(CaseExpression expr) { - if (expr.getSwitchExpression() != null) { - expr.getSwitchExpression().accept(this); + public T visit(CaseExpression caseExpression, S context) { + if (caseExpression.getSwitchExpression() != null) { + caseExpression.getSwitchExpression().accept(this, context); } - for (Expression x : expr.getWhenClauses()) { - x.accept(this); + for (Expression x : caseExpression.getWhenClauses()) { + x.accept(this, context); } - if (expr.getElseExpression() != null) { - expr.getElseExpression().accept(this); + if (caseExpression.getElseExpression() != null) { + caseExpression.getElseExpression().accept(this, context); } + return null; } @Override - public void visit(WhenClause expr) { - expr.getWhenExpression().accept(this); - expr.getThenExpression().accept(this); + public T visit(WhenClause whenClause, S context) { + whenClause.getWhenExpression().accept(this, context); + whenClause.getThenExpression().accept(this, context); + return null; } @Override - public void visit(ExistsExpression expr) { - expr.getRightExpression().accept(this); + public T visit(ExistsExpression existsExpression, S context) { + existsExpression.getRightExpression().accept(this, context); + return null; } @Override - public void visit(MemberOfExpression memberOfExpression) { - memberOfExpression.getRightExpression().accept(this); + public T visit(MemberOfExpression memberOfExpression, S context) { + memberOfExpression.getRightExpression().accept(this, context); + return null; } @Override - public void visit(AnyComparisonExpression expr) { + public T visit(AnyComparisonExpression anyComparisonExpression, S context) { + return null; } @Override - public void visit(Concat expr) { - visitBinaryExpression(expr); + public T visit(Concat concat, S context) { + visitBinaryExpression(concat, context); + return null; } @Override - public void visit(Matches expr) { - visitBinaryExpression(expr); + public T visit(Matches matches, S context) { + visitBinaryExpression(matches, context); + return null; } @Override - public void visit(BitwiseAnd expr) { - visitBinaryExpression(expr); + public T visit(BitwiseAnd bitwiseAnd, S context) { + visitBinaryExpression(bitwiseAnd, context); + return null; } @Override - public void visit(BitwiseOr expr) { - visitBinaryExpression(expr); + public T visit(BitwiseOr bitwiseOr, S context) { + visitBinaryExpression(bitwiseOr, context); + return null; } @Override - public void visit(BitwiseXor expr) { - visitBinaryExpression(expr); + public T visit(BitwiseXor bitwiseXor, S context) { + visitBinaryExpression(bitwiseXor, context); + return null; } @Override - public void visit(CastExpression expr) { - expr.getLeftExpression().accept(this); + public T visit(CastExpression castExpression, S context) { + castExpression.getLeftExpression().accept(this, context); + return null; } @Override - public void visit(Modulo expr) { - visitBinaryExpression(expr); + public T visit(Modulo modulo, S context) { + visitBinaryExpression(modulo, context); + return null; } @Override - public void visit(AnalyticExpression expr) { - if (expr.getExpression() != null) { - expr.getExpression().accept(this); + public T visit(AnalyticExpression analyticExpression, S context) { + if (analyticExpression.getExpression() != null) { + analyticExpression.getExpression().accept(this, context); } - if (expr.getDefaultValue() != null) { - expr.getDefaultValue().accept(this); + if (analyticExpression.getDefaultValue() != null) { + analyticExpression.getDefaultValue().accept(this, context); } - if (expr.getOffset() != null) { - expr.getOffset().accept(this); + if (analyticExpression.getOffset() != null) { + analyticExpression.getOffset().accept(this, context); } - if (expr.getKeep() != null) { - expr.getKeep().accept(this); + if (analyticExpression.getKeep() != null) { + analyticExpression.getKeep().accept(this, context); } - if (expr.getFuncOrderBy() != null) { - for (OrderByElement element : expr.getOrderByElements()) { - element.getExpression().accept(this); + if (analyticExpression.getFuncOrderBy() != null) { + for (OrderByElement element : analyticExpression.getOrderByElements()) { + element.getExpression().accept(this, context); } } - if (expr.getWindowElement() != null) { + if (analyticExpression.getWindowElement() != null) { /* * Visit expressions from the range and offset of the window element. Do this using * optional chains, because several things down the tree can be null e.g. the * expression. So, null-safe versions of e.g.: - * expr.getWindowElement().getOffset().getExpression().accept(this); + * analyticExpression.getWindowElement().getOffset().getExpression().accept(this, + * parameters); */ - Optional.ofNullable(expr.getWindowElement().getRange()).map(WindowRange::getStart) - .map(WindowOffset::getExpression).ifPresent(e -> e.accept(this)); - Optional.ofNullable(expr.getWindowElement().getRange()).map(WindowRange::getEnd) - .map(WindowOffset::getExpression).ifPresent(e -> e.accept(this)); - Optional.ofNullable(expr.getWindowElement().getOffset()) - .map(WindowOffset::getExpression).ifPresent(e -> e.accept(this)); + Optional.ofNullable(analyticExpression.getWindowElement().getRange()) + .map(WindowRange::getStart) + .map(WindowOffset::getExpression).ifPresent(e -> e.accept(this, context)); + Optional.ofNullable(analyticExpression.getWindowElement().getRange()) + .map(WindowRange::getEnd) + .map(WindowOffset::getExpression).ifPresent(e -> e.accept(this, context)); + Optional.ofNullable(analyticExpression.getWindowElement().getOffset()) + .map(WindowOffset::getExpression).ifPresent(e -> e.accept(this, context)); } + return null; } @Override - public void visit(ExtractExpression expr) { - expr.getExpression().accept(this); + public T visit(ExtractExpression extractExpression, S context) { + extractExpression.getExpression().accept(this, context); + return null; } @Override - public void visit(IntervalExpression expr) {} + public T visit(IntervalExpression intervalExpression, S context) { + return null; + } @Override - public void visit(OracleHierarchicalExpression expr) { - expr.getConnectExpression().accept(this); - expr.getStartExpression().accept(this); + public T visit(OracleHierarchicalExpression hierarchicalExpression, S context) { + hierarchicalExpression.getConnectExpression().accept(this, context); + hierarchicalExpression.getStartExpression().accept(this, context); + return null; } @Override - public void visit(RegExpMatchOperator expr) { - visitBinaryExpression(expr); + public T visit(RegExpMatchOperator regExpMatchOperator, S context) { + visitBinaryExpression(regExpMatchOperator, context); + return null; } @Override - public void visit(ExpressionList expressionList) { + public T visit(ExpressionList expressionList, S context) { for (Expression expr : expressionList) { - expr.accept(this); + expr.accept(this, context); } + return null; } @Override - public void visit(RowConstructor rowConstructor) { + public T visit(RowConstructor rowConstructor, S context) { for (Expression expr : rowConstructor) { - expr.accept(this); + expr.accept(this, context); } + return null; } @Override - public void visit(NotExpression notExpr) { - notExpr.getExpression().accept(this); + public T visit(NotExpression notExpr, S context) { + notExpr.getExpression().accept(this, context); + return null; } @Override - public void visit(BitwiseRightShift expr) { - visitBinaryExpression(expr); + public T visit(BitwiseRightShift bitwiseRightShift, S context) { + visitBinaryExpression(bitwiseRightShift, context); + return null; } @Override - public void visit(BitwiseLeftShift expr) { - visitBinaryExpression(expr); + public T visit(BitwiseLeftShift bitwiseLeftShift, S context) { + visitBinaryExpression(bitwiseLeftShift, context); + return null; } - protected void visitBinaryExpression(BinaryExpression expr) { - expr.getLeftExpression().accept(this); - expr.getRightExpression().accept(this); + protected T visitBinaryExpression(BinaryExpression binaryExpression, S context) { + binaryExpression.getLeftExpression().accept(this, context); + binaryExpression.getRightExpression().accept(this, context); + return null; } @Override - public void visit(JsonExpression jsonExpr) { - jsonExpr.getExpression().accept(this); + public T visit(JsonExpression jsonExpr, S context) { + jsonExpr.getExpression().accept(this, context); + return null; } @Override - public void visit(JsonOperator expr) { - visitBinaryExpression(expr); + public T visit(JsonOperator jsonOperator, S context) { + visitBinaryExpression(jsonOperator, context); + return null; } @Override - public void visit(UserVariable var) { + public T visit(UserVariable userVariable, S context) { + return null; } @Override - public void visit(NumericBind bind) { + public T visit(NumericBind numericBind, S context) { + return null; } @Override - public void visit(KeepExpression expr) { - for (OrderByElement element : expr.getOrderByElements()) { - element.getExpression().accept(this); + public T visit(KeepExpression keepExpression, S context) { + for (OrderByElement element : keepExpression.getOrderByElements()) { + element.getExpression().accept(this, context); } + return null; } @Override - public void visit(MySQLGroupConcat groupConcat) { - for (Expression expr : groupConcat.getExpressionList().getExpressions()) { - expr.accept(this); + public T visit(MySQLGroupConcat groupConcat, S context) { + for (Expression expr : groupConcat.getExpressionList()) { + expr.accept(this, context); } if (groupConcat.getOrderByElements() != null) { for (OrderByElement element : groupConcat.getOrderByElements()) { - element.getExpression().accept(this); + element.getExpression().accept(this, context); } } + return null; } @Override - public void visit(Pivot pivot) { + public T visit(Pivot pivot, S context) { for (SelectItem item : pivot.getFunctionItems()) { - item.getExpression().accept(this); + item.getExpression().accept(this, context); } for (Column col : pivot.getForColumns()) { - col.accept(this); + col.accept(this, context); } if (pivot.getSingleInItems() != null) { - for (SelectItem item : pivot.getSingleInItems()) { - item.getExpression().accept(this); + for (SelectItem item : pivot.getSingleInItems()) { + item.getExpression().accept(this, context); } } if (pivot.getMultiInItems() != null) { - for (SelectItem item : pivot.getMultiInItems()) { - item.getExpression().accept(this); + for (SelectItem> item : pivot.getMultiInItems()) { + item.getExpression().accept(this, context); } } + return null; } @Override - public void visit(PivotXml pivot) { - for (SelectItem item : pivot.getFunctionItems()) { - item.getExpression().accept(this); + public T visit(PivotXml pivotXml, S context) { + for (SelectItem item : pivotXml.getFunctionItems()) { + item.getExpression().accept(this, context); } - for (Column col : pivot.getForColumns()) { - col.accept(this); + for (Column col : pivotXml.getForColumns()) { + col.accept(this, context); } - if (pivot.getInSelect() != null && selectVisitor != null) { - pivot.getInSelect().accept(selectVisitor); + if (pivotXml.getInSelect() != null && selectVisitor != null) { + pivotXml.getInSelect().accept(selectVisitor, context); } + return null; } @Override - public void visit(UnPivot unpivot) { - unpivot.accept(this); + public T visit(UnPivot unpivot, S context) { + unpivot.accept(this, context); + return null; } @Override - public void visit(AllColumns allColumns) {} + public T visit(AllColumns allColumns, S context) { + return null; + } @Override - public void visit(AllTableColumns allTableColumns) {} + public T visit(AllTableColumns allTableColumns, S context) { + return null; + } @Override - public void visit(AllValue allValue) {} + public T visit(AllValue allValue, S context) { + return null; + } @Override - public void visit(IsDistinctExpression isDistinctExpression) { - visitBinaryExpression(isDistinctExpression); + public T visit(IsDistinctExpression isDistinctExpression, S context) { + visitBinaryExpression(isDistinctExpression, context); + return null; } @Override - public void visit(SelectItem selectExpressionItem) { - selectExpressionItem.getExpression().accept(this); + public T visit(SelectItem selectItem, S context) { + selectItem.getExpression().accept(this, context); + return null; } @Override - public void visit(RowGetExpression rowGetExpression) { - rowGetExpression.getExpression().accept(this); + public T visit(RowGetExpression rowGetExpression, S context) { + rowGetExpression.getExpression().accept(this, context); + return null; } @Override - public void visit(HexValue hexValue) { + public T visit(HexValue hexValue, S context) { + return null; } @Override - public void visit(OracleHint hint) { + public T visit(OracleHint hint, S context) { + return null; } @Override - public void visit(TimeKeyExpression timeKeyExpression) { + public T visit(TimeKeyExpression timeKeyExpression, S context) { + return null; } @Override - public void visit(DateTimeLiteralExpression literal) {} + public T visit(DateTimeLiteralExpression dateTimeLiteralExpression, S context) { + return null; + } @Override - public void visit(NextValExpression nextVal) {} + public T visit(NextValExpression nextValExpression, S context) { + return null; + } @Override - public void visit(CollateExpression col) { - col.getLeftExpression().accept(this); + public T visit(CollateExpression collateExpression, S context) { + collateExpression.getLeftExpression().accept(this, context); + return null; } @Override - public void visit(SimilarToExpression expr) { - visitBinaryExpression(expr); + public T visit(SimilarToExpression similarToExpression, S context) { + visitBinaryExpression(similarToExpression, context); + return null; } @Override - public void visit(ArrayExpression array) { - array.getObjExpression().accept(this); - if (array.getIndexExpression() != null) { - array.getIndexExpression().accept(this); + public T visit(ArrayExpression arrayExpression, S context) { + arrayExpression.getObjExpression().accept(this, context); + if (arrayExpression.getIndexExpression() != null) { + arrayExpression.getIndexExpression().accept(this, context); } - if (array.getStartIndexExpression() != null) { - array.getStartIndexExpression().accept(this); + if (arrayExpression.getStartIndexExpression() != null) { + arrayExpression.getStartIndexExpression().accept(this, context); } - if (array.getStopIndexExpression() != null) { - array.getStopIndexExpression().accept(this); + if (arrayExpression.getStopIndexExpression() != null) { + arrayExpression.getStopIndexExpression().accept(this, context); } + return null; } @Override - public void visit(ArrayConstructor aThis) { - for (Expression expression : aThis.getExpressions()) { - expression.accept(this); + public T visit(ArrayConstructor arrayConstructor, S context) { + for (Expression expression : arrayConstructor.getExpressions()) { + expression.accept(this, context); } + return null; } @Override - public void visit(VariableAssignment var) { - var.getVariable().accept(this); - var.getExpression().accept(this); + public T visit(VariableAssignment variableAssignment, S context) { + variableAssignment.getVariable().accept(this, context); + variableAssignment.getExpression().accept(this, context); + return null; } @Override - public void visit(XMLSerializeExpr expr) { - expr.getExpression().accept(this); - for (OrderByElement elm : expr.getOrderByElements()) { - elm.getExpression().accept(this); + public T visit(XMLSerializeExpr xmlSerializeExpr, S context) { + xmlSerializeExpr.getExpression().accept(this, context); + for (OrderByElement elm : xmlSerializeExpr.getOrderByElements()) { + elm.getExpression().accept(this, context); } + return null; } @Override - public void visit(TimezoneExpression expr) { - expr.getLeftExpression().accept(this); + public T visit(TimezoneExpression timezoneExpression, S context) { + timezoneExpression.getLeftExpression().accept(this, context); + return null; } @Override - public void visit(JsonAggregateFunction expression) { - Expression expr = expression.getExpression(); + public T visit(JsonAggregateFunction jsonAggregateFunction, S context) { + Expression expr = jsonAggregateFunction.getExpression(); if (expr != null) { - expr.accept(this); + expr.accept(this, context); } - expr = expression.getFilterExpression(); + expr = jsonAggregateFunction.getFilterExpression(); if (expr != null) { - expr.accept(this); + expr.accept(this, context); } + return null; } @Override - public void visit(JsonFunction expression) { - for (JsonFunctionExpression expr : expression.getExpressions()) { - expr.getExpression().accept(this); + public T visit(JsonFunction jsonFunction, S context) { + for (JsonFunctionExpression expr : jsonFunction.getExpressions()) { + expr.getExpression().accept(this, context); } + return null; } @Override - public void visit(ConnectByRootOperator connectByRootOperator) { - connectByRootOperator.getColumn().accept(this); + public T visit(ConnectByRootOperator connectByRootOperator, S context) { + connectByRootOperator.getColumn().accept(this, context); + return null; } @Override - public void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter) { - oracleNamedFunctionParameter.getExpression().accept(this); + public T visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, S context) { + oracleNamedFunctionParameter.getExpression().accept(this, context); + return null; } @Override - public void visit(GeometryDistance geometryDistance) { - visitBinaryExpression(geometryDistance); + public T visit(GeometryDistance geometryDistance, S context) { + visitBinaryExpression(geometryDistance, context); + return null; } @Override - public void visit(Select selectBody) { + public T visit(Select select, S context) { if (selectVisitor != null) { - if (selectBody.getWithItemsList() != null) { - for (WithItem item : selectBody.getWithItemsList()) { - item.accept(selectVisitor); + if (select.getWithItemsList() != null) { + for (WithItem item : select.getWithItemsList()) { + item.accept(selectVisitor, context); } } - selectBody.accept(selectVisitor); + select.accept(selectVisitor, context); } + return null; } @Override - public void visit(TranscodingFunction transcodingFunction) { + public T visit(TranscodingFunction transcodingFunction, S context) { + return null; } @Override - public void visit(TrimFunction trimFunction) { + public T visit(TrimFunction trimFunction, S context) { + return null; + } + + @Override + public T visit(RangeExpression rangeExpression, S context) { + rangeExpression.getStartExpression().accept(this, context); + rangeExpression.getEndExpression().accept(this, context); + return null; } @Override - public void visit(RangeExpression rangeExpression) { - rangeExpression.getStartExpression().accept(this); - rangeExpression.getEndExpression().accept(this); + public T visit(TSQLLeftJoin tsqlLeftJoin, S context) { + visitBinaryExpression(tsqlLeftJoin, context); + return null; } @Override - public void visit(TSQLLeftJoin tsqlLeftJoin) { - visitBinaryExpression(tsqlLeftJoin); + public T visit(TSQLRightJoin tsqlRightJoin, S context) { + visitBinaryExpression(tsqlRightJoin, context); + return null; + } + + @Override + public T visit(StructType structType, S context) { + // @todo: visit the ColType also + if (structType.getArguments() != null) { + for (SelectItem selectItem : structType.getArguments()) { + visit(selectItem, context); + } + } + return null; } @Override - public void visit(TSQLRightJoin tsqlRightJoin) { - visitBinaryExpression(tsqlRightJoin); + public T visit(LambdaExpression lambdaExpression, S context) { + lambdaExpression.getExpression().accept(this, context); + return null; } } diff --git a/src/main/java/net/sf/jsqlparser/expression/ExtractExpression.java b/src/main/java/net/sf/jsqlparser/expression/ExtractExpression.java index aeb01814e..dcbddfef8 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExtractExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExtractExpression.java @@ -23,8 +23,8 @@ public class ExtractExpression extends ASTNodeAccessImpl implements Expression { private Expression expression; @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } public String getName() { diff --git a/src/main/java/net/sf/jsqlparser/expression/FilterOverImpl.java b/src/main/java/net/sf/jsqlparser/expression/FilterOverImpl.java index f3a28349d..50e557933 100644 --- a/src/main/java/net/sf/jsqlparser/expression/FilterOverImpl.java +++ b/src/main/java/net/sf/jsqlparser/expression/FilterOverImpl.java @@ -10,12 +10,12 @@ package net.sf.jsqlparser.expression; import java.util.List; + import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; import net.sf.jsqlparser.statement.select.OrderByElement; /** - * * @author tw */ public class FilterOverImpl extends ASTNodeAccessImpl { @@ -32,7 +32,7 @@ public AnalyticType getAnalyticType() { public void setAnalyticType(AnalyticType analyticType) { this.analyticType = analyticType; } - + public FilterOverImpl withAnalyticType(AnalyticType analyticType) { this.setAnalyticType(analyticType); return this; @@ -45,7 +45,7 @@ public List getOrderByElements() { public void setOrderByElements(List orderByElements) { orderBy.setOrderByElements(orderByElements); } - + public FilterOverImpl withOrderByElements(List orderByElements) { this.setOrderByElements(orderByElements); return this; @@ -59,14 +59,15 @@ public void setPartitionExpressionList(ExpressionList partitionExpressionList) { setPartitionExpressionList(partitionExpressionList, false); } - public void setPartitionExpressionList(ExpressionList partitionExpressionList, boolean brackets) { + public void setPartitionExpressionList(ExpressionList partitionExpressionList, + boolean brackets) { partitionBy.setPartitionExpressionList(partitionExpressionList, brackets); } public boolean isPartitionByBrackets() { return partitionBy.isBrackets(); } - + public Expression getFilterExpression() { return filterExpression; } @@ -88,13 +89,14 @@ public WindowElement getWindowElement() { public void setWindowElement(WindowElement windowElement) { this.windowElement = windowElement; } - + public FilterOverImpl withWindowElement(WindowElement windowElement) { this.setWindowElement(windowElement); return this; } - - @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity", "PMD.MissingBreakInSwitch"}) + + @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity", + "PMD.MissingBreakInSwitch"}) public StringBuilder append(StringBuilder builder) { if (filterExpression != null) { builder.append("FILTER (WHERE "); diff --git a/src/main/java/net/sf/jsqlparser/expression/Function.java b/src/main/java/net/sf/jsqlparser/expression/Function.java index 9a7c2d9d9..ffe2a0128 100644 --- a/src/main/java/net/sf/jsqlparser/expression/Function.java +++ b/src/main/java/net/sf/jsqlparser/expression/Function.java @@ -13,6 +13,7 @@ import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.statement.select.Limit; import net.sf.jsqlparser.statement.select.OrderByElement; import java.util.Arrays; @@ -22,7 +23,6 @@ * A function as MAX,COUNT... */ public class Function extends ASTNodeAccessImpl implements Expression { - private List nameparts; private ExpressionList parameters; private NamedExpressionList namedParameters; @@ -31,28 +31,44 @@ public class Function extends ASTNodeAccessImpl implements Expression { private boolean unique = false; private boolean isEscaped = false; private Expression attributeExpression; + private HavingClause havingClause; private Column attributeColumn = null; private List orderByElements; + private NullHandling nullHandling = null; + private boolean ignoreNullsOutside = false; // IGNORE NULLS outside function parameters + private Limit limit = null; private KeepExpression keep = null; - private boolean ignoreNulls = false; - @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public Function() {} + + public Function(String name, Expression... parameters) { + this.nameparts = Arrays.asList(name); + this.parameters = new ExpressionList<>(parameters); } - public String getName() { - return nameparts == null ? null : String.join(".", nameparts); + @Override + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } - public List getMultipartName() { - return nameparts; + public String getName() { + return nameparts == null ? null + : String.join(nameparts.get(0).equalsIgnoreCase("APPROXIMATE") ? " " : ".", + nameparts); } public void setName(String string) { nameparts = Arrays.asList(string); } + public void setName(List string) { + nameparts = string; + } + + public List getMultipartName() { + return nameparts; + } + public Function withName(String name) { this.setName(name); return this; @@ -63,10 +79,6 @@ public Function withName(List nameparts) { return this; } - public void setName(List string) { - nameparts = string; - } - public boolean isAllColumns() { return allColumns; } @@ -75,17 +87,58 @@ public void setAllColumns(boolean b) { allColumns = b; } + public NullHandling getNullHandling() { + return nullHandling; + } + + public Function setNullHandling(NullHandling nullHandling) { + this.nullHandling = nullHandling; + return this; + } + + public boolean isIgnoreNullsOutside() { + return ignoreNullsOutside; + } + + public Function setIgnoreNullsOutside(boolean ignoreNullsOutside) { + this.ignoreNullsOutside = ignoreNullsOutside; + return this; + } + + public Limit getLimit() { + return limit; + } + + public Function setLimit(Limit limit) { + this.limit = limit; + return this; + } + public boolean isIgnoreNulls() { - return ignoreNulls; + return nullHandling != null && nullHandling == NullHandling.IGNORE_NULLS; } /** * This is at the moment only necessary for AnalyticExpression initialization and not for normal * functions. Therefore there is no deparsing for it for normal functions. - * */ public void setIgnoreNulls(boolean ignoreNulls) { - this.ignoreNulls = ignoreNulls; + this.nullHandling = ignoreNulls ? NullHandling.IGNORE_NULLS : null; + } + + public HavingClause getHavingClause() { + return havingClause; + } + + public Function setHavingClause(HavingClause havingClause) { + this.havingClause = havingClause; + return this; + } + + public Function setHavingClause(String havingType, Expression expression) { + this.havingClause = new HavingClause( + HavingClause.HavingType.valueOf(havingType.trim().toUpperCase()), expression); + return this; } /** @@ -170,6 +223,11 @@ public void setAttribute(Expression attributeExpression) { this.attributeExpression = attributeExpression; } + public void setAttribute(Column attributeColumn) { + attributeExpression = null; + this.attributeColumn = attributeColumn; + } + @Deprecated public String getAttributeName() { return attributeColumn.toString(); @@ -183,11 +241,6 @@ public Column getAttributeColumn() { return attributeColumn; } - public void setAttribute(Column attributeColumn) { - attributeExpression = null; - this.attributeColumn = attributeColumn; - } - public Function withAttribute(Column attributeColumn) { setAttribute(attributeColumn); return this; @@ -219,6 +272,21 @@ public String toString() { b.append("ALL "); } b.append(parameters); + + if (havingClause != null) { + havingClause.appendTo(b); + } + + if (nullHandling != null && !isIgnoreNullsOutside()) { + switch (nullHandling) { + case IGNORE_NULLS: + b.append(" IGNORE NULLS"); + break; + case RESPECT_NULLS: + b.append(" RESPECT NULLS"); + break; + } + } if (orderByElements != null) { b.append(" ORDER BY "); boolean comma = false; @@ -231,6 +299,9 @@ public String toString() { b.append(orderByElement); } } + if (limit != null) { + b.append(limit); + } b.append(")"); params = b.toString(); } else { @@ -242,6 +313,17 @@ public String toString() { String ans = getName() + params; + if (nullHandling != null && isIgnoreNullsOutside()) { + switch (nullHandling) { + case IGNORE_NULLS: + ans += " IGNORE NULLS"; + break; + case RESPECT_NULLS: + ans += " RESPECT NULLS"; + break; + } + } + if (attributeExpression != null) { ans += "." + attributeExpression; } else if (attributeColumn != null) { @@ -320,4 +402,55 @@ public void setOrderByElements(List orderByElements) { public E getAttribute(Class type) { return type.cast(getAttribute()); } + + public enum NullHandling { + IGNORE_NULLS, RESPECT_NULLS; + } + + public static class HavingClause extends ASTNodeAccessImpl implements Expression { + HavingType havingType; + Expression expression; + + public HavingClause(HavingType havingType, Expression expression) { + this.havingType = havingType; + this.expression = expression; + } + + public HavingType getHavingType() { + return havingType; + } + + public HavingClause setHavingType(HavingType havingType) { + this.havingType = havingType; + return this; + } + + public Expression getExpression() { + return expression; + } + + public HavingClause setExpression(Expression expression) { + this.expression = expression; + return this; + } + + @Override + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expression.accept(expressionVisitor, context); + } + + public StringBuilder appendTo(StringBuilder builder) { + builder.append(" HAVING ").append(havingType.name()).append(" ").append(expression); + return builder; + } + + @Override + public String toString() { + return appendTo(new StringBuilder()).toString(); + } + + enum HavingType { + MAX, MIN; + } + } } diff --git a/src/main/java/net/sf/jsqlparser/expression/HexValue.java b/src/main/java/net/sf/jsqlparser/expression/HexValue.java index a5a334a2a..cba9a3ac1 100644 --- a/src/main/java/net/sf/jsqlparser/expression/HexValue.java +++ b/src/main/java/net/sf/jsqlparser/expression/HexValue.java @@ -11,6 +11,8 @@ import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import java.nio.charset.StandardCharsets; + public class HexValue extends ASTNodeAccessImpl implements Expression { private String value; @@ -24,9 +26,19 @@ public HexValue(final String value) { this.value = val; } + public static byte[] hexStringToByteArray(String s) { + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + + Character.digit(s.charAt(i + 1), 16)); + } + return data; + } + @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } public String getValue() { @@ -46,4 +58,36 @@ public HexValue withValue(String value) { public String toString() { return value; } + + public String getDigits() { + return value.toUpperCase().startsWith("0X") + ? value.substring(2) + : value.substring(2, value.length() - 1); + } + + public Long getLong() { + return Long.parseLong( + getDigits(), 16); + } + + public LongValue getLongValue() { + return new LongValue(getLong()); + } + + // `X'C3BC'` --> `'ü'` + public StringValue getStringValue() { + return new StringValue( + new String(hexStringToByteArray(getDigits()), StandardCharsets.UTF_8)); + } + + // `X'C3BC'` --> `\xC3\xBC` + public StringValue getBlob() { + StringBuilder builder = new StringBuilder(); + String digits = getDigits(); + int len = digits.length(); + for (int i = 0; i < len; i += 2) { + builder.append("\\x").append(digits.charAt(i)).append(digits.charAt(i + 1)); + } + return new StringValue(builder.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/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 c49086106..13e3ba296 100644 --- a/src/main/java/net/sf/jsqlparser/expression/JsonAggregateFunction.java +++ b/src/main/java/net/sf/jsqlparser/expression/JsonAggregateFunction.java @@ -11,29 +11,27 @@ 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 boolean usingValueKeyword = false; private Object value; - + private boolean usingFormatJson = false; - + private JsonAggregateOnNullType onNullType; private JsonAggregateUniqueKeysType uniqueKeysType; - + public JsonAggregateOnNullType getOnNullType() { return onNullType; @@ -42,7 +40,7 @@ public JsonAggregateOnNullType getOnNullType() { public void setOnNullType(JsonAggregateOnNullType onNullType) { this.onNullType = onNullType; } - + public JsonAggregateFunction withOnNullType(JsonAggregateOnNullType onNullType) { this.setOnNullType(onNullType); return this; @@ -55,7 +53,7 @@ public JsonAggregateUniqueKeysType getUniqueKeysType() { public void setUniqueKeysType(JsonAggregateUniqueKeysType uniqueKeysType) { this.uniqueKeysType = uniqueKeysType; } - + public JsonAggregateFunction withUniqueKeysType(JsonAggregateUniqueKeysType uniqueKeysType) { this.setUniqueKeysType(uniqueKeysType); return this; @@ -64,21 +62,25 @@ public JsonAggregateFunction withUniqueKeysType(JsonAggregateUniqueKeysType uniq 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"); + 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 JsonAggregateFunction 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 JsonAggregateFunction withType(String typeName) { this.setType(typeName); return this; @@ -91,7 +93,7 @@ public Expression getExpression() { public void setExpression(Expression expression) { this.expression = expression; } - + public JsonAggregateFunction withExpression(Expression expression) { this.setExpression(expression); return this; @@ -104,7 +106,7 @@ public boolean isUsingKeyKeyword() { public void setUsingKeyKeyword(boolean usingKeyKeyword) { this.usingKeyKeyword = usingKeyKeyword; } - + public JsonAggregateFunction withUsingKeyKeyword(boolean usingKeyKeyword) { this.setUsingKeyKeyword(usingKeyKeyword); return this; @@ -117,7 +119,7 @@ public String getKey() { public void setKey(String key) { this.key = key; } - + public JsonAggregateFunction withKey(String key) { this.setKey(key); return this; @@ -130,7 +132,7 @@ public boolean isUsingValueKeyword() { public void setUsingValueKeyword(boolean usingValueKeyword) { this.usingValueKeyword = usingValueKeyword; } - + public JsonAggregateFunction withUsingValueKeyword(boolean usingValueKeyword) { this.setUsingValueKeyword(usingValueKeyword); return this; @@ -143,12 +145,12 @@ public Object getValue() { public void setValue(Object value) { this.value = value; } - + public JsonAggregateFunction withValue(Object value) { this.setValue(value); return this; } - + public boolean isUsingFormatJson() { return usingFormatJson; } @@ -156,12 +158,12 @@ public boolean isUsingFormatJson() { public void setUsingFormatJson(boolean usingFormatJson) { this.usingFormatJson = usingFormatJson; } - + public JsonAggregateFunction withUsingFormatJson(boolean usingFormatJson) { this.setUsingFormatJson(usingFormatJson); return this; } - + public List getExpressionOrderByElements() { return expressionOrderBy.getOrderByElements(); } @@ -169,17 +171,18 @@ public List getExpressionOrderByElements() { public void setExpressionOrderByElements(List orderByElements) { expressionOrderBy.setOrderByElements(orderByElements); } - - public JsonAggregateFunction withExpressionOrderByElements(List orderByElements) { + + public JsonAggregateFunction withExpressionOrderByElements( + List orderByElements) { this.setExpressionOrderByElements(orderByElements); return this; } @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 @Override public StringBuilder append(StringBuilder builder) { @@ -192,11 +195,12 @@ public StringBuilder append(StringBuilder builder) { break; default: // this should never happen really - throw new UnsupportedOperationException("JSON Aggregate Function of the type " + functionType.name() + " has not been implemented yet."); + throw new UnsupportedOperationException("JSON Aggregate Function of the type " + + functionType.name() + " has not been implemented yet."); } return builder; } - + @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"}) public StringBuilder appendObject(StringBuilder builder) { builder.append("JSON_OBJECTAGG( "); @@ -208,13 +212,13 @@ public StringBuilder appendObject(StringBuilder builder) { } else { builder.append(key).append(":").append(value); } - + if (usingFormatJson) { builder.append(" FORMAT JSON"); } - - if (onNullType!=null) { - switch(onNullType) { + + if (onNullType != null) { + switch (onNullType) { case NULL: builder.append(" NULL ON NULL"); break; @@ -225,9 +229,9 @@ public StringBuilder appendObject(StringBuilder builder) { // this should never happen } } - - if (uniqueKeysType!=null) { - switch(uniqueKeysType) { + + if (uniqueKeysType != null) { + switch (uniqueKeysType) { case WITH: builder.append(" WITH UNIQUE KEYS"); break; @@ -238,29 +242,29 @@ public StringBuilder appendObject(StringBuilder builder) { // this should never happen } } - + builder.append(" ) "); - - + + // FILTER( WHERE expression ) OVER windowNameOrSpecification super.append(builder); - + return builder; } - + @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"}) public StringBuilder appendArray(StringBuilder builder) { builder.append("JSON_ARRAYAGG( "); builder.append(expression).append(" "); - + if (usingFormatJson) { builder.append("FORMAT JSON "); } - + expressionOrderBy.toStringOrderByElements(builder); - - if (onNullType!=null) { - switch(onNullType) { + + if (onNullType != null) { + switch (onNullType) { case NULL: builder.append(" NULL ON NULL "); break; @@ -272,17 +276,17 @@ public StringBuilder appendArray(StringBuilder builder) { } } builder.append(") "); - - + + // FILTER( WHERE expression ) OVER windowNameOrSpecification super.append(builder); - + return builder; } @Override public String toString() { - StringBuilder builder = new StringBuilder(); - return append(builder).toString(); + StringBuilder builder = new StringBuilder(); + return append(builder).toString(); } } 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..5b0f97b4c 100644 --- a/src/main/java/net/sf/jsqlparser/expression/JsonExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/JsonExpression.java @@ -18,9 +18,8 @@ import java.util.Map; public class JsonExpression extends ASTNodeAccessImpl implements Expression { - private Expression expr; - private final List> idents = new ArrayList<>(); + private Expression expr; public JsonExpression() { @@ -36,8 +35,8 @@ public JsonExpression(Expression expr, List> 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() { diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonFunction.java b/src/main/java/net/sf/jsqlparser/expression/JsonFunction.java index 9d09b9711..4422c1beb 100644 --- a/src/main/java/net/sf/jsqlparser/expression/JsonFunction.java +++ b/src/main/java/net/sf/jsqlparser/expression/JsonFunction.java @@ -11,251 +11,254 @@ import java.util.ArrayList; import java.util.Objects; + import net.sf.jsqlparser.parser.ASTNodeAccessImpl; /** - * * @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 + private final ArrayList keyValuePairs = new ArrayList<>(); + private final ArrayList expressions = new ArrayList<>(); + private JsonFunctionType functionType; + private JsonAggregateOnNullType onNullType; + private JsonAggregateUniqueKeysType uniqueKeysType; + + public ArrayList getKeyValuePairs() { + return keyValuePairs; } - 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 "); - } - 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++; + + 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; } - 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 - } + public JsonFunction withOnNullType(JsonAggregateOnNullType onNullType) { + this.setOnNullType(onNullType); + return this; } - 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 - } + public JsonAggregateUniqueKeysType getUniqueKeysType() { + return uniqueKeysType; } - builder.append(" ) "); + public void setUniqueKeysType(JsonAggregateUniqueKeysType uniqueKeysType) { + this.uniqueKeysType = uniqueKeysType; + } - return builder; - } + public JsonFunction withUniqueKeysType(JsonAggregateUniqueKeysType uniqueKeysType) { + this.setUniqueKeysType(uniqueKeysType); + return this; + } + public JsonFunctionType getType() { + return functionType; + } - @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()); - } + public void setType(JsonFunctionType type) { + this.functionType = + Objects.requireNonNull(type, + "The Type of the JSON Aggregate Function must not be null"); } - 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++; + + public void setType(String typeName) { + this.functionType = JsonFunctionType.valueOf( + Objects.requireNonNull(typeName, + "The Type of the JSON Aggregate Function must not be null") + .toUpperCase()); } - 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++; + + public JsonFunction withType(JsonFunctionType type) { + this.setType(type); + return this; } - 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 - } + public JsonFunction withType(String typeName) { + this.setType(typeName); + return this; } - builder.append(") "); - return builder; - } + @Override + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); + } - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - return append(builder).toString(); - } + // 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 "); + } + 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(); + } } diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonFunctionExpression.java b/src/main/java/net/sf/jsqlparser/expression/JsonFunctionExpression.java index e23aa2751..5df7ad310 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 */ @@ -26,6 +25,7 @@ public class JsonFunctionExpression implements Serializable { public JsonFunctionExpression(Expression expression) { this.expression = Objects.requireNonNull(expression, "The EXPRESSION must not be null"); } + public Expression getExpression() { return expression; } @@ -37,12 +37,12 @@ public boolean isUsingFormatJson() { public void setUsingFormatJson(boolean usingFormatJson) { this.usingFormatJson = usingFormatJson; } - + public JsonFunctionExpression withUsingFormatJson(boolean usingFormatJson) { this.setUsingFormatJson(usingFormatJson); return this; } - + public StringBuilder append(StringBuilder builder) { return builder.append(getExpression()).append(isUsingFormatJson() ? " FORMAT JSON" : ""); } diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonFunctionType.java b/src/main/java/net/sf/jsqlparser/expression/JsonFunctionType.java index 4502b3ca6..43a33aab6 100644 --- a/src/main/java/net/sf/jsqlparser/expression/JsonFunctionType.java +++ b/src/main/java/net/sf/jsqlparser/expression/JsonFunctionType.java @@ -11,7 +11,6 @@ package net.sf.jsqlparser.expression; /** - * * @author Andreas Reichel */ public enum JsonFunctionType { diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePair.java b/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePair.java index b85274caa..f1119071d 100644 --- a/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePair.java +++ b/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePair.java @@ -14,114 +14,113 @@ 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 String key; + private final Object value; + private boolean usingKeyKeyword = false; + 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(); + } } 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 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/LambdaExpression.java b/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java new file mode 100644 index 000000000..46d057f96 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java @@ -0,0 +1,72 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; + +import java.util.Arrays; +import java.util.List; + +public class LambdaExpression extends ASTNodeAccessImpl implements Expression { + private List identifiers; + private Expression expression; + + public LambdaExpression(String identifier, Expression expression) { + this.identifiers = Arrays.asList(identifier); + this.expression = expression; + } + + public LambdaExpression(List identifiers, Expression expression) { + this.identifiers = identifiers; + this.expression = expression; + } + + public List getIdentifiers() { + return identifiers; + } + + public LambdaExpression setIdentifiers(List identifiers) { + this.identifiers = identifiers; + return this; + } + + public Expression getExpression() { + return expression; + } + + public LambdaExpression setExpression(Expression expression) { + this.expression = expression; + return this; + } + + public StringBuilder appendTo(StringBuilder builder) { + if (identifiers.size() == 1) { + builder.append(identifiers.get(0)); + } else { + int i = 0; + builder.append("( "); + for (String s : identifiers) { + builder.append(i++ > 0 ? ", " : "").append(s); + } + builder.append(" )"); + } + return builder.append(" -> ").append(expression); + } + + @Override + public String toString() { + return appendTo(new StringBuilder()).toString(); + } + + @Override + 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/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..342ad1390 100644 --- a/src/main/java/net/sf/jsqlparser/expression/NextValExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/NextValExpression.java @@ -1,21 +1,18 @@ -/* - - * #%L - * JSQLParser library - * %% - * Copyright (C) 2004 - 2019 JSQLParser - * %% - * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 - * #L% +/* + * - #%L JSQLParser library %% Copyright (C) 2004 - 2019 JSQLParser %% Dual licensed under GNU LGPL + * 2.1 or Apache License 2.0 #L% */ package net.sf.jsqlparser.expression; import java.util.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 +60,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..6ec4c6a8b 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 diff --git a/src/main/java/net/sf/jsqlparser/expression/OracleHint.java b/src/main/java/net/sf/jsqlparser/expression/OracleHint.java index c229e880e..35ba8ad3b 100644 --- a/src/main/java/net/sf/jsqlparser/expression/OracleHint.java +++ b/src/main/java/net/sf/jsqlparser/expression/OracleHint.java @@ -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 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/Parenthesis.java b/src/main/java/net/sf/jsqlparser/expression/Parenthesis.java index 51d3ef707..c162cd1ef 100644 --- a/src/main/java/net/sf/jsqlparser/expression/Parenthesis.java +++ b/src/main/java/net/sf/jsqlparser/expression/Parenthesis.java @@ -9,45 +9,29 @@ */ package net.sf.jsqlparser.expression; -import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; /** - * It represents an expression like "(" expression ")" + * @deprecated This class is deprecated since version 5.0. Use {@link ParenthesedExpressionList} + * instead. The reason for deprecation is the ambiguity and redundancy. */ -public class Parenthesis extends ASTNodeAccessImpl implements Expression { - - private Expression expression; - - public Parenthesis() {} - - public Parenthesis(Expression expression) { - setExpression(expression); - } - +@Deprecated(since = "5.0", forRemoval = true) +public class Parenthesis extends ParenthesedExpressionList { public Expression getExpression() { - return expression; - } - - public final void setExpression(Expression expression) { - this.expression = expression; - } - - @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + return isEmpty() ? null : get(0); } - @Override - public String toString() { - return "(" + (expression != null ? expression : "") + ")"; + public Parenthesis setExpression(Expression expression) { + this.set(0, expression); + return this; } public Parenthesis withExpression(Expression expression) { - this.setExpression(expression); - return this; + return this.setExpression(expression); } public E getExpression(Class type) { return type.cast(getExpression()); } + } diff --git a/src/main/java/net/sf/jsqlparser/expression/PartitionByClause.java b/src/main/java/net/sf/jsqlparser/expression/PartitionByClause.java index 0b0f70663..243975029 100644 --- a/src/main/java/net/sf/jsqlparser/expression/PartitionByClause.java +++ b/src/main/java/net/sf/jsqlparser/expression/PartitionByClause.java @@ -21,25 +21,27 @@ public class PartitionByClause implements Serializable { public ExpressionList getPartitionExpressionList() { return partitionExpressionList; } - + public void setPartitionExpressionList(ExpressionList partitionExpressionList) { setPartitionExpressionList(partitionExpressionList, false); } - public void setPartitionExpressionList(ExpressionList partitionExpressionList, boolean brackets) { + public void setPartitionExpressionList(ExpressionList partitionExpressionList, + boolean brackets) { this.partitionExpressionList = partitionExpressionList; this.brackets = brackets; } public void toStringPartitionBy(StringBuilder b) { - if (partitionExpressionList != null && !partitionExpressionList.getExpressions().isEmpty()) { + if (partitionExpressionList != null + && !partitionExpressionList.getExpressions().isEmpty()) { b.append("PARTITION BY "); - b.append(PlainSelect. - getStringList(partitionExpressionList.getExpressions(), true, brackets)); + b.append(PlainSelect.getStringList(partitionExpressionList.getExpressions(), true, + brackets)); b.append(" "); } } - + public boolean isBrackets() { return brackets; } 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/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..ec77f54a9 100644 --- a/src/main/java/net/sf/jsqlparser/expression/StringValue.java +++ b/src/main/java/net/sf/jsqlparser/expression/StringValue.java @@ -20,11 +20,10 @@ */ 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; public StringValue() { // empty constructor @@ -57,10 +56,18 @@ 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 getNotExcapedValue() { StringBuilder buffer = new StringBuilder(value); int index = 0; @@ -73,17 +80,9 @@ 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 diff --git a/src/main/java/net/sf/jsqlparser/expression/StructType.java b/src/main/java/net/sf/jsqlparser/expression/StructType.java new file mode 100644 index 000000000..4bd38a693 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/StructType.java @@ -0,0 +1,198 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import net.sf.jsqlparser.statement.create.table.ColDataType; +import net.sf.jsqlparser.statement.select.SelectItem; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/* + * 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;; + private String keyword; + private List> parameters; + private List> arguments; + + public StructType(Dialect dialect, String keyword, + List> parameters, + List> arguments) { + this.dialect = dialect; + this.keyword = keyword; + this.parameters = parameters; + this.arguments = arguments; + } + + public StructType(Dialect dialect, List> parameters, + List> arguments) { + this.dialect = dialect; + this.parameters = parameters; + this.arguments = arguments; + } + + public StructType(Dialect dialect, List> arguments) { + this.dialect = dialect; + this.arguments = arguments; + } + + public Dialect getDialect() { + return dialect; + } + + public StructType setDialect(Dialect dialect) { + this.dialect = dialect; + return this; + } + + public String getKeyword() { + return keyword; + } + + public StructType setKeyword(String keyword) { + this.keyword = keyword; + return this; + } + + public List> getParameters() { + return parameters; + } + + public StructType setParameters(List> parameters) { + this.parameters = parameters; + return this; + } + + public List> getArguments() { + return arguments; + } + + public StructType setArguments(List> arguments) { + this.arguments = arguments; + return this; + } + + public StructType add(Expression expression, String aliasName) { + if (arguments == null) { + arguments = new ArrayList<>(); + } + arguments.add(new SelectItem<>(expression, aliasName)); + + return this; + } + + public StringBuilder appendTo(StringBuilder builder) { + if (dialect != Dialect.DUCKDB && keyword != null) { + builder.append(keyword); + } + + if (dialect != Dialect.DUCKDB && parameters != null && !parameters.isEmpty()) { + builder.append("<"); + int i = 0; + + for (Map.Entry e : parameters) { + if (0 < i++) { + builder.append(","); + } + // optional name + if (e.getKey() != null && !e.getKey().isEmpty()) { + builder.append(e.getKey()).append(" "); + } + + // mandatory type + builder.append(e.getValue()); + } + + builder.append(">"); + } + + if (arguments != null && !arguments.isEmpty()) { + + if (dialect == Dialect.DUCKDB) { + builder.append("{ "); + int i = 0; + for (SelectItem e : arguments) { + if (0 < i++) { + builder.append(","); + } + builder.append(e.getAlias().getName()); + builder.append(":"); + builder.append(e.getExpression()); + } + builder.append(" }"); + } else { + builder.append("("); + int i = 0; + for (SelectItem e : arguments) { + if (0 < i++) { + builder.append(","); + } + e.appendTo(builder); + } + + builder.append(")"); + } + } + + if (dialect == Dialect.DUCKDB && parameters != null && !parameters.isEmpty()) { + builder.append("::STRUCT( "); + int i = 0; + + for (Map.Entry e : parameters) { + if (0 < i++) { + builder.append(","); + } + builder.append(e.getKey()).append(" "); + builder.append(e.getValue()); + } + builder.append(")"); + } + + return builder; + } + + @Override + public String toString() { + return appendTo(new StringBuilder()).toString(); + } + + @Override + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); + } + + public enum Dialect { + BIG_QUERY, DUCKDB + } +} 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 6fe53154f..a67572ace 100644 --- a/src/main/java/net/sf/jsqlparser/expression/TimezoneExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/TimezoneExpression.java @@ -12,41 +12,52 @@ import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import java.util.Arrays; import java.util.List; public class TimezoneExpression extends ASTNodeAccessImpl implements Expression { + private final ExpressionList timezoneExpressions = new ExpressionList<>(); private Expression leftExpression; - private ExpressionList timezoneExpressions = new ExpressionList<>(); + + public TimezoneExpression() { + leftExpression = null; + } + + public TimezoneExpression(Expression leftExpression, Expression... timezoneExpressions) { + this.leftExpression = leftExpression; + this.timezoneExpressions.addAll(Arrays.asList(timezoneExpressions)); + } public Expression getLeftExpression() { return leftExpression; } - public void setLeftExpression(Expression expression) { - leftExpression = expression; + public TimezoneExpression setLeftExpression(Expression expression) { + this.leftExpression = expression; + return this; } @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } public List getTimezoneExpressions() { return timezoneExpressions; } - public void addTimezoneExpression(Expression timezoneExpr) { - this.timezoneExpressions.add(timezoneExpr); + public void addTimezoneExpression(Expression... timezoneExpr) { + this.timezoneExpressions.addAll(Arrays.asList(timezoneExpr)); } @Override public String toString() { - String returnValue = getLeftExpression().toString(); + StringBuilder returnValue = new StringBuilder(leftExpression.toString()); for (Expression expr : timezoneExpressions) { - returnValue += " AT TIME ZONE " + expr.toString(); + returnValue.append(" AT TIME ZONE ").append(expr.toString()); } - return returnValue; + return returnValue.toString(); } } diff --git a/src/main/java/net/sf/jsqlparser/expression/TranscodingFunction.java b/src/main/java/net/sf/jsqlparser/expression/TranscodingFunction.java index 61fa05290..343579e29 100644 --- a/src/main/java/net/sf/jsqlparser/expression/TranscodingFunction.java +++ b/src/main/java/net/sf/jsqlparser/expression/TranscodingFunction.java @@ -10,8 +10,11 @@ package net.sf.jsqlparser.expression; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import net.sf.jsqlparser.statement.create.table.ColDataType; public class TranscodingFunction extends ASTNodeAccessImpl implements Expression { + private boolean isTranscodeStyle = true; + private ColDataType colDataType; private Expression expression; private String transcodingName; @@ -20,6 +23,14 @@ public TranscodingFunction(Expression expression, String transcodingName) { this.transcodingName = transcodingName; } + public TranscodingFunction(ColDataType colDataType, Expression expression, + String transcodingName) { + this.colDataType = colDataType; + this.expression = expression; + this.transcodingName = transcodingName; + this.isTranscodeStyle = false; + } + public TranscodingFunction() { this(null, null); } @@ -51,17 +62,47 @@ public TranscodingFunction withTranscodingName(String transcodingName) { } - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public ColDataType getColDataType() { + return colDataType; + } + + public TranscodingFunction setColDataType(ColDataType colDataType) { + this.colDataType = colDataType; + return this; + } + + public boolean isTranscodeStyle() { + return isTranscodeStyle; + } + + public TranscodingFunction setTranscodeStyle(boolean transcodeStyle) { + isTranscodeStyle = transcodeStyle; + return this; + } + + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } public StringBuilder appendTo(StringBuilder builder) { - return builder - .append("CONVERT( ") - .append(expression) - .append(" USING ") - .append(transcodingName) - .append(" )"); + if (isTranscodeStyle) { + return builder + .append("CONVERT( ") + .append(expression) + .append(" USING ") + .append(transcodingName) + .append(" )"); + } else { + return builder + .append("CONVERT( ") + .append(colDataType) + .append(", ") + .append(expression) + .append(transcodingName != null && !transcodingName.isEmpty() + ? ", " + transcodingName + : "") + .append(" )"); + } } @Override 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..ece2bd13a 100644 --- a/src/main/java/net/sf/jsqlparser/expression/UserVariable.java +++ b/src/main/java/net/sf/jsqlparser/expression/UserVariable.java @@ -36,8 +36,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); } 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 2d4de0b29..5ed58de11 100644 --- a/src/main/java/net/sf/jsqlparser/expression/WhenClause.java +++ b/src/main/java/net/sf/jsqlparser/expression/WhenClause.java @@ -12,17 +12,23 @@ import net.sf.jsqlparser.parser.ASTNodeAccessImpl; /** - * A clause of following syntax: WHEN condition THEN expression. Which is part - * of a CaseExpression. + * A clause of following syntax: WHEN condition THEN expression. Which is part of a CaseExpression. */ public class WhenClause extends ASTNodeAccessImpl implements Expression { private Expression whenExpression; private Expression thenExpression; + public WhenClause() {} + + public WhenClause(Expression whenExpression, Expression thenExpression) { + this.whenExpression = whenExpression; + this.thenExpression = 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..a5df35aa6 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; @@ -54,7 +55,8 @@ public void setPartitionExpressionList(ExpressionList partitionExpressionList) { setPartitionExpressionList(partitionExpressionList, false); } - public void setPartitionExpressionList(ExpressionList partitionExpressionList, boolean brackets) { + public void setPartitionExpressionList(ExpressionList partitionExpressionList, + boolean brackets) { partitionBy.setPartitionExpressionList(partitionExpressionList, brackets); } @@ -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 cc1d9620e..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 @@ -15,9 +15,15 @@ public class Addition extends BinaryExpression { + public Addition() {} + + public Addition(Expression leftExpression, Expression rightExpression) { + super(leftExpression, 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 54e031bf5..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 @@ -15,9 +15,15 @@ public class BitwiseAnd extends BinaryExpression { + public BitwiseAnd() {} + + public BitwiseAnd(Expression leftExpression, Expression rightExpression) { + super(leftExpression, 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 ddd529f2e..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 @@ -15,9 +15,15 @@ public class BitwiseLeftShift extends BinaryExpression { + public BitwiseLeftShift() {} + + public BitwiseLeftShift(Expression leftExpression, Expression rightExpression) { + super(leftExpression, 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 f381bb8c9..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 @@ -15,9 +15,15 @@ public class BitwiseOr extends BinaryExpression { + public BitwiseOr() {} + + public BitwiseOr(Expression leftExpression, Expression rightExpression) { + super(leftExpression, 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 f697cfd06..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 @@ -15,9 +15,15 @@ public class BitwiseRightShift extends BinaryExpression { + public BitwiseRightShift() {} + + public BitwiseRightShift(Expression leftExpression, Expression rightExpression) { + super(leftExpression, 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 d543ee42b..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 @@ -15,9 +15,15 @@ public class BitwiseXor extends BinaryExpression { + public BitwiseXor() {} + + public BitwiseXor(Expression leftExpression, Expression rightExpression) { + super(leftExpression, 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 50ad8cf7b..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 @@ -15,9 +15,15 @@ public class Concat extends BinaryExpression { + public Concat() {} + + public Concat(Expression leftExpression, Expression rightExpression) { + super(leftExpression, 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 c980d87c3..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 @@ -15,9 +15,15 @@ public class Division extends BinaryExpression { + public Division() {} + + public Division(Expression leftExpression, Expression rightExpression) { + super(leftExpression, 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 f9ac96fb6..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 @@ -15,9 +15,15 @@ public class IntegerDivision extends BinaryExpression { + public IntegerDivision() {} + + public IntegerDivision(Expression leftExpression, Expression rightExpression) { + super(leftExpression, 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 ff0ad6eb4..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 @@ -18,12 +18,15 @@ */ public class Modulo extends BinaryExpression { - public Modulo() { + public Modulo() {} + + public Modulo(Expression leftExpression, Expression rightExpression) { + super(leftExpression, 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 db66fb1d4..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 @@ -15,9 +15,15 @@ public class Multiplication extends BinaryExpression { + public Multiplication() {} + + public Multiplication(Expression leftExpression, Expression rightExpression) { + super(leftExpression, 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 87615f6c1..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 @@ -15,9 +15,15 @@ public class Subtraction extends BinaryExpression { + public Subtraction() {} + + public Subtraction(Expression leftExpression, Expression rightExpression) { + super(leftExpression, 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..1cd997216 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 @@ -27,42 +27,43 @@ public Expression getBetweenExpressionEnd() { return betweenExpressionEnd; } - public Expression getBetweenExpressionStart() { - return betweenExpressionStart; - } - - public Expression getLeftExpression() { - return leftExpression; - } - - public boolean isNot() { - return not; - } - 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 setNot(boolean b) { not = b; } @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 " + 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/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 new file mode 100644 index 000000000..847ff087c --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExcludesExpression.java @@ -0,0 +1,78 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2019 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression.operators.relational; + +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.ExpressionVisitor; +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; + +public class ExcludesExpression extends ASTNodeAccessImpl implements Expression { + + private Expression leftExpression; + private Expression rightExpression; + + public ExcludesExpression() {} + + public ExcludesExpression(Expression leftExpression, Expression rightExpression) { + this.leftExpression = leftExpression; + this.rightExpression = rightExpression; + } + + public Expression getLeftExpression() { + return leftExpression; + } + + public final void setLeftExpression(Expression expression) { + leftExpression = expression; + } + + public ExcludesExpression withLeftExpression(Expression expression) { + this.setLeftExpression(expression); + return this; + } + + public Expression getRightExpression() { + return rightExpression; + } + + public void setRightExpression(Expression rightExpression) { + this.rightExpression = rightExpression; + } + + @Override + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); + } + + @Override + public String toString() { + StringBuilder statementBuilder = new StringBuilder(); + statementBuilder.append(leftExpression); + + statementBuilder.append(" "); + statementBuilder.append("EXCLUDES "); + + statementBuilder.append(rightExpression); + return statementBuilder.toString(); + } + + public ExcludesExpression withRightExpression(Expression rightExpression) { + this.setRightExpression(rightExpression); + return this; + } + + public E getLeftExpression(Class type) { + return type.cast(getLeftExpression()); + } + + public E getRightExpression(Class type) { + return type.cast(getRightExpression()); + } +} 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..2abbae1db 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 @@ -94,10 +94,6 @@ public String toString() { return appendTo(new StringBuilder()).toString(); } - @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); - } @Override public SimpleNode getASTNode() { @@ -108,4 +104,9 @@ public SimpleNode getASTNode() { public void setASTNode(SimpleNode 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..f191ae1a1 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 @@ -32,12 +32,16 @@ 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) { @@ -52,21 +56,17 @@ public void setAgainstValue(JdbcParameter val) { this._againstValue = 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 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 1a22e867b..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 @@ -18,9 +18,13 @@ public GreaterThan() { super(">"); } + public GreaterThan(Expression leftExpression, Expression rightExpression) { + super(">", leftExpression, 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 2ff66a134..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 @@ -22,9 +22,13 @@ public GreaterThanEquals(String operator) { super(operator); } + public GreaterThanEquals(Expression leftExpression, Expression rightExpression) { + super(">=", leftExpression, 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/InExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/InExpression.java index af6ad913d..743d8a0aa 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/InExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/InExpression.java @@ -29,6 +29,11 @@ public InExpression(Expression leftExpression, Expression rightExpression) { this.rightExpression = rightExpression; } + @Override + public int getOldOracleJoinSyntax() { + return oldOracleJoinSyntax; + } + @Override public void setOldOracleJoinSyntax(int oldOracleJoinSyntax) { this.oldOracleJoinSyntax = oldOracleJoinSyntax; @@ -39,24 +44,19 @@ public void setOldOracleJoinSyntax(int oldOracleJoinSyntax) { } } - @Override - public int getOldOracleJoinSyntax() { - return oldOracleJoinSyntax; - } - public Expression getLeftExpression() { return leftExpression; } + public final void setLeftExpression(Expression expression) { + leftExpression = expression; + } + public InExpression withLeftExpression(Expression expression) { this.setLeftExpression(expression); return this; } - public final void setLeftExpression(Expression expression) { - leftExpression = expression; - } - public boolean isGlobal() { return global; } @@ -83,8 +83,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); } private String getLeftExpressionString() { diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/IncludesExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/IncludesExpression.java new file mode 100644 index 000000000..b0b260e72 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/IncludesExpression.java @@ -0,0 +1,79 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2019 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression.operators.relational; + +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.ExpressionVisitor; +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; + +public class IncludesExpression extends ASTNodeAccessImpl + implements Expression { + + private Expression leftExpression; + private Expression rightExpression; + + public IncludesExpression() {} + + public IncludesExpression(Expression leftExpression, Expression rightExpression) { + this.leftExpression = leftExpression; + this.rightExpression = rightExpression; + } + + public Expression getLeftExpression() { + return leftExpression; + } + + public final void setLeftExpression(Expression expression) { + leftExpression = expression; + } + + public IncludesExpression withLeftExpression(Expression expression) { + this.setLeftExpression(expression); + return this; + } + + public Expression getRightExpression() { + return rightExpression; + } + + public void setRightExpression(Expression rightExpression) { + this.rightExpression = rightExpression; + } + + @Override + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); + } + + @Override + public String toString() { + StringBuilder statementBuilder = new StringBuilder(); + statementBuilder.append(leftExpression); + + statementBuilder.append(" "); + statementBuilder.append("INCLUDES "); + + statementBuilder.append(rightExpression); + return statementBuilder.toString(); + } + + public IncludesExpression withRightExpression(Expression rightExpression) { + this.setRightExpression(rightExpression); + return this; + } + + public E getLeftExpression(Class type) { + return type.cast(getLeftExpression()); + } + + public E getRightExpression(Class type) { + return type.cast(getRightExpression()); + } +} diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/IsBooleanExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/IsBooleanExpression.java index 68ce5eed4..3c8336533 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/IsBooleanExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/IsBooleanExpression.java @@ -23,14 +23,14 @@ public Expression getLeftExpression() { return leftExpression; } - public boolean isNot() { - return not; - } - public void setLeftExpression(Expression expression) { leftExpression = expression; } + public boolean isNot() { + return not; + } + public void setNot(boolean b) { not = b; } @@ -44,8 +44,8 @@ public void setIsTrue(boolean isTrue) { } @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/IsDistinctExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/IsDistinctExpression.java index 4cff4ac0e..60add6b6e 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/IsDistinctExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/IsDistinctExpression.java @@ -25,8 +25,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); } @Override diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/IsNullExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/IsNullExpression.java index b292b827a..393f9f194 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/IsNullExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/IsNullExpression.java @@ -12,6 +12,7 @@ import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import net.sf.jsqlparser.schema.Column; public class IsNullExpression extends ASTNodeAccessImpl implements Expression { @@ -20,18 +21,29 @@ public class IsNullExpression extends ASTNodeAccessImpl implements Expression { private boolean useIsNull = false; private boolean useNotNull = false; - public Expression getLeftExpression() { - return leftExpression; + public IsNullExpression() {} + + public IsNullExpression(Expression leftExpression) { + this.leftExpression = leftExpression; } - public boolean isNot() { - return not; + public IsNullExpression(String columnName, boolean not) { + this.leftExpression = new Column(columnName); + this.not = not; + } + + public Expression getLeftExpression() { + return leftExpression; } public void setLeftExpression(Expression expression) { leftExpression = expression; } + public boolean isNot() { + return not; + } + public void setNot(boolean b) { not = b; } @@ -54,8 +66,8 @@ public IsNullExpression setUseNotNull(boolean useNotNull) { } @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/JsonOperator.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/JsonOperator.java index 5525b1e05..94237e8f6 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/JsonOperator.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/JsonOperator.java @@ -15,15 +15,15 @@ public class JsonOperator extends BinaryExpression { - private String op; //"@>" + private String op; // "@>" public JsonOperator(String op) { this.op = op; } @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/LikeExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/LikeExpression.java index 13bb3a223..cf55678ce 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/LikeExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/LikeExpression.java @@ -14,14 +14,6 @@ import net.sf.jsqlparser.expression.ExpressionVisitor; public class LikeExpression extends BinaryExpression { - public enum KeyWord { - LIKE, ILIKE, RLIKE, REGEXP; - - public static KeyWord from(String keyword) { - return Enum.valueOf(KeyWord.class, keyword.toUpperCase()); - } - } - private boolean not = false; private boolean useBinary = false; private Expression escapeExpression = null; @@ -45,8 +37,8 @@ public LikeExpression setUseBinary(boolean useBinary) { } @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } @Deprecated @@ -58,7 +50,8 @@ public String getStringExpression() { @Override public String toString() { String retval = getLeftExpression() + " " + (not ? "NOT " : "") - + likeKeyWord + " " + (useBinary ? "BINARY " : "") + getRightExpression(); + + (likeKeyWord == KeyWord.SIMILAR_TO ? "SIMILAR TO" : likeKeyWord) + " " + + (useBinary ? "BINARY " : "") + getRightExpression(); if (escapeExpression != null) { retval += " ESCAPE " + escapeExpression; } @@ -122,4 +115,12 @@ public LikeExpression withLeftExpression(Expression arg0) { public LikeExpression withRightExpression(Expression arg0) { return (LikeExpression) super.withRightExpression(arg0); } + + public enum KeyWord { + LIKE, ILIKE, RLIKE, REGEXP, SIMILAR_TO; + + public static KeyWord from(String keyword) { + return Enum.valueOf(KeyWord.class, keyword.toUpperCase().replaceAll("\\s+", "_")); + } + } } diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/Matches.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/Matches.java index 4c2e1cb4b..1388fa51f 100755 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/Matches.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/Matches.java @@ -15,8 +15,8 @@ public class Matches extends OldOracleJoinBinaryExpression { @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/MemberOfExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpression.java index 590606629..d602e6278 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpression.java @@ -57,7 +57,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/operators/relational/MinorThan.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/MinorThan.java index 717e59493..3f6ddd267 100755 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/MinorThan.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/MinorThan.java @@ -18,9 +18,13 @@ public MinorThan() { super("<"); } + public MinorThan(Expression leftExpression, Expression rightExpression) { + super("<", leftExpression, 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/MinorThanEquals.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/MinorThanEquals.java index 2bdc5eef1..5318a0d27 100755 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/MinorThanEquals.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/MinorThanEquals.java @@ -22,9 +22,13 @@ public MinorThanEquals(String operator) { super(operator); } + public MinorThanEquals(Expression leftExpression, Expression rightExpression) { + super("<=", leftExpression, 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/NotEqualsTo.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/NotEqualsTo.java index 397a4fb84..c6e1ef3cb 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/NotEqualsTo.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/NotEqualsTo.java @@ -39,8 +39,8 @@ public NotEqualsTo 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/OldOracleJoinBinaryExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/OldOracleJoinBinaryExpression.java index e607ee36c..46b093b7d 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/OldOracleJoinBinaryExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/OldOracleJoinBinaryExpression.java @@ -12,24 +12,17 @@ import net.sf.jsqlparser.expression.BinaryExpression; import net.sf.jsqlparser.expression.Expression; -public abstract class OldOracleJoinBinaryExpression extends BinaryExpression implements SupportsOldOracleJoinSyntax { +public abstract class OldOracleJoinBinaryExpression extends BinaryExpression + implements SupportsOldOracleJoinSyntax { private int oldOracleJoinSyntax = NO_ORACLE_JOIN; private int oraclePriorPosition = NO_ORACLE_PRIOR; - @Override - public void setOldOracleJoinSyntax(int oldOracleJoinSyntax) { - this.oldOracleJoinSyntax = oldOracleJoinSyntax; - if (oldOracleJoinSyntax < 0 || oldOracleJoinSyntax > 2) { - throw new IllegalArgumentException("unknown join type for oracle found (type=" + oldOracleJoinSyntax + ")"); - } - } - @Override public String toString() { - return //(isNot() ? "NOT " : "") - (oraclePriorPosition == ORACLE_PRIOR_START ? "PRIOR " : "") + return // (isNot() ? "NOT " : "") + (oraclePriorPosition == ORACLE_PRIOR_START ? "PRIOR " : "") + getLeftExpression() + (oldOracleJoinSyntax == ORACLE_JOIN_RIGHT ? "(+)" : "") + " " + getStringExpression() + " " @@ -43,6 +36,15 @@ public int getOldOracleJoinSyntax() { return oldOracleJoinSyntax; } + @Override + public void setOldOracleJoinSyntax(int oldOracleJoinSyntax) { + this.oldOracleJoinSyntax = oldOracleJoinSyntax; + if (oldOracleJoinSyntax < 0 || oldOracleJoinSyntax > 2) { + throw new IllegalArgumentException( + "unknown join type for oracle found (type=" + oldOracleJoinSyntax + ")"); + } + } + @Override public int getOraclePriorPosition() { return oraclePriorPosition; diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ParenthesedExpressionList.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ParenthesedExpressionList.java index 13efb57c8..dc71ea6ad 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ParenthesedExpressionList.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ParenthesedExpressionList.java @@ -22,6 +22,7 @@ public ParenthesedExpressionList(ExpressionList expressions) { addAll(expressions); } + @SafeVarargs public ParenthesedExpressionList(T... expressions) { addAll(Arrays.asList(expressions)); } @@ -31,7 +32,7 @@ public ParenthesedExpressionList(Collection expressions) { } public static ParenthesedExpressionList from(ExpressionList expressions) { - return new ParenthesedExpressionList(expressions); + return new ParenthesedExpressionList<>(expressions); } @Override diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/RegExpMatchOperator.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/RegExpMatchOperator.java index bffafc71d..786f60407 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/RegExpMatchOperator.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/RegExpMatchOperator.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.expression.operators.relational; import java.util.Objects; + import net.sf.jsqlparser.expression.BinaryExpression; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; @@ -19,7 +20,8 @@ public class RegExpMatchOperator extends BinaryExpression { private RegExpMatchOperatorType operatorType; public RegExpMatchOperator(RegExpMatchOperatorType operatorType) { - this.operatorType = Objects.requireNonNull(operatorType, "The provided RegExpMatchOperatorType must not be NULL."); + this.operatorType = Objects.requireNonNull(operatorType, + "The provided RegExpMatchOperatorType must not be NULL."); } public RegExpMatchOperatorType getOperatorType() { @@ -27,8 +29,8 @@ public RegExpMatchOperatorType getOperatorType() { } @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/RegExpMatchOperatorType.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/RegExpMatchOperatorType.java index 8d324a4ab..c22f05eee 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/RegExpMatchOperatorType.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/RegExpMatchOperatorType.java @@ -13,8 +13,5 @@ * PostgresSQL match operators. */ public enum RegExpMatchOperatorType { - MATCH_CASESENSITIVE, - MATCH_CASEINSENSITIVE, - NOT_MATCH_CASESENSITIVE, - NOT_MATCH_CASEINSENSITIVE + MATCH_CASESENSITIVE, MATCH_CASEINSENSITIVE, NOT_MATCH_CASESENSITIVE, NOT_MATCH_CASEINSENSITIVE } diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/SimilarToExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/SimilarToExpression.java index ae460e42b..0818d75c0 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/SimilarToExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/SimilarToExpression.java @@ -27,8 +27,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); } @Override @@ -38,7 +38,8 @@ public String getStringExpression() { @Override public String toString() { - String retval = getLeftExpression() + " " + (not ? "NOT " : "") + getStringExpression() + " " + getRightExpression(); + String retval = getLeftExpression() + " " + (not ? "NOT " : "") + getStringExpression() + + " " + getRightExpression(); if (escape != null) { retval += " ESCAPE " + "'" + escape + "'"; } diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/TSQLLeftJoin.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/TSQLLeftJoin.java index e654bab2d..aa1b90e16 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/TSQLLeftJoin.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/TSQLLeftJoin.java @@ -18,7 +18,7 @@ public TSQLLeftJoin() { } @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/TSQLRightJoin.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/TSQLRightJoin.java index a38ad4a9a..fcb3e9dc4 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/TSQLRightJoin.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/TSQLRightJoin.java @@ -18,7 +18,7 @@ public TSQLRightJoin() { } @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/parser/ASTNodeAccessImpl.java b/src/main/java/net/sf/jsqlparser/parser/ASTNodeAccessImpl.java index e13ec6ff6..8ecbca8bc 100644 --- a/src/main/java/net/sf/jsqlparser/parser/ASTNodeAccessImpl.java +++ b/src/main/java/net/sf/jsqlparser/parser/ASTNodeAccessImpl.java @@ -9,6 +9,9 @@ */ package net.sf.jsqlparser.parser; +import java.util.Set; +import java.util.TreeSet; + public class ASTNodeAccessImpl implements ASTNodeAccess { private transient SimpleNode node; @@ -24,14 +27,42 @@ public void setASTNode(SimpleNode node) { } public StringBuilder appendTo(StringBuilder builder) { + // don't add spaces around the following punctuation + final Set punctuation = new TreeSet<>(Set.of(".", "[", "]")); + SimpleNode simpleNode = getASTNode(); - Token token = simpleNode.jjtGetFirstToken(); - Token lastToken = simpleNode.jjtGetLastToken(); - while (token.next != null && token.absoluteEnd <= lastToken.absoluteEnd) { - builder.append(" ").append(token.image); - token = token.next; + if (simpleNode != null) { + Token token = simpleNode.jjtGetFirstToken(); + Token lastToken = simpleNode.jjtGetLastToken(); + Token prevToken = null; + while (token.next != null && token.absoluteEnd <= lastToken.absoluteEnd) { + if (!punctuation.contains(token.image) + && (prevToken == null || !punctuation.contains(prevToken.image))) { + builder.append(" "); + } + builder.append(token.image); + prevToken = token; + token = token.next; + } } return builder; } + public ASTNodeAccess getParent() { + SimpleNode parent = (SimpleNode) node.jjtGetParent(); + while (parent.jjtGetValue() == null) { + parent = (SimpleNode) parent.jjtGetParent(); + } + + return ASTNodeAccess.class.cast(parent.jjtGetValue()); + } + + public T getParent(Class clazz) { + SimpleNode parent = (SimpleNode) node.jjtGetParent(); + while (parent.jjtGetValue() == null || !clazz.isInstance(parent.jjtGetValue())) { + parent = (SimpleNode) parent.jjtGetParent(); + } + + return clazz.cast(parent.jjtGetValue()); + } } diff --git a/src/main/java/net/sf/jsqlparser/parser/AbstractJSqlParser.java b/src/main/java/net/sf/jsqlparser/parser/AbstractJSqlParser.java index 13ebcd781..3c414d852 100644 --- a/src/main/java/net/sf/jsqlparser/parser/AbstractJSqlParser.java +++ b/src/main/java/net/sf/jsqlparser/parser/AbstractJSqlParser.java @@ -21,14 +21,34 @@ public abstract class AbstractJSqlParser

{ protected boolean errorRecovery = false; protected List parseErrors = new ArrayList<>(); + public P withSquareBracketQuotation() { + return withFeature(Feature.allowSquareBracketQuotation, true); + } + public P withSquareBracketQuotation(boolean allowSquareBracketQuotation) { return withFeature(Feature.allowSquareBracketQuotation, allowSquareBracketQuotation); } + public P withAllowComplexParsing() { + return withFeature(Feature.allowComplexParsing, true); + } + public P withAllowComplexParsing(boolean allowComplexParsing) { return withFeature(Feature.allowComplexParsing, allowComplexParsing); } + public P withComplexParsing() { + return withFeature(Feature.allowComplexParsing, true); + } + + public P withComplexParsing(boolean allowComplexParsing) { + return withFeature(Feature.allowComplexParsing, allowComplexParsing); + } + + public P withUnsupportedStatements() { + return withFeature(Feature.allowUnsupportedStatements, true); + } + public P withUnsupportedStatements(boolean allowUnsupportedStatements) { return withFeature(Feature.allowUnsupportedStatements, allowUnsupportedStatements); } @@ -37,6 +57,10 @@ public P withTimeOut(long timeOutMillSeconds) { return withFeature(Feature.timeOut, timeOutMillSeconds); } + public P withBackslashEscapeCharacter() { + return withFeature(Feature.allowBackslashEscapeCharacter, true); + } + public P withBackslashEscapeCharacter(boolean allowBackslashEscapeCharacter) { return withFeature(Feature.allowBackslashEscapeCharacter, allowBackslashEscapeCharacter); } @@ -67,6 +91,16 @@ public void setErrorRecovery(boolean errorRecovery) { this.errorRecovery = errorRecovery; } + public P withErrorRecovery() { + this.errorRecovery = true; + return me(); + } + + public P withErrorRecovery(boolean errorRecovery) { + this.errorRecovery = errorRecovery; + return me(); + } + public List getParseErrors() { return parseErrors; } diff --git a/src/main/java/net/sf/jsqlparser/parser/CCJSqlParserUtil.java b/src/main/java/net/sf/jsqlparser/parser/CCJSqlParserUtil.java index eb6e8b2ce..50d583194 100644 --- a/src/main/java/net/sf/jsqlparser/parser/CCJSqlParserUtil.java +++ b/src/main/java/net/sf/jsqlparser/parser/CCJSqlParserUtil.java @@ -22,6 +22,8 @@ import java.util.function.Consumer; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Expression; @@ -38,12 +40,12 @@ @SuppressWarnings("PMD.CyclomaticComplexity") public final class CCJSqlParserUtil { public final static Logger LOGGER = Logger.getLogger(CCJSqlParserUtil.class.getName()); + public final static int ALLOWED_NESTING_DEPTH = 10; + static { LOGGER.setLevel(Level.OFF); } - public final static int ALLOWED_NESTING_DEPTH = 10; - private CCJSqlParserUtil() {} public static Statement parse(Reader statementReader) throws JSQLParserException { @@ -64,9 +66,9 @@ public static Statement parse(String sql) throws JSQLParserException { /** * Parses an sql statement while allowing via consumer to configure the used parser before. - * + *

* For instance to activate SQLServer bracket quotation on could use: - * + *

* {@code * CCJSqlParserUtil.parse("select * from [mytable]", parser -> parser.withSquareBracketQuotation(true)); * } @@ -525,4 +527,19 @@ public static int getUnbalancedPosition(String text) { return -1; // Return -1 if all brackets and quotes are balanced } + public static String sanitizeSingleSql(String sqlStr) { + final Pattern SQL_DELIMITER_SPLIT = + Pattern.compile("((?:'[^']*+'|[^\\n])*+)"); + final StringBuilder builder = new StringBuilder(); + final Matcher matcher = SQL_DELIMITER_SPLIT.matcher(sqlStr); + while (matcher.find()) { + for (int i = 1; i <= matcher.groupCount(); i++) { + if (!matcher.group(i).isEmpty()) { + builder.append("\n").append(matcher.group(i)); + } + } + } + return builder.toString(); + } + } diff --git a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java index 6aa5686c9..28acdd793 100644 --- a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java +++ b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java @@ -64,6 +64,7 @@ public class ParserKeywordsUtils { {"DOUBLE", RESTRICTED_ALIAS}, {"ELSE", RESTRICTED_JSQLPARSER}, {"EXCEPT", RESTRICTED_SQL2016}, + {"EXCLUDES", RESTRICTED_JSQLPARSER}, {"EXISTS", RESTRICTED_SQL2016}, {"FETCH", RESTRICTED_SQL2016}, {"FINAL", RESTRICTED_JSQLPARSER}, @@ -82,6 +83,7 @@ public class ParserKeywordsUtils { {"IGNORE", RESTRICTED_ALIAS}, {"ILIKE", RESTRICTED_SQL2016}, {"IN", RESTRICTED_SQL2016}, + {"INCLUDES", RESTRICTED_JSQLPARSER}, {"INNER", RESTRICTED_SQL2016}, {"INTERSECT", RESTRICTED_SQL2016}, {"INTERVAL", RESTRICTED_SQL2016}, @@ -109,8 +111,6 @@ public class ParserKeywordsUtils { {"PIVOT", RESTRICTED_JSQLPARSER}, {"PROCEDURE", RESTRICTED_ALIAS}, {"PUBLIC", RESTRICTED_ALIAS}, - {"RECURSIVE", RESTRICTED_SQL2016}, - {"REGEXP", RESTRICTED_SQL2016}, {"RETURNING", RESTRICTED_JSQLPARSER}, {"RIGHT", RESTRICTED_SQL2016}, {"SAMPLE", RESTRICTED_ALIAS}, @@ -193,7 +193,7 @@ public static List getReservedKeywords(int restriction) { */ public static void main(String[] args) throws Exception { if (args.length < 2) { - throw new IllegalArgumentException("No filename provided as parameters ARGS[0]"); + throw new IllegalArgumentException("No filename provided aS context ARGS[0]"); } File grammarFile = new File(args[0]); @@ -215,9 +215,9 @@ public static void main(String[] args) throws Exception { public static TreeSet getAllKeywordsUsingRegex(File file) throws IOException { Pattern tokenBlockPattern = Pattern.compile( - "TOKEN\\s*:\\s*(?:/\\*.*\\*/*)(?:\\r?\\n|\\r)\\{(?:[^\\}\\{]+|\\{(?:[^\\}\\{]+|\\{[^\\}\\{]*\\})*\\})*\\}", + "TOKEN\\s*:\\s*/\\*.*\\*/*(?:\\r?\\n|\\r)\\{(?:[^}{]+|\\{(?:[^}{]+|\\{[^}{]*})*})*}", Pattern.MULTILINE); - Pattern tokenStringValuePattern = Pattern.compile("\\\"(\\w{2,})\\\"", Pattern.MULTILINE); + Pattern tokenStringValuePattern = Pattern.compile("\"(\\w{2,})\"", Pattern.MULTILINE); TreeSet allKeywords = new TreeSet<>(); @@ -257,7 +257,7 @@ public static void buildGrammarForRelObjectNameWithoutValue(File file) throws Ex + "{ Token tk = null; }\n" + "{\n" // @todo: find a way to avoid those hardcoded compound tokens - + " ( tk= | tk= | tk= | tk= | tk= | tk= | tk= \n" + + " ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= \n" + " "); for (String keyword : allKeywords) { diff --git a/src/main/java/net/sf/jsqlparser/parser/SimpleCharStream.java b/src/main/java/net/sf/jsqlparser/parser/SimpleCharStream.java index 2b011e1d3..b96578e01 100644 --- a/src/main/java/net/sf/jsqlparser/parser/SimpleCharStream.java +++ b/src/main/java/net/sf/jsqlparser/parser/SimpleCharStream.java @@ -19,42 +19,86 @@ public class SimpleCharStream { */ @SuppressWarnings("checkstyle:constantname") public static final boolean staticFlag = false; - int bufsize; - int available; - int tokenBegin; /** * Position in buffer. */ public int bufpos = -1; protected int bufline[]; protected int bufcolumn[]; - protected int column = 0; protected int line = 1; - protected boolean prevCharIsCR = false; protected boolean prevCharIsLF = false; - protected Provider inputStream; - private boolean isStringProvider; - protected char[] buffer; protected int maxNextCharInd = 0; protected int inBuf = 0; protected int tabSize = 1; protected boolean trackLineColumn = true; - protected int totalCharsRead = 0; protected int absoluteTokenBegin = 0; + int bufsize; + int available; + int tokenBegin; + private boolean isStringProvider; - public void setTabSize(int i) { - tabSize = i; + /** + * Constructor + * + * @param dstream + * @param startline + * @param startcolumn + * @param buffersize + */ + public SimpleCharStream(Provider dstream, int startline, + int startcolumn, int buffersize) { + inputStream = dstream; + isStringProvider = dstream instanceof StringProvider; + line = startline; + column = startcolumn - 1; + + if (isStringProvider) { + int bs = ((StringProvider) inputStream)._string.length(); + available = bufsize = bs; + bufline = new int[bs]; + bufcolumn = new int[bs]; + } else { + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + } + } + + /** + * Constructor + * + * @param dstream + * @param startline + * @param startcolumn + */ + public SimpleCharStream(Provider dstream, int startline, + int startcolumn) { + this(dstream, startline, startcolumn, 4096); + } + + /** + * Constructor + * + * @param dstream + */ + public SimpleCharStream(Provider dstream) { + this(dstream, 1, 1, 4096); } public int getTabSize() { return tabSize; } + public void setTabSize(int i) { + tabSize = i; + } + public final int getAbsoluteTokenBegin() { return absoluteTokenBegin; } @@ -129,7 +173,8 @@ protected void FillBuff() throws IOException { } maxNextCharInd = i; } else { - if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1) { + if ((i = inputStream.read(buffer, maxNextCharInd, + available - maxNextCharInd)) == -1) { inputStream.close(); throw new IOException(); } else { @@ -149,6 +194,7 @@ protected void FillBuff() throws IOException { /** * Start. + * * @return the character read * @throws IOException */ @@ -204,6 +250,7 @@ private char readChar(int pos) { /** * Read a character. + * * @return the character read * @throws IOException */ @@ -231,7 +278,6 @@ public char readChar() throws IOException { return c; } - /** * @return the column * @deprecated @see #getEndColumn @@ -241,7 +287,6 @@ public int getColumn() { return bufcolumn[bufpos]; } - /** * @return the line * @deprecated @see #getEndLine @@ -281,6 +326,7 @@ public int getBeginLine() { /** * Backup a number of characters. + * * @param amount */ public void backup(int amount) { @@ -292,54 +338,9 @@ public void backup(int amount) { } } - /** - * Constructor - * @param dstream - * @param startline - * @param startcolumn - * @param buffersize - */ - public SimpleCharStream(Provider dstream, int startline, - int startcolumn, int buffersize) { - inputStream = dstream; - isStringProvider = dstream instanceof StringProvider; - line = startline; - column = startcolumn - 1; - - if (isStringProvider) { - int bs = ((StringProvider) inputStream)._string.length(); - available = bufsize = bs; - bufline = new int[bs]; - bufcolumn = new int[bs]; - } else { - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - } - } - - /** - * Constructor - * @param dstream - * @param startline - * @param startcolumn - */ - public SimpleCharStream(Provider dstream, int startline, - int startcolumn) { - this(dstream, startline, startcolumn, 4096); - } - - /** - * Constructor - * @param dstream - */ - public SimpleCharStream(Provider dstream) { - this(dstream, 1, 1, 4096); - } - /** * Reinitialise. + * * @param dstream * @param startline * @param startcolumn @@ -371,6 +372,7 @@ public void ReInit(Provider dstream, int startline, /** * Reinitialise. + * * @param dstream * @param startline * @param startcolumn @@ -380,10 +382,11 @@ public void ReInit(Provider dstream, int startline, ReInit(dstream, startline, startcolumn, 4096); } - /** - * Reinitialise. - * @param dstream - */ + /** + * Reinitialise. + * + * @param dstream + */ public void ReInit(Provider dstream) { ReInit(dstream, 1, 1, 4096); } @@ -420,10 +423,11 @@ public char[] GetSuffix(int len) { if (isStringProvider) { String str = ((StringProvider) inputStream)._string; - if ((bufpos + 1) >= len) { + if ((bufpos + 1) >= len) { str.getChars(bufpos - len + 1, bufpos - len + 1 + len, ret, 0); } else { - str.getChars(bufsize - (len - bufpos - 1), bufsize - (len - bufpos - 1) + len - bufpos - 1, ret, 0); + str.getChars(bufsize - (len - bufpos - 1), + bufsize - (len - bufpos - 1) + len - bufpos - 1, ret, 0); str.getChars(0, bufpos + 1, ret, len - bufpos - 1); } } else { @@ -450,6 +454,7 @@ public void Done() { /** * Method to adjust line and column numbers for the start of a token. + * * @param newLine * @param newCol */ diff --git a/src/main/java/net/sf/jsqlparser/parser/StatementListener.java b/src/main/java/net/sf/jsqlparser/parser/StatementListener.java index d48901f39..3e26a0018 100644 --- a/src/main/java/net/sf/jsqlparser/parser/StatementListener.java +++ b/src/main/java/net/sf/jsqlparser/parser/StatementListener.java @@ -12,7 +12,6 @@ import net.sf.jsqlparser.statement.Statement; /** - * * @author Tobias Warneke (t.warneke@gmx.net) */ public interface StatementListener { diff --git a/src/main/java/net/sf/jsqlparser/parser/feature/Feature.java b/src/main/java/net/sf/jsqlparser/parser/feature/Feature.java index 011919338..244a3887e 100644 --- a/src/main/java/net/sf/jsqlparser/parser/feature/Feature.java +++ b/src/main/java/net/sf/jsqlparser/parser/feature/Feature.java @@ -110,7 +110,7 @@ public enum Feature { limitOffset, /** * "OFFSET offset" - * + * * @see Offset */ offset, @@ -127,7 +127,7 @@ public enum Feature { fetch, /** * "FETCH FIRST row_count (ROW | ROWS) ONLY" - * + * * @see Fetch#isFetchParamFirst() */ fetchFirst, @@ -465,7 +465,6 @@ public enum Feature { executeUsing, /** * SQL "REPLACE" statement is allowed - * */ @Deprecated replace, @@ -787,7 +786,8 @@ public enum Feature { /** * allows Backslash '\' as Escape Character */ - allowBackslashEscapeCharacter(false),; + allowBackslashEscapeCharacter(false), + ; private final Object value; private final boolean configurable; diff --git a/src/main/java/net/sf/jsqlparser/parser/feature/FeatureConfiguration.java b/src/main/java/net/sf/jsqlparser/parser/feature/FeatureConfiguration.java index dc72652ba..da5ddd2b0 100644 --- a/src/main/java/net/sf/jsqlparser/parser/feature/FeatureConfiguration.java +++ b/src/main/java/net/sf/jsqlparser/parser/feature/FeatureConfiguration.java @@ -24,7 +24,7 @@ public class FeatureConfiguration { public FeatureConfiguration() { // set default-value for all switchable features EnumSet.allOf(Feature.class).stream().filter(Feature::isConfigurable) - .forEach(f -> setValue(f, f.getDefaultValue())); + .forEach(f -> setValue(f, f.getDefaultValue())); } /** @@ -46,8 +46,7 @@ public FeatureConfiguration setValue(Feature feature, Object value) { /** * @param feature * @return the configured feature value - can be null - * @throws IllegalStateException - if given {@link Feature#isConfigurable()} == - * false + * @throws IllegalStateException - if given {@link Feature#isConfigurable()} == false */ public Object getValue(Feature feature) { if (feature.isConfigurable()) { diff --git a/src/main/java/net/sf/jsqlparser/parser/feature/FeatureSet.java b/src/main/java/net/sf/jsqlparser/parser/feature/FeatureSet.java index 7ebefec9e..551e0c575 100644 --- a/src/main/java/net/sf/jsqlparser/parser/feature/FeatureSet.java +++ b/src/main/java/net/sf/jsqlparser/parser/feature/FeatureSet.java @@ -12,6 +12,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; + import net.sf.jsqlparser.util.validation.feature.FeaturesAllowed; public interface FeatureSet { @@ -19,8 +20,8 @@ public interface FeatureSet { Set getFeatures(); /** - * @return true if the feature is identical to one of the features - * contained in this set, false otherwise + * @return true if the feature is identical to one of the features contained in + * this set, false otherwise */ default boolean contains(Feature feature) { return getFeatures().contains(feature); @@ -35,8 +36,7 @@ default Set getFeaturesClone() { /** * @param features - * @return all features within this feature set which are not contained in given - * set + * @return all features within this feature set which are not contained in given set */ default Set getNotContained(Collection features) { Set f = getFeaturesClone(); @@ -46,8 +46,7 @@ default Set getNotContained(Collection features) { /** * @param features - * @return all features within this feature set which are contained in given - * set too. + * @return all features within this feature set which are contained in given set too. */ default Set retainAll(Collection features) { Set f = getFeaturesClone(); diff --git a/src/main/java/net/sf/jsqlparser/schema/Column.java b/src/main/java/net/sf/jsqlparser/schema/Column.java index 3f7721ca3..b14c1d03f 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Column.java +++ b/src/main/java/net/sf/jsqlparser/schema/Column.java @@ -9,7 +9,10 @@ */ package net.sf.jsqlparser.schema; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; + import net.sf.jsqlparser.expression.ArrayConstructor; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; @@ -24,6 +27,7 @@ public class Column extends ASTNodeAccessImpl implements Expression, MultiPartNa private String columnName; private String commentText; private ArrayConstructor arrayConstructor; + private String tableDelimiter = "."; public Column() {} @@ -33,8 +37,16 @@ public Column(Table table, String columnName) { } public Column(List nameParts) { - this(nameParts.size() > 1 ? new Table(nameParts.subList(0, nameParts.size() - 1)) : null, + this(nameParts, nameParts.size() > 1 ? Collections.nCopies(nameParts.size() - 1, ".") + : new ArrayList<>()); + } + + public Column(List nameParts, List delimiters) { + this( + nameParts.size() > 1 ? new Table(nameParts.subList(0, nameParts.size() - 1), + delimiters.subList(0, delimiters.size() - 1)) : null, nameParts.get(nameParts.size() - 1)); + setTableDelimiter(delimiters.isEmpty() ? "." : delimiters.get(delimiters.size() - 1)); } public Column(String columnName) { @@ -92,6 +104,14 @@ public void setColumnName(String string) { columnName = string; } + public String getTableDelimiter() { + return tableDelimiter; + } + + public void setTableDelimiter(String tableDelimiter) { + this.tableDelimiter = tableDelimiter; + } + @Override public String getFullyQualifiedName() { return getFullyQualifiedName(false); @@ -108,7 +128,7 @@ public String getFullyQualifiedName(boolean aliases) { } } if (fqn.length() > 0) { - fqn.append('.'); + fqn.append(tableDelimiter); } if (columnName != null) { fqn.append(columnName); @@ -133,8 +153,8 @@ public String getName(boolean aliases) { } @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } @Override @@ -157,11 +177,16 @@ public Column withCommentText(String commentText) { return this; } - public void setCommentText(String commentText) { - this.commentText = commentText; + public Column withTableDelimiter(String delimiter) { + this.setTableDelimiter(delimiter); + return this; } public String getCommentText() { return commentText; } + + public void setCommentText(String commentText) { + this.commentText = commentText; + } } diff --git a/src/main/java/net/sf/jsqlparser/schema/Sequence.java b/src/main/java/net/sf/jsqlparser/schema/Sequence.java index 0997eefb8..d58f04ab7 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Sequence.java +++ b/src/main/java/net/sf/jsqlparser/schema/Sequence.java @@ -37,14 +37,14 @@ public Sequence(List partItems) { Collections.reverse(this.partItems); } - public void setParameters(List parameters) { - this.parameters = parameters; - } - public List getParameters() { return parameters; } + public void setParameters(List parameters) { + this.parameters = parameters; + } + public Database getDatabase() { return new Database(getIndex(DATABASE_IDX)); } diff --git a/src/main/java/net/sf/jsqlparser/schema/Server.java b/src/main/java/net/sf/jsqlparser/schema/Server.java index 3dca6cd2c..d04c5c69b 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Server.java +++ b/src/main/java/net/sf/jsqlparser/schema/Server.java @@ -13,8 +13,8 @@ public final class Server implements MultiPartName { - public static final Pattern SERVER_PATTERN = Pattern. - compile("\\[([^\\]]+?)(?:\\\\([^\\]]+))?\\]"); + public static final Pattern SERVER_PATTERN = + Pattern.compile("\\[([^\\]]+?)(?:\\\\([^\\]]+))?\\]"); private String serverName; @@ -57,8 +57,8 @@ public void setInstanceName(String instanceName) { @Override public String getFullyQualifiedName() { - if (serverName != null && !serverName.isEmpty() && instanceName != null && !instanceName. - isEmpty()) { + if (serverName != null && !serverName.isEmpty() && instanceName != null + && !instanceName.isEmpty()) { return String.format("[%s\\%s]", serverName, instanceName); } else if (serverName != null && !serverName.isEmpty()) { return String.format("[%s]", serverName); diff --git a/src/main/java/net/sf/jsqlparser/schema/Synonym.java b/src/main/java/net/sf/jsqlparser/schema/Synonym.java index b2b958302..ae938d357 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Synonym.java +++ b/src/main/java/net/sf/jsqlparser/schema/Synonym.java @@ -23,8 +23,7 @@ public class Synonym extends ASTNodeAccessImpl implements MultiPartName { private static final int SERVER_IDX = 3; private List partItems = new ArrayList<>(); - public Synonym() { - } + public Synonym() {} public Synonym(List partItems) { this.partItems = new ArrayList<>(partItems); diff --git a/src/main/java/net/sf/jsqlparser/schema/Table.java b/src/main/java/net/sf/jsqlparser/schema/Table.java index 744010ca4..dd9f5a6b2 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Table.java +++ b/src/main/java/net/sf/jsqlparser/schema/Table.java @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; + import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.MySQLIndexHint; import net.sf.jsqlparser.expression.SQLServerHints; @@ -41,6 +42,8 @@ public class Table extends ASTNodeAccessImpl implements FromItem, MultiPartName private List partItems = new ArrayList<>(); + private List partDelimiters = new ArrayList<>(); + private Alias alias; private SampleClause sampleClause; @@ -70,18 +73,34 @@ public Table(Database database, String schemaName, String name) { setDatabase(database); } + public Table(String catalogName, String schemaName, String tableName) { + setName(tableName); + setSchemaName(schemaName); + setDatabase(new Database(catalogName)); + } + public Table(List partItems) { this.partItems = new ArrayList<>(partItems); Collections.reverse(this.partItems); } - public Database getDatabase() { - return new Database(getIndex(DATABASE_IDX)); + public Table(List partItems, List partDelimiters) { + if (partDelimiters.size() != partItems.size() - 1) { + throw new IllegalArgumentException( + "the length of the delimiters list must be 1 less than nameParts"); + } + this.partItems = new ArrayList<>(partItems); + this.partDelimiters = new ArrayList<>(partDelimiters); + Collections.reverse(this.partItems); + Collections.reverse(this.partDelimiters); } - public Table withDatabase(Database database) { - setDatabase(database); - return this; + public String getCatalogName() { + return getIndex(DATABASE_IDX); + } + + public Database getDatabase() { + return new Database(getIndex(DATABASE_IDX)); } public void setDatabase(Database database) { @@ -91,19 +110,24 @@ public void setDatabase(Database database) { } } + public Table withDatabase(Database database) { + setDatabase(database); + return this; + } + public String getSchemaName() { return getIndex(SCHEMA_IDX); } + public void setSchemaName(String schemaName) { + setIndex(SCHEMA_IDX, schemaName); + } + public Table withSchemaName(String schemaName) { setSchemaName(schemaName); return this; } - public void setSchemaName(String schemaName) { - setIndex(SCHEMA_IDX, schemaName); - } - public String getName() { String name = getIndex(NAME_IDX); if (name != null && name.contains("@")) { @@ -115,11 +139,15 @@ public String getName() { return name; } + public void setName(String name) { + setIndex(NAME_IDX, name); + } + public String getDBLinkName() { String name = getIndex(NAME_IDX); if (name != null && name.contains("@")) { int pos = name.lastIndexOf('@'); - if (pos > 0 && name.length() > 1) { + if (pos > 0) { name = name.substring(pos + 1); } } @@ -131,10 +159,6 @@ public Table withName(String name) { return this; } - public void setName(String name) { - setIndex(NAME_IDX, name); - } - @Override public Alias getAlias() { return alias; @@ -177,7 +201,7 @@ public String getFullyQualifiedName() { } fqn.append(part); if (i != 0) { - fqn.append("."); + fqn.append(partDelimiters.isEmpty() ? "." : partDelimiters.get(i - 1)); } } @@ -185,12 +209,12 @@ public String getFullyQualifiedName() { } @Override - public void accept(FromItemVisitor fromItemVisitor) { - fromItemVisitor.visit(this); + public T accept(FromItemVisitor fromItemVisitor, S context) { + return fromItemVisitor.visit(this, context); } - public void accept(IntoTableVisitor intoTableVisitor) { - intoTableVisitor.visit(this); + public T accept(IntoTableVisitor intoTableVisitor, S context) { + return intoTableVisitor.visit(this, context); } @Override @@ -299,4 +323,8 @@ public Table withSqlServerHints(SQLServerHints sqlServerHints) { public List getNameParts() { return partItems; } + + public List getNamePartDelimiters() { + return partDelimiters; + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/Block.java b/src/main/java/net/sf/jsqlparser/statement/Block.java index cbbbb3c87..83b9a2347 100644 --- a/src/main/java/net/sf/jsqlparser/statement/Block.java +++ b/src/main/java/net/sf/jsqlparser/statement/Block.java @@ -31,8 +31,8 @@ public void setSemicolonAfterEnd(boolean hasSemicolonAfterEnd) { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public StringBuilder appendTo(StringBuilder builder) { diff --git a/src/main/java/net/sf/jsqlparser/statement/Commit.java b/src/main/java/net/sf/jsqlparser/statement/Commit.java index f33a36ae1..7ce465053 100644 --- a/src/main/java/net/sf/jsqlparser/statement/Commit.java +++ b/src/main/java/net/sf/jsqlparser/statement/Commit.java @@ -11,10 +11,10 @@ public class Commit implements Statement { @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } - + @Override public String toString() { return "COMMIT"; diff --git a/src/main/java/net/sf/jsqlparser/statement/CreateFunctionalStatement.java b/src/main/java/net/sf/jsqlparser/statement/CreateFunctionalStatement.java index 6a6e3c1d2..536a2b68f 100644 --- a/src/main/java/net/sf/jsqlparser/statement/CreateFunctionalStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/CreateFunctionalStatement.java @@ -32,17 +32,14 @@ protected CreateFunctionalStatement(String kind) { protected CreateFunctionalStatement(String kind, List functionDeclarationParts) { this(false, kind, functionDeclarationParts); } - - protected CreateFunctionalStatement(boolean orReplace, String kind, List functionDeclarationParts) { + + protected CreateFunctionalStatement(boolean orReplace, String kind, + List functionDeclarationParts) { this.orReplace = orReplace; this.kind = kind; this.functionDeclarationParts = functionDeclarationParts; } - public void setFunctionDeclarationParts(List functionDeclarationParts) { - this.functionDeclarationParts = functionDeclarationParts; - } - /** * @return the declaration parts after {@code CREATE FUNCTION|PROCEDURE} */ @@ -50,20 +47,23 @@ public List getFunctionDeclarationParts() { return functionDeclarationParts; } + public void setFunctionDeclarationParts(List functionDeclarationParts) { + this.functionDeclarationParts = functionDeclarationParts; + } + /** * @return the kind of functional statement */ public String getKind() { return kind; } - + public void setOrReplace(boolean orReplace) { this.orReplace = orReplace; } /** - * @return a whitespace appended String with the declaration parts with some - * minimal formatting. + * @return a whitespace appended String with the declaration parts with some minimal formatting. */ public String formatDeclaration() { StringBuilder declaration = new StringBuilder(); @@ -85,30 +85,35 @@ public String formatDeclaration() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } @Override public String toString() { - return "CREATE " - + (orReplace?"OR REPLACE ":"") + return "CREATE " + + (orReplace ? "OR REPLACE " : "") + kind + " " + formatDeclaration(); } - public CreateFunctionalStatement withFunctionDeclarationParts(List functionDeclarationParts) { + public CreateFunctionalStatement withFunctionDeclarationParts( + List functionDeclarationParts) { this.setFunctionDeclarationParts(functionDeclarationParts); return this; } - public CreateFunctionalStatement addFunctionDeclarationParts(String... functionDeclarationParts) { - List collection = Optional.ofNullable(getFunctionDeclarationParts()).orElseGet(ArrayList::new); + public CreateFunctionalStatement addFunctionDeclarationParts( + String... functionDeclarationParts) { + List collection = + Optional.ofNullable(getFunctionDeclarationParts()).orElseGet(ArrayList::new); Collections.addAll(collection, functionDeclarationParts); return this.withFunctionDeclarationParts(collection); } - public CreateFunctionalStatement addFunctionDeclarationParts(Collection functionDeclarationParts) { - List collection = Optional.ofNullable(getFunctionDeclarationParts()).orElseGet(ArrayList::new); + public CreateFunctionalStatement addFunctionDeclarationParts( + Collection functionDeclarationParts) { + List collection = + Optional.ofNullable(getFunctionDeclarationParts()).orElseGet(ArrayList::new); collection.addAll(functionDeclarationParts); return this.withFunctionDeclarationParts(collection); } diff --git a/src/main/java/net/sf/jsqlparser/statement/DeclareStatement.java b/src/main/java/net/sf/jsqlparser/statement/DeclareStatement.java index 282220a1a..d015dc561 100644 --- a/src/main/java/net/sf/jsqlparser/statement/DeclareStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/DeclareStatement.java @@ -15,6 +15,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; + import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.UserVariable; import net.sf.jsqlparser.statement.create.table.ColDataType; @@ -28,17 +29,16 @@ public final class DeclareStatement implements Statement { private List typeDefExprList = new ArrayList<>(); private List columnDefinitions = new ArrayList<>(); - public DeclareStatement() { + public DeclareStatement() {} + + public UserVariable getUserVariable() { + return userVariable; } public void setUserVariable(UserVariable userVariable) { this.userVariable = userVariable; } - public UserVariable getUserVariable() { - return userVariable; - } - /** * @return the {@link DeclareType} * @deprecated use {@link #getDeclareType()} @@ -55,30 +55,38 @@ public DeclareType getDeclareType() { return declareType; } + public void setDeclareType(DeclareType declareType) { + this.declareType = declareType; + } + public String getTypeName() { return typeName; } - public void setDeclareType(DeclareType declareType) { - this.declareType = declareType; + public void setTypeName(String typeName) { + this.typeName = typeName; } public void addType(ColDataType colDataType, Expression defaultExpr) { addTypeDefExprList(new TypeDefExpr(colDataType, defaultExpr)); } - public void addType(UserVariable userVariable, ColDataType colDataType, Expression defaultExpr) { + public void addType(UserVariable userVariable, ColDataType colDataType, + Expression defaultExpr) { addTypeDefExprList(new TypeDefExpr(userVariable, colDataType, defaultExpr)); } public DeclareStatement addTypeDefExprList(TypeDefExpr... typeDefExpressions) { - List collection = Optional.ofNullable(getTypeDefExprList()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getTypeDefExprList()).orElseGet(ArrayList::new); Collections.addAll(collection, typeDefExpressions); return this.withTypeDefExprList(collection); } - public DeclareStatement addTypeDefExprList(Collection typeDefExpressions) { - List collection = Optional.ofNullable(getTypeDefExprList()).orElseGet(ArrayList::new); + public DeclareStatement addTypeDefExprList( + Collection typeDefExpressions) { + List collection = + Optional.ofNullable(getTypeDefExprList()).orElseGet(ArrayList::new); collection.addAll(typeDefExpressions); return this.withTypeDefExprList(collection); } @@ -88,32 +96,28 @@ public DeclareStatement withTypeDefExprList(List typeDefExpressions return this; } - public void setTypeDefExprList(List expr) { - this.typeDefExprList = expr; + public List getTypeDefExprList() { + return this.typeDefExprList; } - public List getTypeDefExprList() { - return this.typeDefExprList ; + public void setTypeDefExprList(List expr) { + this.typeDefExprList = expr; } public void addColumnDefinition(ColumnDefinition colDef) { columnDefinitions.add(colDef); } - public void setColumnDefinitions(List columnDefinitions) { - this.columnDefinitions = columnDefinitions; - } - public List getColumnDefinitions() { return columnDefinitions; } - public List getTypeDefinitions() { - return typeDefExprList; + public void setColumnDefinitions(List columnDefinitions) { + this.columnDefinitions = columnDefinitions; } - public void setTypeName(String typeName) { - this.typeName = typeName; + public List getTypeDefinitions() { + return typeDefExprList; } @Override @@ -153,8 +157,8 @@ public String toString() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public DeclareStatement withUserVariable(UserVariable userVariable) { @@ -178,14 +182,17 @@ public DeclareStatement withColumnDefinitions(List columnDefin } public DeclareStatement addColumnDefinitions(ColumnDefinition... statements) { - List collection = Optional.ofNullable(getColumnDefinitions()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getColumnDefinitions()).orElseGet(ArrayList::new); Collections.addAll(collection, statements); return this.withColumnDefinitions(collection); } - public DeclareStatement addColumnDefinitions(Collection columnDefinitions) { - List collection = Optional.ofNullable(getColumnDefinitions()).orElseGet(ArrayList::new); + public DeclareStatement addColumnDefinitions( + Collection columnDefinitions) { + List collection = + Optional.ofNullable(getColumnDefinitions()).orElseGet(ArrayList::new); collection.addAll(columnDefinitions); return this.withColumnDefinitions(collection); } @@ -200,7 +207,8 @@ public TypeDefExpr(ColDataType colDataType, Expression defaultExpr) { this(null, colDataType, defaultExpr); } - public TypeDefExpr(UserVariable userVariable, ColDataType colDataType, Expression defaultExpr) { + public TypeDefExpr(UserVariable userVariable, ColDataType colDataType, + Expression defaultExpr) { this.userVariable = userVariable; this.colDataType = colDataType; this.defaultExpr = defaultExpr; diff --git a/src/main/java/net/sf/jsqlparser/statement/DeclareType.java b/src/main/java/net/sf/jsqlparser/statement/DeclareType.java index c63c686a4..5208a333a 100644 --- a/src/main/java/net/sf/jsqlparser/statement/DeclareType.java +++ b/src/main/java/net/sf/jsqlparser/statement/DeclareType.java @@ -10,7 +10,6 @@ package net.sf.jsqlparser.statement; /** - * * @author tobens */ public enum DeclareType { diff --git a/src/main/java/net/sf/jsqlparser/statement/DescribeStatement.java b/src/main/java/net/sf/jsqlparser/statement/DescribeStatement.java index 8a2ab01d4..10a92764c 100644 --- a/src/main/java/net/sf/jsqlparser/statement/DescribeStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/DescribeStatement.java @@ -38,8 +38,8 @@ public String toString() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public DescribeStatement withTable(Table table) { diff --git a/src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java b/src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java index 01e7c2f18..55e5c679e 100644 --- a/src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java @@ -12,6 +12,7 @@ import java.io.Serializable; import java.util.LinkedHashMap; import java.util.stream.Collectors; + import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.select.Select; @@ -28,6 +29,10 @@ public ExplainStatement() { // empty constructor } + public ExplainStatement(Select select) { + this.select = select; + } + public Table getTable() { return table; } @@ -37,10 +42,6 @@ public ExplainStatement setTable(Table table) { return this; } - public ExplainStatement(Select select) { - this.select = select; - } - public Select getStatement() { return select; } @@ -63,7 +64,7 @@ public void addOption(Option option) { /** * Returns the first option that matches this optionType - * + * * @param optionType the option type to retrieve an Option for * @return an option of that type, or null. In case of duplicate options, the first found option * will be returned. @@ -97,8 +98,8 @@ public String toString() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public enum OptionType { diff --git a/src/main/java/net/sf/jsqlparser/statement/IfElseStatement.java b/src/main/java/net/sf/jsqlparser/statement/IfElseStatement.java index 856aa5501..848c886ab 100644 --- a/src/main/java/net/sf/jsqlparser/statement/IfElseStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/IfElseStatement.java @@ -11,77 +11,78 @@ package net.sf.jsqlparser.statement; import java.util.Objects; + import net.sf.jsqlparser.expression.Expression; /** - * * @author Andreas Reichel */ public class IfElseStatement implements Statement { - private final Expression condition; - private final Statement ifStatement; - private Statement elseStatement; - private boolean usingSemicolonForIfStatement = false; - private boolean usingSemicolonForElseStatement = false; - - public IfElseStatement(Expression condition, Statement ifStatement) { - this.condition = - Objects.requireNonNull(condition, "The CONDITION of the IfElseStatement must not be null."); - this.ifStatement = Objects.requireNonNull(ifStatement, - "The IF Statement of the IfElseStatement must not be null."); - } - - public Expression getCondition() { - return condition; - } - - public Statement getIfStatement() { - return ifStatement; - } - - public void setElseStatement(Statement elseStatement) { - this.elseStatement = elseStatement; - } - - public Statement getElseStatement() { - return elseStatement; - } - - public void setUsingSemicolonForElseStatement(boolean usingSemicolonForElseStatement) { - this.usingSemicolonForElseStatement = usingSemicolonForElseStatement; - } - - public boolean isUsingSemicolonForElseStatement() { - return usingSemicolonForElseStatement; - } - - public void setUsingSemicolonForIfStatement(boolean usingSemicolonForIfStatement) { - this.usingSemicolonForIfStatement = usingSemicolonForIfStatement; - } - - public boolean isUsingSemicolonForIfStatement() { - return usingSemicolonForIfStatement; - } - - public StringBuilder appendTo(StringBuilder builder) { - builder.append("IF ").append(condition).append(" ").append(ifStatement) - .append(usingSemicolonForIfStatement ? ";" : ""); - - if (elseStatement != null) { - builder.append(" ELSE ").append(elseStatement) - .append(usingSemicolonForElseStatement ? ";" : ""); + private final Expression condition; + private final Statement ifStatement; + private Statement elseStatement; + private boolean usingSemicolonForIfStatement = false; + private boolean usingSemicolonForElseStatement = false; + + public IfElseStatement(Expression condition, Statement ifStatement) { + this.condition = + Objects.requireNonNull(condition, + "The CONDITION of the IfElseStatement must not be null."); + this.ifStatement = Objects.requireNonNull(ifStatement, + "The IF Statement of the IfElseStatement must not be null."); + } + + public Expression getCondition() { + return condition; + } + + public Statement getIfStatement() { + return ifStatement; + } + + public Statement getElseStatement() { + return elseStatement; + } + + public void setElseStatement(Statement elseStatement) { + this.elseStatement = elseStatement; + } + + public boolean isUsingSemicolonForElseStatement() { + return usingSemicolonForElseStatement; + } + + public void setUsingSemicolonForElseStatement(boolean usingSemicolonForElseStatement) { + this.usingSemicolonForElseStatement = usingSemicolonForElseStatement; + } + + public boolean isUsingSemicolonForIfStatement() { + return usingSemicolonForIfStatement; + } + + public void setUsingSemicolonForIfStatement(boolean usingSemicolonForIfStatement) { + this.usingSemicolonForIfStatement = usingSemicolonForIfStatement; + } + + public StringBuilder appendTo(StringBuilder builder) { + builder.append("IF ").append(condition).append(" ").append(ifStatement) + .append(usingSemicolonForIfStatement ? ";" : ""); + + if (elseStatement != null) { + builder.append(" ELSE ").append(elseStatement) + .append(usingSemicolonForElseStatement ? ";" : ""); + } + return builder; + } + + @Override + public String toString() { + return appendTo(new StringBuilder()).toString(); + } + + @Override + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } - return builder; - } - - @Override - public String toString() { - return appendTo(new StringBuilder()).toString(); - } - - @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); - } } diff --git a/src/main/java/net/sf/jsqlparser/statement/PurgeObjectType.java b/src/main/java/net/sf/jsqlparser/statement/PurgeObjectType.java index c9fecb849..4cb2755ba 100644 --- a/src/main/java/net/sf/jsqlparser/statement/PurgeObjectType.java +++ b/src/main/java/net/sf/jsqlparser/statement/PurgeObjectType.java @@ -10,7 +10,6 @@ package net.sf.jsqlparser.statement; /** - * * @author Andreas Reichel */ public enum PurgeObjectType { diff --git a/src/main/java/net/sf/jsqlparser/statement/PurgeStatement.java b/src/main/java/net/sf/jsqlparser/statement/PurgeStatement.java index bfcfff14d..2dca9fbab 100644 --- a/src/main/java/net/sf/jsqlparser/statement/PurgeStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/PurgeStatement.java @@ -11,13 +11,14 @@ package net.sf.jsqlparser.statement; import java.util.Objects; + import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.create.table.Index; /** - * * @author Andreas Reichel - * @see Purge + * @see Purge */ public class PurgeStatement implements Statement { @@ -27,34 +28,38 @@ public class PurgeStatement implements Statement { public PurgeStatement(Table table) { this.purgeObjectType = PurgeObjectType.TABLE; - this.object = Objects.requireNonNull(table, "The TABLE of the PURGE TABLE statement must not be null."); + this.object = Objects.requireNonNull(table, + "The TABLE of the PURGE TABLE statement must not be null."); } - + public PurgeStatement(Index index) { this.purgeObjectType = PurgeObjectType.INDEX; - this.object = Objects.requireNonNull(index, "The INDEX of the PURGE INDEX statement must not be null."); + this.object = Objects.requireNonNull(index, + "The INDEX of the PURGE INDEX statement must not be null."); } - + public PurgeStatement(PurgeObjectType purgeObjectType) { this.purgeObjectType = purgeObjectType; this.object = null; } - + public PurgeStatement(PurgeObjectType purgeObjectType, String tableSpaceName, String userName) { this.purgeObjectType = purgeObjectType; - this.object = Objects.requireNonNull(tableSpaceName, "The TABLESPACE NAME of the PURGE TABLESPACE statement must not be null."); + this.object = Objects.requireNonNull(tableSpaceName, + "The TABLESPACE NAME of the PURGE TABLESPACE statement must not be null."); this.userName = userName; } - - @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + + @Override + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } - - @SuppressWarnings({"PMD.MissingBreakInSwitch", "PMD.SwitchStmtsShouldHaveDefault", "PMD.CyclomaticComplexity"}) + + @SuppressWarnings({"PMD.MissingBreakInSwitch", "PMD.SwitchStmtsShouldHaveDefault", + "PMD.CyclomaticComplexity"}) public StringBuilder appendTo(StringBuilder builder) { builder.append("PURGE "); - + switch (purgeObjectType) { case RECYCLEBIN: case DBA_RECYCLEBIN: @@ -63,16 +68,16 @@ public StringBuilder appendTo(StringBuilder builder) { case TABLE: case INDEX: builder.append(purgeObjectType); - if (object!=null) { + if (object != null) { builder.append(" ").append(object); } break; case TABLESPACE: builder.append(purgeObjectType); - if (object!=null) { + if (object != null) { builder.append(" ").append(object); } - if (userName!=null && userName.length()>0) { + if (userName != null && userName.length() > 0) { builder.append(" USER ").append(userName); } break; diff --git a/src/main/java/net/sf/jsqlparser/statement/ReferentialAction.java b/src/main/java/net/sf/jsqlparser/statement/ReferentialAction.java index 16dc9427d..5691aed25 100644 --- a/src/main/java/net/sf/jsqlparser/statement/ReferentialAction.java +++ b/src/main/java/net/sf/jsqlparser/statement/ReferentialAction.java @@ -62,9 +62,8 @@ public int hashCode() { @Override public String toString() { - return new StringBuilder(" ON ").append(getType().name()).append(" ") - .append(getAction().getAction()) - .toString(); + return " ON " + getType().name() + " " + + getAction().getAction(); } @Override diff --git a/src/main/java/net/sf/jsqlparser/statement/ResetStatement.java b/src/main/java/net/sf/jsqlparser/statement/ResetStatement.java index 956ffd027..dc769a9e8 100644 --- a/src/main/java/net/sf/jsqlparser/statement/ResetStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/ResetStatement.java @@ -25,7 +25,7 @@ public ResetStatement(String name) { public void add(String name) { this.name = name; } - + public String getName() { return name; } @@ -41,8 +41,8 @@ public String toString() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } } diff --git a/src/main/java/net/sf/jsqlparser/statement/ReturningClause.java b/src/main/java/net/sf/jsqlparser/statement/ReturningClause.java index 3c7525b46..c84a07903 100644 --- a/src/main/java/net/sf/jsqlparser/statement/ReturningClause.java +++ b/src/main/java/net/sf/jsqlparser/statement/ReturningClause.java @@ -21,20 +21,11 @@ */ public class ReturningClause extends ArrayList> { - enum Keyword { - RETURN, RETURNING; - - public static Keyword from(String keyword) { - return Enum.valueOf(Keyword.class, keyword.toUpperCase()); - } - } - - private Keyword keyword; - /** * List of output targets like Table or UserVariable */ private final List dataItems; + private Keyword keyword; public ReturningClause(Keyword keyword, List> selectItems, List dataItems) { @@ -78,7 +69,7 @@ public StringBuilder appendTo(StringBuilder builder) { builder.append(get(i)); } - if (dataItems != null && dataItems.size() > 0) { + if (dataItems != null && !dataItems.isEmpty()) { builder.append(" INTO "); for (int i = 0; i < dataItems.size(); i++) { if (i > 0) { @@ -94,4 +85,12 @@ public StringBuilder appendTo(StringBuilder builder) { public String toString() { return appendTo(new StringBuilder()).toString(); } + + public enum Keyword { + RETURN, RETURNING; + + public static Keyword from(String keyword) { + return Enum.valueOf(Keyword.class, keyword.toUpperCase()); + } + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/RollbackStatement.java b/src/main/java/net/sf/jsqlparser/statement/RollbackStatement.java index ef566bc03..0c6f66769 100644 --- a/src/main/java/net/sf/jsqlparser/statement/RollbackStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/RollbackStatement.java @@ -26,87 +26,89 @@ package net.sf.jsqlparser.statement; /** - * * @author are */ public class RollbackStatement implements Statement { - private boolean usingWorkKeyword=false; - private boolean usingSavepointKeyword=false; - private String savepointName=null; - private String forceDistributedTransactionIdentifier=null; + private boolean usingWorkKeyword = false; + private boolean usingSavepointKeyword = false; + private String savepointName = null; + private String forceDistributedTransactionIdentifier = null; public boolean isUsingWorkKeyword() { return usingWorkKeyword; } - public RollbackStatement withUsingWorkKeyword(boolean usingWorkKeyword) { + public void setUsingWorkKeyword(boolean usingWorkKeyword) { this.usingWorkKeyword = usingWorkKeyword; - return this; } - - public void setUsingWorkKeyword(boolean usingWorkKeyword) { + + public RollbackStatement withUsingWorkKeyword(boolean usingWorkKeyword) { this.usingWorkKeyword = usingWorkKeyword; + return this; } public boolean isUsingSavepointKeyword() { return usingSavepointKeyword; } - - public RollbackStatement withUsingSavepointKeyword(boolean usingSavepointKeyword) { + + public void setUsingSavepointKeyword(boolean usingSavepointKeyword) { this.usingSavepointKeyword = usingSavepointKeyword; - return this; } - public void setUsingSavepointKeyword(boolean usingSavepointKeyword) { + public RollbackStatement withUsingSavepointKeyword(boolean usingSavepointKeyword) { this.usingSavepointKeyword = usingSavepointKeyword; + return this; } public String getSavepointName() { return savepointName; } - - public RollbackStatement withSavepointName(String savepointName) { + + public void setSavepointName(String savepointName) { this.savepointName = savepointName; - return this; } - public void setSavepointName(String savepointName) { + public RollbackStatement withSavepointName(String savepointName) { this.savepointName = savepointName; + return this; } public String getForceDistributedTransactionIdentifier() { return forceDistributedTransactionIdentifier; } - - public RollbackStatement withForceDistributedTransactionIdentifier(String forceDistributedTransactionIdentifier) { + + public void setForceDistributedTransactionIdentifier( + String forceDistributedTransactionIdentifier) { this.forceDistributedTransactionIdentifier = forceDistributedTransactionIdentifier; - return this; } - public void setForceDistributedTransactionIdentifier(String forceDistributedTransactionIdentifier) { + public RollbackStatement withForceDistributedTransactionIdentifier( + String forceDistributedTransactionIdentifier) { this.forceDistributedTransactionIdentifier = forceDistributedTransactionIdentifier; + return this; } @Override public String toString() { - return "ROLLBACK " - + ( usingWorkKeyword - ? "WORK " - : "" ) - + (savepointName!=null && savepointName.trim().length()!=0 - ? "TO " + (usingSavepointKeyword - ? "SAVEPOINT " - : "") + savepointName - : forceDistributedTransactionIdentifier!=null && forceDistributedTransactionIdentifier.trim().length()!=0 - ? "FORCE " + forceDistributedTransactionIdentifier - : "" - + return "ROLLBACK " + + (usingWorkKeyword + ? "WORK " + : "") + + (savepointName != null && !savepointName.trim().isEmpty() + ? "TO " + (usingSavepointKeyword + ? "SAVEPOINT " + : "") + savepointName + : forceDistributedTransactionIdentifier != null + && !forceDistributedTransactionIdentifier.trim().isEmpty() + ? "FORCE " + forceDistributedTransactionIdentifier + : "" + ); } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } } diff --git a/src/main/java/net/sf/jsqlparser/statement/SavepointStatement.java b/src/main/java/net/sf/jsqlparser/statement/SavepointStatement.java index fd08d2999..390c7f438 100644 --- a/src/main/java/net/sf/jsqlparser/statement/SavepointStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/SavepointStatement.java @@ -13,22 +13,23 @@ import java.util.Objects; /** - * * @author Andreas Reichel */ public class SavepointStatement implements Statement { private String savepointName; + public SavepointStatement(String savepointName) { + this.savepointName = + Objects.requireNonNull(savepointName, "The Savepoint Name must not be NULL."); + } + public String getSavepointName() { return savepointName; } public void setSavepointName(String savepointName) { - this.savepointName = Objects.requireNonNull(savepointName, "The Savepoint Name must not be NULL."); - } - - public SavepointStatement(String savepointName) { - this.savepointName = Objects.requireNonNull(savepointName, "The Savepoint Name must not be NULL."); + this.savepointName = + Objects.requireNonNull(savepointName, "The Savepoint Name must not be NULL."); } @Override @@ -37,7 +38,7 @@ public String toString() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } } diff --git a/src/main/java/net/sf/jsqlparser/statement/SetStatement.java b/src/main/java/net/sf/jsqlparser/statement/SetStatement.java index f276f4956..16878f773 100644 --- a/src/main/java/net/sf/jsqlparser/statement/SetStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/SetStatement.java @@ -21,8 +21,8 @@ public final class SetStatement implements Statement { - private String effectParameter; private final List values = new ArrayList<>(); + private String effectParameter; public SetStatement() { // empty constructor @@ -52,6 +52,10 @@ public boolean isUseEqual() { return isUseEqual(0); } + public SetStatement setUseEqual(boolean useEqual) { + return setUseEqual(0, useEqual); + } + public SetStatement withUseEqual(int idx, boolean useEqual) { this.setUseEqual(idx, useEqual); return this; @@ -67,23 +71,18 @@ public SetStatement withUseEqual(boolean useEqual) { return this; } - public SetStatement setUseEqual(boolean useEqual) { - return setUseEqual(0, useEqual); - } - - public Object getName() { return getName(0); } - public Object getName(int idx) { - return values.get(idx).name; - } - public void setName(String name) { setName(0, name); } + public Object getName(int idx) { + return values.get(idx).name; + } + public void setName(int idx, String name) { values.get(idx).name = name; } @@ -96,14 +95,14 @@ public List getExpressions() { return getExpressions(0); } - public void setExpressions(int idx, ExpressionList expressions) { - values.get(idx).expressions = expressions; - } - public void setExpressions(ExpressionList expressions) { setExpressions(0, expressions); } + public void setExpressions(int idx, ExpressionList expressions) { + values.get(idx).expressions = expressions; + } + private String toString(NameExpr ne) { return ne.name + (ne.useEqual ? " = " : " ") + PlainSelect.getStringList(ne.expressions, true, false); @@ -146,8 +145,21 @@ public void clear() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); + } + + public String getEffectParameter() { + return effectParameter; + } + + public void setEffectParameter(String effectParameter) { + this.effectParameter = effectParameter; + } + + public SetStatement withEffectParameter(String effectParameter) { + this.effectParameter = effectParameter; + return this; } static class NameExpr implements Serializable { @@ -155,6 +167,12 @@ static class NameExpr implements Serializable { ExpressionList expressions; boolean useEqual; + public NameExpr(Object name, ExpressionList expressions, boolean useEqual) { + this.name = name; + this.expressions = expressions; + this.useEqual = useEqual; + } + public Object getName() { return name; } @@ -178,24 +196,5 @@ public boolean isUseEqual() { public void setUseEqual(boolean useEqual) { this.useEqual = useEqual; } - - public NameExpr(Object name, ExpressionList expressions, boolean useEqual) { - this.name = name; - this.expressions = expressions; - this.useEqual = useEqual; - } - } - - public String getEffectParameter() { - return effectParameter; - } - - public void setEffectParameter(String effectParameter) { - this.effectParameter = effectParameter; - } - - public SetStatement withEffectParameter(String effectParameter) { - this.effectParameter = effectParameter; - return this; } } diff --git a/src/main/java/net/sf/jsqlparser/statement/ShowColumnsStatement.java b/src/main/java/net/sf/jsqlparser/statement/ShowColumnsStatement.java index 8915d81fd..51f1ed26d 100644 --- a/src/main/java/net/sf/jsqlparser/statement/ShowColumnsStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/ShowColumnsStatement.java @@ -35,8 +35,8 @@ public String toString() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public ShowColumnsStatement withTableName(String tableName) { diff --git a/src/main/java/net/sf/jsqlparser/statement/ShowStatement.java b/src/main/java/net/sf/jsqlparser/statement/ShowStatement.java index f6bc84518..c5f1729cc 100644 --- a/src/main/java/net/sf/jsqlparser/statement/ShowStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/ShowStatement.java @@ -35,8 +35,8 @@ public String toString() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public ShowStatement withName(String name) { diff --git a/src/main/java/net/sf/jsqlparser/statement/Statement.java b/src/main/java/net/sf/jsqlparser/statement/Statement.java index fee483c09..380092ab6 100644 --- a/src/main/java/net/sf/jsqlparser/statement/Statement.java +++ b/src/main/java/net/sf/jsqlparser/statement/Statement.java @@ -12,5 +12,9 @@ import net.sf.jsqlparser.Model; public interface Statement extends Model { - void accept(StatementVisitor statementVisitor); + T accept(StatementVisitor statementVisitor, S context); + + default void accept(StatementVisitor statementVisitor) { + accept(statementVisitor, null); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java b/src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java index 46d4e0d96..8625f6576 100644 --- a/src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java +++ b/src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java @@ -37,93 +37,269 @@ import net.sf.jsqlparser.statement.update.Update; import net.sf.jsqlparser.statement.upsert.Upsert; -public interface StatementVisitor { +public interface StatementVisitor { - void visit(Analyze analyze); + T visit(Analyze analyze, S context); - void visit(SavepointStatement savepointStatement); + default void visit(Analyze analyze) { + this.visit(analyze, null); + } - void visit(RollbackStatement rollbackStatement); + T visit(SavepointStatement savepointStatement, S context); - void visit(Comment comment); + default void visit(SavepointStatement savepointStatement) { + this.visit(savepointStatement, null); + } - void visit(Commit commit); + T visit(RollbackStatement rollbackStatement, S context); - void visit(Delete delete); + default void visit(RollbackStatement rollbackStatement) { + this.visit(rollbackStatement, null); + } - void visit(Update update); + T visit(Comment comment, S context); - void visit(Insert insert); + default void visit(Comment comment) { + this.visit(comment, null); + } - void visit(Drop drop); + T visit(Commit commit, S context); - void visit(Truncate truncate); + default void visit(Commit commit) { + this.visit(commit, null); + } - void visit(CreateIndex createIndex); + T visit(Delete delete, S context); - void visit(CreateSchema aThis); + default void visit(Delete delete) { + this.visit(delete, null); + } - void visit(CreateTable createTable); + T visit(Update update, S context); - void visit(CreateView createView); + default void visit(Update update) { + this.visit(update, null); + } - void visit(AlterView alterView); + T visit(Insert insert, S context); - void visit(RefreshMaterializedViewStatement materializedView); + default void visit(Insert insert) { + this.visit(insert, null); + } - void visit(Alter alter); + T visit(Drop drop, S context); - void visit(Statements stmts); + default void visit(Drop drop) { + this.visit(drop, null); + } - void visit(Execute execute); + T visit(Truncate truncate, S context); - void visit(SetStatement set); + default void visit(Truncate truncate) { + this.visit(truncate, null); + } - void visit(ResetStatement reset); + T visit(CreateIndex createIndex, S context); - void visit(ShowColumnsStatement set); + default void visit(CreateIndex createIndex) { + this.visit(createIndex, null); + } - void visit(ShowIndexStatement showIndex); + T visit(CreateSchema createSchema, S context); - void visit(ShowTablesStatement showTables); + default void visit(CreateSchema createSchema) { + this.visit(createSchema, null); + } - void visit(Merge merge); + T visit(CreateTable createTable, S context); - void visit(Select select); + default void visit(CreateTable createTable) { + this.visit(createTable, null); + } - void visit(Upsert upsert); + T visit(CreateView createView, S context); - void visit(UseStatement use); + default void visit(CreateView createView) { + this.visit(createView, null); + } - void visit(Block block); + T visit(AlterView alterView, S context); - void visit(DescribeStatement describe); + default void visit(AlterView alterView) { + this.visit(alterView, null); + } - void visit(ExplainStatement aThis); + T visit(RefreshMaterializedViewStatement materializedView, S context); - void visit(ShowStatement aThis); + default void visit(RefreshMaterializedViewStatement materializedView) { + this.visit(materializedView, null); + } - void visit(DeclareStatement aThis); + T visit(Alter alter, S context); - void visit(Grant grant); + default void visit(Alter alter) { + this.visit(alter, null); + } - void visit(CreateSequence createSequence); + T visit(Statements statements, S context); - void visit(AlterSequence alterSequence); + default void visit(Statements statements) { + this.visit(statements, null); + } - void visit(CreateFunctionalStatement createFunctionalStatement); + T visit(Execute execute, S context); - void visit(CreateSynonym createSynonym); + default void visit(Execute execute) { + this.visit(execute, null); + } - void visit(AlterSession alterSession); + T visit(SetStatement set, S context); - void visit(IfElseStatement aThis); + default void visit(SetStatement set) { + this.visit(set, null); + } - void visit(RenameTableStatement renameTableStatement); + T visit(ResetStatement reset, S context); - void visit(PurgeStatement purgeStatement); + default void visit(ResetStatement reset) { + this.visit(reset, null); + } - void visit(AlterSystemStatement alterSystemStatement); + T visit(ShowColumnsStatement showColumns, S context); - void visit(UnsupportedStatement unsupportedStatement); + default void visit(ShowColumnsStatement showColumns) { + this.visit(showColumns, null); + } + + T visit(ShowIndexStatement showIndex, S context); + + default void visit(ShowIndexStatement showIndex) { + this.visit(showIndex, null); + } + + T visit(ShowTablesStatement showTables, S context); + + default void visit(ShowTablesStatement showTables) { + this.visit(showTables, null); + } + + T visit(Merge merge, S context); + + default void visit(Merge merge) { + this.visit(merge, null); + } + + T visit(Select select, S context); + + default void visit(Select select) { + this.visit(select, null); + } + + T visit(Upsert upsert, S context); + + default void visit(Upsert upsert) { + this.visit(upsert, null); + } + + T visit(UseStatement use, S context); + + default void visit(UseStatement use) { + this.visit(use, null); + } + + T visit(Block block, S context); + + default void visit(Block block) { + this.visit(block, null); + } + + T visit(DescribeStatement describe, S context); + + default void visit(DescribeStatement describe) { + this.visit(describe, null); + } + + T visit(ExplainStatement explainStatement, S context); + + default void visit(ExplainStatement explainStatement) { + this.visit(explainStatement, null); + } + + T visit(ShowStatement showStatement, S context); + + default void visit(ShowStatement showStatement) { + this.visit(showStatement, null); + } + + T visit(DeclareStatement declareStatement, S context); + + default void visit(DeclareStatement declareStatement) { + this.visit(declareStatement, null); + } + + T visit(Grant grant, S context); + + default void visit(Grant grant) { + this.visit(grant, null); + } + + T visit(CreateSequence createSequence, S context); + + default void visit(CreateSequence createSequence) { + this.visit(createSequence, null); + } + + T visit(AlterSequence alterSequence, S context); + + default void visit(AlterSequence alterSequence) { + this.visit(alterSequence, null); + } + + T visit(CreateFunctionalStatement createFunctionalStatement, S context); + + default void visit(CreateFunctionalStatement createFunctionalStatement) { + this.visit(createFunctionalStatement, null); + } + + T visit(CreateSynonym createSynonym, S context); + + default void visit(CreateSynonym createSynonym) { + this.visit(createSynonym, null); + } + + T visit(AlterSession alterSession, S context); + + default void visit(AlterSession alterSession) { + this.visit(alterSession, null); + } + + T visit(IfElseStatement ifElseStatement, S context); + + default void visit(IfElseStatement ifElseStatement) { + this.visit(ifElseStatement, null); + } + + T visit(RenameTableStatement renameTableStatement, S context); + + default void visit(RenameTableStatement renameTableStatement) { + this.visit(renameTableStatement, null); + } + + T visit(PurgeStatement purgeStatement, S context); + + default void visit(PurgeStatement purgeStatement) { + this.visit(purgeStatement, null); + } + + T visit(AlterSystemStatement alterSystemStatement, S context); + + default void visit(AlterSystemStatement alterSystemStatement) { + this.visit(alterSystemStatement, null); + } + + T visit(UnsupportedStatement unsupportedStatement, S context); + + default void visit(UnsupportedStatement unsupportedStatement) { + this.visit(unsupportedStatement, null); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java index 72d2a540a..5ee05b852 100644 --- a/src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java @@ -38,194 +38,253 @@ import net.sf.jsqlparser.statement.upsert.Upsert; @SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) -public class StatementVisitorAdapter implements StatementVisitor { +public class StatementVisitorAdapter implements StatementVisitor { @Override - public void visit(Comment comment) { + public T visit(Comment comment, S context) { + return null; } @Override - public void visit(Commit commit) { + public T visit(Commit commit, S context) { + return null; } @Override - public void visit(Select select) { + public T visit(Select select, S context) { + return null; } @Override - public void visit(Delete delete) { + public T visit(Delete delete, S context) { + return null; } @Override - public void visit(Update update) { + public T visit(Update update, S context) { + return null; } @Override - public void visit(Insert insert) { + public T visit(Insert insert, S context) { + return null; } @Override - public void visit(Drop drop) { + public T visit(Drop drop, S context) { + return null; } @Override - public void visit(Truncate truncate) { + public T visit(Truncate truncate, S context) { + return null; } @Override - public void visit(CreateIndex createIndex) { + public T visit(CreateIndex createIndex, S context) { + return null; } @Override - public void visit(CreateSchema aThis) {} + public T visit(CreateSchema createSchema, S context) { + return null; + } @Override - public void visit(CreateTable createTable) { + public T visit(CreateTable createTable, S context) { + return null; } @Override - public void visit(CreateView createView) { + public T visit(CreateView createView, S context) { + return null; } @Override - public void visit(Alter alter) { + public T visit(Alter alter, S context) { + return null; } @Override - public void visit(Statements stmts) { - for (Statement statement : stmts.getStatements()) { - statement.accept(this); + public T visit(Statements statements, S context) { + for (Statement statement : statements) { + statement.accept(this, context); } + return null; } @Override - public void visit(Execute execute) { + public T visit(Execute execute, S context) { + return null; } @Override - public void visit(SetStatement set) { + public T visit(SetStatement set, S context) { + return null; } @Override - public void visit(ResetStatement reset) { + public T visit(ResetStatement reset, S context) { + return null; } @Override - public void visit(Merge merge) { + public T visit(Merge merge, S context) { + return null; } @Override - public void visit(AlterView alterView) {} + public T visit(AlterView alterView, S context) { + return null; + } @Override - public void visit(Upsert upsert) {} + public T visit(Upsert upsert, S context) { + return null; + } @Override - public void visit(UseStatement use) {} + public T visit(UseStatement use, S context) { + return null; + } @Override - public void visit(Block block) {} + public T visit(Block block, S context) { + return null; + } @Override - public void visit(DescribeStatement describe) {} + public T visit(DescribeStatement describe, S context) { + return null; + } @Override - public void visit(ExplainStatement aThis) {} + public T visit(ExplainStatement explainStatement, S context) { + return null; + } @Override - public void visit(ShowStatement aThis) {} + public T visit(ShowStatement showStatement, S context) { + return null; + } @Override - public void visit(ShowColumnsStatement set) {} + public T visit(ShowColumnsStatement showColumnsStatement, S context) { + return null; + } @Override - public void visit(ShowIndexStatement set) {} + public T visit(ShowIndexStatement showIndexStatement, S context) { + return null; + } @Override - public void visit(ShowTablesStatement showTables) {} + public T visit(ShowTablesStatement showTables, S context) { + return null; + } @Override - public void visit(DeclareStatement aThis) {} + public T visit(DeclareStatement declareStatement, S context) { + return null; + } @Override - public void visit(Grant grant) {} + public T visit(Grant grant, S context) { + return null; + } @Override - public void visit(CreateSequence createSequence) {} + public T visit(CreateSequence createSequence, S context) { + return null; + } @Override - public void visit(AlterSequence alterSequence) {} + public T visit(AlterSequence alterSequence, S context) { + return null; + } @Override - public void visit(CreateFunctionalStatement createFunctionalStatement) {} + public T visit(CreateFunctionalStatement createFunctionalStatement, S context) { + return null; + } @Override - public void visit(CreateSynonym createSynonym) {} + public T visit(CreateSynonym createSynonym, S context) { + return null; + } @Override - public void visit(Analyze analyze) { + public T visit(Analyze analyze, S context) { + return null; } @Override - public void visit(SavepointStatement savepointStatement) { - // @todo: do something usefull here + public T visit(SavepointStatement savepointStatement, S context) { + // @todo: do something usefully here + return null; } @Override - public void visit(RollbackStatement rollbackStatement) { - // @todo: do something usefull here + public T visit(RollbackStatement rollbackStatement, S context) { + // @todo: do something usefully here + return null; } @Override - public void visit(AlterSession alterSession) { - // @todo: do something usefull here + public T visit(AlterSession alterSession, S context) { + // @todo: do something usefully here + return null; } @Override - public void visit(IfElseStatement ifElseStatement) { - ifElseStatement.getIfStatement().accept(this); + public T visit(IfElseStatement ifElseStatement, S context) { + ifElseStatement.getIfStatement().accept(this, context); if (ifElseStatement.getElseStatement() != null) { - ifElseStatement.getElseStatement().accept(this); + ifElseStatement.getElseStatement().accept(this, context); } + return null; } @Override - public void visit(RenameTableStatement renameTableStatement) { - // @todo: do something usefull here + public T visit(RenameTableStatement renameTableStatement, S context) { + return null; } @Override - public void visit(PurgeStatement purgeStatement) { - // @todo: do something usefull here + public T visit(PurgeStatement purgeStatement, S context) { + return null; } @Override - public void visit(AlterSystemStatement alterSystemStatement) {} + public T visit(AlterSystemStatement alterSystemStatement, S context) { + return null; + } @Override - public void visit(UnsupportedStatement unsupportedStatement) { + public T visit(UnsupportedStatement unsupportedStatement, S context) { + return null; } @Override - public void visit(RefreshMaterializedViewStatement materializedView) { - + public T visit(RefreshMaterializedViewStatement materializedView, S context) { + return null; } } diff --git a/src/main/java/net/sf/jsqlparser/statement/Statements.java b/src/main/java/net/sf/jsqlparser/statement/Statements.java index 5f66f2d6f..0c8571c35 100644 --- a/src/main/java/net/sf/jsqlparser/statement/Statements.java +++ b/src/main/java/net/sf/jsqlparser/statement/Statements.java @@ -26,8 +26,8 @@ public void setStatements(List statements) { this.addAll(statements); } - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public E get(Class type, int index) { diff --git a/src/main/java/net/sf/jsqlparser/statement/UnsupportedStatement.java b/src/main/java/net/sf/jsqlparser/statement/UnsupportedStatement.java index 9b47a9e2a..f64a89fac 100644 --- a/src/main/java/net/sf/jsqlparser/statement/UnsupportedStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/UnsupportedStatement.java @@ -15,7 +15,6 @@ import java.util.Objects; /** - * * @author Andreas Reichel */ @@ -35,8 +34,8 @@ public UnsupportedStatement(String upfront, List declarations) { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } @SuppressWarnings({"PMD.MissingBreakInSwitch", "PMD.SwitchStmtsShouldHaveDefault", diff --git a/src/main/java/net/sf/jsqlparser/statement/UseStatement.java b/src/main/java/net/sf/jsqlparser/statement/UseStatement.java index f0a80e4d7..b4b606849 100644 --- a/src/main/java/net/sf/jsqlparser/statement/UseStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/UseStatement.java @@ -49,8 +49,8 @@ public String toString() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public UseStatement withName(String name) { diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/Alter.java b/src/main/java/net/sf/jsqlparser/statement/alter/Alter.java index 0aabfc181..7c00077e2 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/Alter.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/Alter.java @@ -15,6 +15,7 @@ import java.util.Iterator; import java.util.List; import java.util.Optional; + import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; @@ -73,8 +74,8 @@ public void setAlterExpressions(List alterExpressions) { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } @Override diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java index 0a99c97d5..b13e8356a 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java @@ -18,6 +18,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; + import net.sf.jsqlparser.statement.ReferentialAction; import net.sf.jsqlparser.statement.ReferentialAction.Action; import net.sf.jsqlparser.statement.ReferentialAction.Type; @@ -29,18 +30,16 @@ @SuppressWarnings({"PMD.CyclomaticComplexity"}) public class AlterExpression implements Serializable { + private final Set referentialActions = new LinkedHashSet<>(2); private AlterOperation operation; private String optionalSpecifier; private String newTableName; private String columnName; - private String columnOldName; // private ColDataType dataType; - + private String columnOldName; private List colDataTypeList; private List columnDropNotNullList; - private List columnDropDefaultList; - private List pkColumns; private List ukColumns; private String ukName; @@ -48,9 +47,6 @@ public class AlterExpression implements Serializable { private Index oldIndex = null; private String constraintName; private boolean usingIfExists; - - private Set referentialActions = new LinkedHashSet<>(2); - private List fkColumns; private String fkSourceSchema; diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterSession.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterSession.java index 64c25ad94..e7e8308d9 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterSession.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterSession.java @@ -11,15 +11,16 @@ package net.sf.jsqlparser.statement.alter; import java.util.List; + import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; /** - * * @author are - * @see ALTER SESSION + * @see ALTER + * SESSION */ -public class AlterSession implements Statement { +public class AlterSession implements Statement { private AlterSessionOperation operation; private List parameters; @@ -28,6 +29,12 @@ public AlterSession(AlterSessionOperation operation, List parameters) { this.parameters = parameters; } + private static void appendParameters(StringBuilder builder, List parameters) { + for (String s : parameters) { + builder.append(" ").append(s); + } + } + public AlterSessionOperation getOperation() { return operation; } @@ -43,15 +50,9 @@ public List getParameters() { public void setParameters(List parameters) { this.parameters = parameters; } - - private static void appendParamaters(StringBuilder builder, List parameters) { - for (String s: parameters) { - builder.append(" ").append(s); - } - } @Override - @SuppressWarnings({"PMD.ExcessiveMethodLength", "PMD.CyclomaticComplexity"}) + @SuppressWarnings({"PMD.ExcessiveMethodLength", "PMD.CyclomaticComplexity"}) public String toString() { StringBuilder builder = new StringBuilder(); builder.append("ALTER SESSION "); @@ -67,7 +68,7 @@ public String toString() { break; case CLOSE_DATABASE_LINK: builder.append("CLOSE DATABASE LINK "); - appendParamaters(builder, parameters); + appendParameters(builder, parameters); break; case ENABLE_COMMIT_IN_PROCEDURE: builder.append("ENABLE COMMIT IN PROCEDURE"); @@ -81,72 +82,72 @@ public String toString() { case DISABLE_GUARD: builder.append("DISABLE GUARD"); break; - + case ENABLE_PARALLEL_DML: builder.append("ENABLE PARALLEL DML"); - appendParamaters(builder, parameters); + appendParameters(builder, parameters); break; - + case DISABLE_PARALLEL_DML: builder.append("DISABLE PARALLEL DML"); - appendParamaters(builder, parameters); + appendParameters(builder, parameters); break; - + case FORCE_PARALLEL_DML: builder.append("FORCE PARALLEL DML"); - appendParamaters(builder, parameters); + appendParameters(builder, parameters); break; - + case ENABLE_PARALLEL_DDL: builder.append("ENABLE PARALLEL DDL"); - appendParamaters(builder, parameters); + appendParameters(builder, parameters); break; - + case DISABLE_PARALLEL_DDL: builder.append("DISABLE PARALLEL DDL"); break; - + case FORCE_PARALLEL_DDL: builder.append("FORCE PARALLEL DDL"); - appendParamaters(builder, parameters); + appendParameters(builder, parameters); break; - + case ENABLE_PARALLEL_QUERY: builder.append("ENABLE PARALLEL QUERY"); - appendParamaters(builder, parameters); + appendParameters(builder, parameters); break; - + case DISABLE_PARALLEL_QUERY: builder.append("DISABLE PARALLEL QUERY"); break; - + case FORCE_PARALLEL_QUERY: builder.append("FORCE PARALLEL QUERY"); - appendParamaters(builder, parameters); + appendParameters(builder, parameters); break; - + case ENABLE_RESUMABLE: builder.append("ENABLE RESUMABLE"); - appendParamaters(builder, parameters); + appendParameters(builder, parameters); break; - + case DISABLE_RESUMABLE: builder.append("DISABLE RESUMABLE"); break; - + case SET: builder.append("SET"); - appendParamaters(builder, parameters); + appendParameters(builder, parameters); break; default: // not going to happen - + } return builder.toString(); } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } } diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterSessionOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterSessionOperation.java index 1ab603d59..1b8e4ec2a 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterSessionOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterSessionOperation.java @@ -11,7 +11,6 @@ package net.sf.jsqlparser.statement.alter; /** - * * @author are */ public enum AlterSessionOperation { diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterSystemOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterSystemOperation.java index 8cd08ba6b..e3a4dc553 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterSystemOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterSystemOperation.java @@ -11,7 +11,6 @@ package net.sf.jsqlparser.statement.alter; /** - * * @author Andreas Reichel * @see ALTER * SESSION @@ -44,11 +43,6 @@ public enum AlterSystemOperation { this.label = label; } - @Override - public String toString() { - return label; - } - public static AlterSystemOperation from(String operation) { // We can't use Enum.valueOf() since there White Space involved for (AlterSystemOperation alterSystemOperation : values()) { @@ -58,4 +52,9 @@ public static AlterSystemOperation from(String operation) { } return null; } + + @Override + public String toString() { + return label; + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterSystemStatement.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterSystemStatement.java index 15fef66f1..40ff46b06 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterSystemStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterSystemStatement.java @@ -11,13 +11,14 @@ import java.util.List; import java.util.Objects; + import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; /** - * * @author Andreas Reichel - * @see ALTER SESSION + * @see ALTER + * SESSION */ public class AlterSystemStatement implements Statement { @@ -25,8 +26,16 @@ public class AlterSystemStatement implements Statement { private final List parameters; public AlterSystemStatement(AlterSystemOperation operation, List parameters) { - this.operation = Objects.requireNonNull(operation, "The ALTER SYSTEM Operation must not be Null"); - this.parameters = Objects.requireNonNull(parameters, "The PARAMETERS List must not be null although it can be empty."); + this.operation = + Objects.requireNonNull(operation, "The ALTER SYSTEM Operation must not be Null"); + this.parameters = Objects.requireNonNull(parameters, + "The PARAMETERS List must not be null although it can be empty."); + } + + private static void appendParameters(StringBuilder builder, List parameters) { + for (String s : parameters) { + builder.append(" ").append(s); + } } public AlterSystemOperation getOperation() { @@ -36,24 +45,18 @@ public AlterSystemOperation getOperation() { public List getParameters() { return parameters; } - + @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); - } - - private static void appendParameters(StringBuilder builder, List parameters) { - for (String s: parameters) { - builder.append(" ").append(s); - } + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } - + public StringBuilder appendTo(StringBuilder builder) { builder.append("ALTER SYSTEM ").append(operation); appendParameters(builder, parameters); return builder; } - + @Override public String toString() { return appendTo(new StringBuilder()).toString(); diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/RenameTableStatement.java b/src/main/java/net/sf/jsqlparser/statement/alter/RenameTableStatement.java index c53806f28..94eb39be0 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/RenameTableStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/RenameTableStatement.java @@ -15,48 +15,53 @@ import java.util.Map.Entry; import java.util.Objects; import java.util.Set; + import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; /** - * * @author are - * @see Rename + * @see Rename */ public class RenameTableStatement implements Statement { private final LinkedHashMap tableNames = new LinkedHashMap<>(); - + private boolean usingTableKeyword = false; private boolean usingIfExistsKeyword = false; - + private String waitDirective = ""; public RenameTableStatement(Table oldName, Table newName) { tableNames.put( - Objects.requireNonNull(oldName, "The OLD NAME of the Rename Statement must not be null.") - , Objects.requireNonNull(newName, "The NEW NAME of the Rename Statement must not be null.") - ); + Objects.requireNonNull(oldName, + "The OLD NAME of the Rename Statement must not be null."), + Objects.requireNonNull(newName, + "The NEW NAME of the Rename Statement must not be null.")); } - - public RenameTableStatement(Table oldName, Table newName, boolean usingTableKeyword, boolean usingIfExistsKeyword, String waitDirective) { + + public RenameTableStatement(Table oldName, Table newName, boolean usingTableKeyword, + boolean usingIfExistsKeyword, String waitDirective) { tableNames.put( - Objects.requireNonNull(oldName, "The OLD NAME of the Rename Statement must not be null.") - , Objects.requireNonNull(newName, "The NEW NAME of the Rename Statement must not be null.") - ); - + Objects.requireNonNull(oldName, + "The OLD NAME of the Rename Statement must not be null."), + Objects.requireNonNull(newName, + "The NEW NAME of the Rename Statement must not be null.")); + this.usingTableKeyword = usingTableKeyword; this.usingIfExistsKeyword = usingIfExistsKeyword; this.waitDirective = waitDirective; } - + public void addTableNames(Table oldName, Table newName) { tableNames.put( - Objects.requireNonNull(oldName, "The OLD NAME of the Rename Statement must not be null.") - , Objects.requireNonNull(newName, "The NEW NAME of the Rename Statement must not be null.") - ); + Objects.requireNonNull(oldName, + "The OLD NAME of the Rename Statement must not be null."), + Objects.requireNonNull(newName, + "The NEW NAME of the Rename Statement must not be null.")); } - + public boolean isUsingTableKeyword() { return usingTableKeyword; @@ -65,7 +70,7 @@ public boolean isUsingTableKeyword() { public void setUsingTableKeyword(boolean usingTableKeyword) { this.usingTableKeyword = usingTableKeyword; } - + public RenameTableStatement withUsingTableKeyword(boolean usingTableKeyword) { this.usingTableKeyword = usingTableKeyword; return this; @@ -78,7 +83,7 @@ public boolean isUsingIfExistsKeyword() { public void setUsingIfExistsKeyword(boolean usingIfExistsKeyword) { this.usingIfExistsKeyword = usingIfExistsKeyword; } - + public RenameTableStatement withUsingIfExistsKeyword(boolean usingIfExistsKeyword) { this.usingIfExistsKeyword = usingIfExistsKeyword; return this; @@ -91,7 +96,7 @@ public String getWaitDirective() { public void setWaitDirective(String waitDirective) { this.waitDirective = waitDirective; } - + public RenameTableStatement withWaitDirective(String waitDirective) { this.waitDirective = waitDirective; return this; @@ -108,32 +113,34 @@ public boolean isTableNamesEmpty() { public Set> getTableNames() { return tableNames.entrySet(); } - + @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); - } - + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); + } + public StringBuilder appendTo(StringBuilder builder) { - int i=0; + int i = 0; for (Entry e : tableNames.entrySet()) { - if (i==0) { + if (i == 0) { builder - .append("RENAME") - .append(usingTableKeyword ? " TABLE " : " ") - .append(usingIfExistsKeyword ? " IF EXISTS " : " ") - .append(e.getKey()) - .append(waitDirective!=null && waitDirective.length()>0 ? " " + waitDirective : "") - .append(" TO ") - .append(e.getValue()); + .append("RENAME") + .append(usingTableKeyword ? " TABLE " : " ") + .append(usingIfExistsKeyword ? " IF EXISTS " : " ") + .append(e.getKey()) + .append(waitDirective != null && waitDirective.length() > 0 + ? " " + waitDirective + : "") + .append(" TO ") + .append(e.getValue()); } else { builder - .append(", ") - .append(e.getKey()) - .append(" TO ") - .append(e.getValue()); + .append(", ") + .append(e.getKey()) + .append(" TO ") + .append(e.getValue()); } - + i++; } return builder; diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/sequence/AlterSequence.java b/src/main/java/net/sf/jsqlparser/statement/alter/sequence/AlterSequence.java index cd994717b..a9869f8ed 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/sequence/AlterSequence.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/sequence/AlterSequence.java @@ -20,17 +20,17 @@ public class AlterSequence implements Statement { public Sequence sequence; - public void setSequence(Sequence sequence) { - this.sequence = sequence; - } - public Sequence getSequence() { return sequence; } + public void setSequence(Sequence sequence) { + this.sequence = sequence; + } + @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } @Override diff --git a/src/main/java/net/sf/jsqlparser/statement/analyze/Analyze.java b/src/main/java/net/sf/jsqlparser/statement/analyze/Analyze.java index 35373ae09..ab25cf3b4 100644 --- a/src/main/java/net/sf/jsqlparser/statement/analyze/Analyze.java +++ b/src/main/java/net/sf/jsqlparser/statement/analyze/Analyze.java @@ -18,8 +18,8 @@ public class Analyze implements Statement { private Table table; @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public Table getTable() { diff --git a/src/main/java/net/sf/jsqlparser/statement/comment/Comment.java b/src/main/java/net/sf/jsqlparser/statement/comment/Comment.java index 23942a889..d213aac6b 100755 --- a/src/main/java/net/sf/jsqlparser/statement/comment/Comment.java +++ b/src/main/java/net/sf/jsqlparser/statement/comment/Comment.java @@ -23,8 +23,8 @@ public class Comment implements Statement { private StringValue comment; @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public Table getTable() { diff --git a/src/main/java/net/sf/jsqlparser/statement/create/function/CreateFunction.java b/src/main/java/net/sf/jsqlparser/statement/create/function/CreateFunction.java index b5e1c68a1..ac20c0e3a 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/function/CreateFunction.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/function/CreateFunction.java @@ -26,7 +26,7 @@ public CreateFunction() { public CreateFunction(List functionDeclarationParts) { this(false, functionDeclarationParts); } - + public CreateFunction(boolean orReplace, List functionDeclarationParts) { super(orReplace, "FUNCTION", functionDeclarationParts); } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/index/CreateIndex.java b/src/main/java/net/sf/jsqlparser/statement/create/index/CreateIndex.java index 3fc4fcbf1..87e8f1ee9 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/index/CreateIndex.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/index/CreateIndex.java @@ -12,6 +12,7 @@ import static java.util.stream.Collectors.joining; import java.util.*; + import net.sf.jsqlparser.schema.*; import net.sf.jsqlparser.statement.*; import net.sf.jsqlparser.statement.create.table.*; @@ -22,6 +23,7 @@ public class CreateIndex implements Statement { private Index index; private List tailParameters; private boolean indexTypeBeforeOn = false; + private boolean usingIfNotExists = false; public boolean isIndexTypeBeforeOn() { return indexTypeBeforeOn; @@ -40,11 +42,9 @@ public CreateIndex setUsingIfNotExists(boolean usingIfNotExists) { return this; } - private boolean usingIfNotExists = false; - @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public Index getIndex() { diff --git a/src/main/java/net/sf/jsqlparser/statement/create/procedure/CreateProcedure.java b/src/main/java/net/sf/jsqlparser/statement/create/procedure/CreateProcedure.java index 047f46718..77b385148 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/procedure/CreateProcedure.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/procedure/CreateProcedure.java @@ -11,6 +11,7 @@ import java.util.Collection; import java.util.List; + import net.sf.jsqlparser.statement.CreateFunctionalStatement; /** @@ -41,7 +42,8 @@ public CreateProcedure addFunctionDeclarationParts(String... functionDeclaration } @Override - public CreateProcedure addFunctionDeclarationParts(Collection functionDeclarationParts) { + public CreateProcedure addFunctionDeclarationParts( + Collection functionDeclarationParts) { return (CreateProcedure) super.addFunctionDeclarationParts(functionDeclarationParts); } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/schema/CreateSchema.java b/src/main/java/net/sf/jsqlparser/statement/create/schema/CreateSchema.java index 7832f291e..0a17ddb8c 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/schema/CreateSchema.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/schema/CreateSchema.java @@ -14,6 +14,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; + import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; @@ -25,8 +26,8 @@ public class CreateSchema implements Statement { private List statements = new ArrayList<>(); @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } /** @@ -34,7 +35,6 @@ public void accept(StatementVisitor statementVisitor) { * * @param statement The statement to be added * @return true if the operation was successful - * */ public boolean addStatement(Statement statement) { return statements.add(statement); @@ -44,69 +44,63 @@ public boolean addStatement(Statement statement) { * The owner of the schema. * * @return Owner name - * */ public String getAuthorization() { return authorization; } /** - * The name of the schema + * The owner of the schems. * - * @return Schema name + * @param authorization Owner name */ - public String getSchemaName() { - return schemaName; + public void setAuthorization(String authorization) { + this.authorization = authorization; } /** - * The path of the schema - * - * @return Schema path + * The name of the schema * + * @return Schema name */ - public List getSchemaPath() { - return schemaPath; + public String getSchemaName() { + return schemaName; } /** - * The statements executed as part of the schema creation - * - * @return the statements + * Set the name of the schema * + * @param schemaName Schema name */ - public List getStatements() { - return statements; + public void setSchemaName(String schemaName) { + this.schemaName = schemaName; } /** - * The owner of the schems. - * - * @param authorization Owner name + * The path of the schema * + * @return Schema path */ - public void setAuthorization(String authorization) { - this.authorization = authorization; + public List getSchemaPath() { + return schemaPath; } /** - * Set the name of the schema - * - * @param schemaName Schema name + * Set the path of the schema * + * @param schemaPath Schema path */ - public void setSchemaName(String schemaName) { - this.schemaName = schemaName; + public void setSchemaPath(List schemaPath) { + this.schemaPath = schemaPath; } /** - * Set the path of the schema - * - * @param schemaPath Schema path + * The statements executed as part of the schema creation * + * @return the statements */ - public void setSchemaPath(List schemaPath) { - this.schemaPath = schemaPath; + public List getStatements() { + return statements; } public String toString() { diff --git a/src/main/java/net/sf/jsqlparser/statement/create/sequence/CreateSequence.java b/src/main/java/net/sf/jsqlparser/statement/create/sequence/CreateSequence.java index ba21a04b1..7deff2125 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/sequence/CreateSequence.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/sequence/CreateSequence.java @@ -1,47 +1,42 @@ -/* - * #%L - * JSQLParser library - * %% - * Copyright (C) 2004 - 2020 JSQLParser - * %% - * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 - * #L% - */ -package net.sf.jsqlparser.statement.create.sequence; - -import net.sf.jsqlparser.schema.Sequence; -import net.sf.jsqlparser.statement.Statement; -import net.sf.jsqlparser.statement.StatementVisitor; - -/** - * A {@code CREATE SEQUENCE} statement - */ -public class CreateSequence implements Statement { - - public Sequence sequence; - - public void setSequence(Sequence sequence) { - this.sequence = sequence; - } - - public Sequence getSequence() { - return sequence; - } - - @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); - } - - @Override - public String toString() { - String sql; - sql = "CREATE SEQUENCE " + sequence; - return sql; - } - - public CreateSequence withSequence(Sequence sequence) { - this.setSequence(sequence); - return this; - } -} +/* + * #%L JSQLParser library %% Copyright (C) 2004 - 2020 JSQLParser %% Dual licensed under GNU LGPL + * 2.1 or Apache License 2.0 #L% + */ +package net.sf.jsqlparser.statement.create.sequence; + +import net.sf.jsqlparser.schema.Sequence; +import net.sf.jsqlparser.statement.Statement; +import net.sf.jsqlparser.statement.StatementVisitor; + +/** + * A {@code CREATE SEQUENCE} statement + */ +public class CreateSequence implements Statement { + + public Sequence sequence; + + public Sequence getSequence() { + return sequence; + } + + public void setSequence(Sequence sequence) { + this.sequence = sequence; + } + + @Override + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); + } + + @Override + public String toString() { + String sql; + sql = "CREATE SEQUENCE " + sequence; + return sql; + } + + public CreateSequence withSequence(Sequence sequence) { + this.setSequence(sequence); + return this; + } +} diff --git a/src/main/java/net/sf/jsqlparser/statement/create/synonym/CreateSynonym.java b/src/main/java/net/sf/jsqlparser/statement/create/synonym/CreateSynonym.java index 3528bc60c..ac7eb2640 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/synonym/CreateSynonym.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/synonym/CreateSynonym.java @@ -18,19 +18,19 @@ public class CreateSynonym implements Statement { + public Synonym synonym; private boolean orReplace; private boolean publicSynonym; - public Synonym synonym; private List forList = new ArrayList<>(); - public void setSynonym(Synonym synonym) { - this.synonym = synonym; - } - public Synonym getSynonym() { return synonym; } + public void setSynonym(Synonym synonym) { + this.synonym = synonym; + } + public boolean isOrReplace() { return orReplace; } @@ -47,14 +47,14 @@ public void setPublicSynonym(boolean publicSynonym) { this.publicSynonym = publicSynonym; } - public void setForList(List forList) { - this.forList = forList; - } - public List getForList() { return forList; } + public void setForList(List forList) { + this.forList = forList; + } + public String getFor() { StringBuilder b = new StringBuilder(); for (String name : forList) { @@ -67,8 +67,8 @@ public String getFor() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } @Override diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/CheckConstraint.java b/src/main/java/net/sf/jsqlparser/statement/create/table/CheckConstraint.java index 21a3e5384..b81f7132d 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/table/CheckConstraint.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/CheckConstraint.java @@ -11,6 +11,7 @@ import java.util.Collection; import java.util.List; + import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.schema.Table; diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/ColDataType.java b/src/main/java/net/sf/jsqlparser/statement/create/table/ColDataType.java index 548fc447f..b7b7a9ae9 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/table/ColDataType.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/ColDataType.java @@ -9,14 +9,17 @@ */ package net.sf.jsqlparser.statement.create.table; +import net.sf.jsqlparser.statement.select.PlainSelect; + import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Optional; + import static java.util.stream.Collectors.joining; -import net.sf.jsqlparser.statement.select.PlainSelect; public class ColDataType implements Serializable { @@ -29,6 +32,18 @@ public ColDataType() { // empty constructor } + public ColDataType(String dataType, int precision, int scale) { + this.dataType = dataType; + + if (precision >= 0) { + this.dataType += " (" + (precision == Integer.MAX_VALUE ? "MAX" : precision); + if (scale >= 0) { + this.dataType += ", " + scale; + } + this.dataType += ")"; + } + } + public ColDataType(String dataType) { this.dataType = dataType; } @@ -37,18 +52,18 @@ public List getArgumentsStringList() { return argumentsStringList; } - public String getDataType() { - return dataType; - } - public void setArgumentsStringList(List list) { argumentsStringList = list; } + public String getDataType() { + return dataType; + } + public void setDataType(String string) { dataType = string; } - + public void setDataType(List list) { dataType = list.stream().collect(joining(".")); } @@ -80,8 +95,9 @@ public String toString() { arraySpec.append("]"); } return dataType - + (argumentsStringList != null ? " " + PlainSelect. - getStringList(argumentsStringList, true, true) : "") + + (argumentsStringList != null + ? " " + PlainSelect.getStringList(argumentsStringList, true, true) + : "") + arraySpec.toString() + (characterSet != null ? " CHARACTER SET " + characterSet : ""); } @@ -107,13 +123,15 @@ public ColDataType withArrayData(List arrayData) { } public ColDataType addArgumentsStringList(String... argumentsStringList) { - List collection = Optional.ofNullable(getArgumentsStringList()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getArgumentsStringList()).orElseGet(ArrayList::new); Collections.addAll(collection, argumentsStringList); return this.withArgumentsStringList(collection); } public ColDataType addArgumentsStringList(Collection argumentsStringList) { - List collection = Optional.ofNullable(getArgumentsStringList()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getArgumentsStringList()).orElseGet(ArrayList::new); collection.addAll(argumentsStringList); return this.withArgumentsStringList(collection); } @@ -129,4 +147,29 @@ public ColDataType addArrayData(Collection arrayData) { collection.addAll(arrayData); return this.withArrayData(collection); } + + @Override + public final boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ColDataType)) { + return false; + } + + ColDataType that = (ColDataType) o; + return dataType.equalsIgnoreCase(that.dataType) + && Objects.equals(argumentsStringList, that.argumentsStringList) + && Objects.equals(characterSet, that.characterSet) + && Objects.equals(arrayData, that.arrayData); + } + + @Override + public int hashCode() { + int result = dataType.hashCode(); + result = 31 * result + Objects.hashCode(argumentsStringList); + result = 31 * result + Objects.hashCode(characterSet); + result = 31 * result + Objects.hashCode(arrayData); + return result; + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/CreateTable.java b/src/main/java/net/sf/jsqlparser/statement/create/table/CreateTable.java index d3793589e..390c33777 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/table/CreateTable.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/CreateTable.java @@ -42,8 +42,8 @@ public class CreateTable implements Statement { private SpannerInterleaveIn interleaveIn = null; @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public Table getTable() { @@ -78,11 +78,12 @@ public List getColumns() { } public void setColumns(List columns) { - this.columns =columns; + this.columns = columns; } /** - * @return a list of options (as simple strings) of this table definition, as ("TYPE", "=", "MYISAM") + * @return a list of options (as simple strings) of this table definition, as ("TYPE", "=", + * "MYISAM") */ public List getTableOptionsStrings() { return tableOptionsStrings; @@ -102,8 +103,8 @@ public void setCreateOptionsStrings(List createOptionsStrings) { /** * @return a list of {@link Index}es (for example "PRIMARY KEY") of this table.
- * Indexes created with column definitions (as in mycol INT PRIMARY KEY) are not inserted into - * this list. + * Indexes created with column definitions (as in mycol INT PRIMARY KEY) are not + * inserted into this list. */ public List getIndexes() { return indexes; @@ -197,10 +198,12 @@ public String toString() { sql += " " + rowMovement.getMode().toString() + " ROW MOVEMENT"; } if (select != null) { - sql += " AS " + (selectParenthesis ? "(" : "") + select.toString() + (selectParenthesis ? ")" : ""); + sql += " AS " + (selectParenthesis ? "(" : "") + select.toString() + + (selectParenthesis ? ")" : ""); } if (likeTable != null) { - sql += " LIKE " + (selectParenthesis ? "(" : "") + likeTable.toString() + (selectParenthesis ? ")" : ""); + sql += " LIKE " + (selectParenthesis ? "(" : "") + likeTable.toString() + + (selectParenthesis ? ")" : ""); } if (interleaveIn != null) { sql += ", " + interleaveIn; @@ -259,25 +262,30 @@ public CreateTable withIndexes(List indexes) { } public CreateTable addCreateOptionsStrings(String... createOptionsStrings) { - List collection = Optional.ofNullable(getCreateOptionsStrings()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getCreateOptionsStrings()).orElseGet(ArrayList::new); Collections.addAll(collection, createOptionsStrings); return this.withCreateOptionsStrings(collection); } public CreateTable addCreateOptionsStrings(Collection createOptionsStrings) { - List collection = Optional.ofNullable(getCreateOptionsStrings()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getCreateOptionsStrings()).orElseGet(ArrayList::new); collection.addAll(createOptionsStrings); return this.withCreateOptionsStrings(collection); } public CreateTable addColumnDefinitions(ColumnDefinition... columnDefinitions) { - List collection = Optional.ofNullable(getColumnDefinitions()).orElseGet(ArrayList::new); + List collection = + Optional.ofNullable(getColumnDefinitions()).orElseGet(ArrayList::new); Collections.addAll(collection, columnDefinitions); return this.withColumnDefinitions(collection); } - public CreateTable addColumnDefinitions(Collection columnDefinitions) { - List collection = Optional.ofNullable(getColumnDefinitions()).orElseGet(ArrayList::new); + public CreateTable addColumnDefinitions( + Collection columnDefinitions) { + List collection = + Optional.ofNullable(getColumnDefinitions()).orElseGet(ArrayList::new); collection.addAll(columnDefinitions); return this.withColumnDefinitions(collection); } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/ExcludeConstraint.java b/src/main/java/net/sf/jsqlparser/statement/create/table/ExcludeConstraint.java index cbae5035a..0ec34dd24 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/table/ExcludeConstraint.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/ExcludeConstraint.java @@ -11,6 +11,7 @@ import java.util.Collection; import java.util.List; + import net.sf.jsqlparser.expression.Expression; public class ExcludeConstraint extends Index { @@ -74,7 +75,8 @@ public ExcludeConstraint addColumns(ColumnParams... functionDeclarationParts) { } @Override - public ExcludeConstraint addColumns(Collection functionDeclarationParts) { + public ExcludeConstraint addColumns( + Collection functionDeclarationParts) { return (ExcludeConstraint) super.addColumns(functionDeclarationParts); } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/Index.java b/src/main/java/net/sf/jsqlparser/statement/create/table/Index.java index 720fa1abe..ec7a2d606 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/table/Index.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/Index.java @@ -17,14 +17,15 @@ import java.util.Collections; import java.util.List; import java.util.Optional; + import net.sf.jsqlparser.statement.select.PlainSelect; public class Index implements Serializable { + private final List name = new ArrayList<>(); private String type; private String using; private List columns; - private final List name = new ArrayList<>(); private List idxSpec; private String commentText; @@ -34,6 +35,10 @@ public List getColumnsNames() { .collect(toList()); } + public void setColumnsNames(List list) { + columns = list.stream().map(ColumnParams::new).collect(toList()); + } + @Deprecated public List getColumnWithParams() { return getColumns(); @@ -73,6 +78,16 @@ public String getName() { return name.isEmpty() ? null : String.join(".", name); } + public void setName(String name) { + this.name.clear(); + this.name.add(name); + } + + public void setName(List name) { + this.name.clear(); + this.name.addAll(name); + } + public List getNameParts() { return Collections.unmodifiableList(name); } @@ -81,19 +96,8 @@ public String getType() { return type; } - /** - * In postgresql, the index type (Btree, GIST, etc.) is indicated with a USING clause. Please - * note that: Oracle - the type might be BITMAP, indicating a bitmap kind of index MySQL - the - * type might be FULLTEXT or SPATIAL - * - * @param using - */ - public void setUsing(String using) { - this.using = using; - } - - public void setColumnsNames(List list) { - columns = list.stream().map(ColumnParams::new).collect(toList()); + public void setType(String string) { + type = string; } public Index withColumnsNames(List list) { @@ -101,24 +105,21 @@ public Index withColumnsNames(List list) { return this; } - public void setName(String name) { - this.name.clear(); - this.name.add(name); - } - - public void setName(List name) { - this.name.clear(); - this.name.addAll(name); - } - - public void setType(String string) { - type = string; - } - public String getUsing() { return using; } + /** + * In postgresql, the index type (Btree, GIST, etc.) is indicated with a USING clause. Please + * note that: Oracle - the type might be BITMAP, indicating a bitmap kind of index MySQL - the + * type might be FULLTEXT or SPATIAL + * + * @param using + */ + public void setUsing(String using) { + this.using = using; + } + public List getIndexSpec() { return idxSpec; } @@ -166,6 +167,14 @@ public Index withName(String name) { return this; } + public String getCommentText() { + return commentText; + } + + public void setCommentText(String commentText) { + this.commentText = commentText; + } + public static class ColumnParams implements Serializable { public final String columnName; public final List params; @@ -193,12 +202,4 @@ public String toString() { return columnName + (params != null ? " " + String.join(" ", params) : ""); } } - - public String getCommentText() { - return commentText; - } - - public void setCommentText(String commentText) { - this.commentText = commentText; - } } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/NamedConstraint.java b/src/main/java/net/sf/jsqlparser/statement/create/table/NamedConstraint.java index f9a7f391d..026d56631 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/table/NamedConstraint.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/NamedConstraint.java @@ -11,6 +11,7 @@ import java.util.Collection; import java.util.List; + import net.sf.jsqlparser.statement.select.PlainSelect; public class NamedConstraint extends Index { diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/RowMovement.java b/src/main/java/net/sf/jsqlparser/statement/create/table/RowMovement.java index a9934dcdf..cf6bbe248 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/table/RowMovement.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/RowMovement.java @@ -12,7 +12,8 @@ import java.io.Serializable; /** - * Holds data for the {@code row_movement} clause: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_7002.htm#i2204697 + * Holds data for the {@code row_movement} clause: + * https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_7002.htm#i2204697 */ public class RowMovement implements Serializable { diff --git a/src/main/java/net/sf/jsqlparser/statement/create/view/AlterView.java b/src/main/java/net/sf/jsqlparser/statement/create/view/AlterView.java index 8d43aab3e..079f70bd3 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/view/AlterView.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/view/AlterView.java @@ -28,11 +28,6 @@ public class AlterView implements Statement { private boolean useReplace = false; private List columnNames = null; - @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); - } - public Table getView() { return view; } @@ -117,4 +112,9 @@ public AlterView addColumnNames(Collection columnNames) { public E getSelectBody(Class type) { return type.cast(getSelect()); } + + @Override + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/create/view/CreateView.java b/src/main/java/net/sf/jsqlparser/statement/create/view/CreateView.java index 034902cca..0d7679743 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/view/CreateView.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/view/CreateView.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.statement.create.view; import java.util.List; + import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; @@ -34,8 +35,8 @@ public class CreateView implements Statement { private List viewCommentOptions = null; @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public Table getView() { diff --git a/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java b/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java index 3e5c171a3..931d486c7 100644 --- a/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java +++ b/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java @@ -103,22 +103,22 @@ public void setOrderByElements(List orderByElements) { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public Table getTable() { return table; } - public Expression getWhere() { - return where; - } - public void setTable(Table name) { table = name; } + public Expression getWhere() { + return where; + } + public void setWhere(Expression expression) { where = expression; } @@ -309,30 +309,30 @@ public Delete withModifierQuick(boolean modifierQuick) { return this; } - public void setModifierPriority(DeleteModifierPriority modifierPriority) { - this.modifierPriority = modifierPriority; - } - public DeleteModifierPriority getModifierPriority() { return modifierPriority; } - public void setModifierIgnore(boolean modifierIgnore) { - this.modifierIgnore = modifierIgnore; - } - - public void setModifierQuick(boolean modifierQuick) { - this.modifierQuick = modifierQuick; + public void setModifierPriority(DeleteModifierPriority modifierPriority) { + this.modifierPriority = modifierPriority; } public boolean isModifierIgnore() { return modifierIgnore; } + public void setModifierIgnore(boolean modifierIgnore) { + this.modifierIgnore = modifierIgnore; + } + public boolean isModifierQuick() { return modifierQuick; } + public void setModifierQuick(boolean modifierQuick) { + this.modifierQuick = modifierQuick; + } + public Delete addTables(Table... tables) { List collection = Optional.ofNullable(getTables()).orElseGet(ArrayList::new); Collections.addAll(collection, tables); diff --git a/src/main/java/net/sf/jsqlparser/statement/drop/Drop.java b/src/main/java/net/sf/jsqlparser/statement/drop/Drop.java index 402574d26..a7ac36253 100644 --- a/src/main/java/net/sf/jsqlparser/statement/drop/Drop.java +++ b/src/main/java/net/sf/jsqlparser/statement/drop/Drop.java @@ -16,6 +16,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; + import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; @@ -32,31 +33,38 @@ public class Drop implements Statement { private boolean isUsingTemporary; + public static String formatFuncParams(List params) { + if (params == null) { + return ""; + } + return params.isEmpty() ? "()" : PlainSelect.getStringList(params, true, true); + } + @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public Table getName() { return name; } - public List getParameters() { - return parameters; - } - - public String getType() { - return type; - } - public void setName(Table string) { name = string; } + public List getParameters() { + return parameters; + } + public void setParameters(List list) { parameters = list; } + public String getType() { + return type; + } + public void setType(String string) { type = string; } @@ -74,7 +82,7 @@ public boolean isUsingTemporary() { } public void setUsingTemporary(boolean useTemporary) { - this.isUsingTemporary=useTemporary; + this.isUsingTemporary = useTemporary; } public Drop withUsingTemporary(boolean useTemporary) { @@ -117,13 +125,6 @@ public String toString() { return sql; } - public static String formatFuncParams(List params) { - if (params == null) { - return ""; - } - return params.isEmpty() ? "()" : PlainSelect.getStringList(params, true, true); - } - public List getParamsByType(String type) { return typeToParameters.get(type); } diff --git a/src/main/java/net/sf/jsqlparser/statement/execute/Execute.java b/src/main/java/net/sf/jsqlparser/statement/execute/Execute.java index 366a982e6..e0d597700 100644 --- a/src/main/java/net/sf/jsqlparser/statement/execute/Execute.java +++ b/src/main/java/net/sf/jsqlparser/statement/execute/Execute.java @@ -63,8 +63,8 @@ public boolean isParenthesis() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } @Override diff --git a/src/main/java/net/sf/jsqlparser/statement/grant/Grant.java b/src/main/java/net/sf/jsqlparser/statement/grant/Grant.java index d553adff6..ba46cb365 100644 --- a/src/main/java/net/sf/jsqlparser/statement/grant/Grant.java +++ b/src/main/java/net/sf/jsqlparser/statement/grant/Grant.java @@ -14,7 +14,9 @@ import java.util.Collections; import java.util.List; import java.util.Optional; + import static java.util.stream.Collectors.joining; + import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; @@ -26,8 +28,8 @@ public class Grant implements Statement { private List users; @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public String getRole() { @@ -47,25 +49,26 @@ public void setPrivileges(List privileges) { } public String getObjectName() { - return objectName.size()==0?null:objectName.stream() - .map(part -> part==null?"":part) - .collect(joining(".")); - } - - public List getObjectNameParts() { - return objectName; + return objectName.isEmpty() ? null + : objectName.stream() + .map(part -> part == null ? "" : part) + .collect(joining(".")); } public void setObjectName(String objectName) { this.objectName.clear(); this.objectName.add(objectName); } - + public void setObjectName(List objectName) { this.objectName.clear(); this.objectName.addAll(objectName); } + public List getObjectNameParts() { + return objectName; + } + public List getUsers() { return users; } @@ -115,7 +118,7 @@ public Grant withObjectName(String objectName) { this.setObjectName(objectName); return this; } - + public Grant withObjectName(List objectName) { this.setObjectName(objectName); return this; diff --git a/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java b/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java index bb5595a35..cdb16be05 100644 --- a/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java +++ b/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java @@ -74,8 +74,8 @@ public void setOutputClause(OutputClause outputClause) { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public Table getTable() { diff --git a/src/main/java/net/sf/jsqlparser/statement/insert/InsertConflictAction.java b/src/main/java/net/sf/jsqlparser/statement/insert/InsertConflictAction.java index 8bbba83b7..76781bbcc 100644 --- a/src/main/java/net/sf/jsqlparser/statement/insert/InsertConflictAction.java +++ b/src/main/java/net/sf/jsqlparser/statement/insert/InsertConflictAction.java @@ -21,7 +21,7 @@ /** * https://www.postgresql.org/docs/current/sql-insert.html - * + * *
  * conflict_action is one of:
  *
@@ -36,10 +36,8 @@
 
 public class InsertConflictAction implements Serializable {
     ConflictActionType conflictActionType;
-
-    private List updateSets;
-
     Expression whereExpression;
+    private List updateSets;
 
     public InsertConflictAction(ConflictActionType conflictActionType) {
         this.conflictActionType = Objects.requireNonNull(conflictActionType,
diff --git a/src/main/java/net/sf/jsqlparser/statement/insert/InsertConflictTarget.java b/src/main/java/net/sf/jsqlparser/statement/insert/InsertConflictTarget.java
index 070996483..59c2d624c 100644
--- a/src/main/java/net/sf/jsqlparser/statement/insert/InsertConflictTarget.java
+++ b/src/main/java/net/sf/jsqlparser/statement/insert/InsertConflictTarget.java
@@ -16,14 +16,14 @@
 
 /**
  * https://www.postgresql.org/docs/current/sql-insert.html
- * 
+ *
  * 
  * conflict_target can be one of:
  *
  *     ( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ]
  *     ON CONSTRAINT constraint_name
  * 
- * + *

* Currently, COLLATE is not supported yet. */ public class InsertConflictTarget implements Serializable { diff --git a/src/main/java/net/sf/jsqlparser/statement/merge/Merge.java b/src/main/java/net/sf/jsqlparser/statement/merge/Merge.java index ed2c9ee50..689bd5d8e 100644 --- a/src/main/java/net/sf/jsqlparser/statement/merge/Merge.java +++ b/src/main/java/net/sf/jsqlparser/statement/merge/Merge.java @@ -192,8 +192,8 @@ public void setMergeUpdate(MergeUpdate mergeUpdate) { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public boolean isInsertFirst() { diff --git a/src/main/java/net/sf/jsqlparser/statement/merge/MergeDelete.java b/src/main/java/net/sf/jsqlparser/statement/merge/MergeDelete.java index fee068a99..bfacef1c1 100644 --- a/src/main/java/net/sf/jsqlparser/statement/merge/MergeDelete.java +++ b/src/main/java/net/sf/jsqlparser/statement/merge/MergeDelete.java @@ -30,8 +30,8 @@ public MergeDelete withAndPredicate(Expression andPredicate) { } @Override - public void accept(MergeOperationVisitor mergeOperationVisitor) { - mergeOperationVisitor.visit(this); + public T accept(MergeOperationVisitor mergeOperationVisitor, S context) { + return mergeOperationVisitor.visit(this, context); } @Override diff --git a/src/main/java/net/sf/jsqlparser/statement/merge/MergeInsert.java b/src/main/java/net/sf/jsqlparser/statement/merge/MergeInsert.java index 95b69bbf3..be0d4bb2f 100644 --- a/src/main/java/net/sf/jsqlparser/statement/merge/MergeInsert.java +++ b/src/main/java/net/sf/jsqlparser/statement/merge/MergeInsert.java @@ -58,8 +58,8 @@ public void setWhereCondition(Expression whereCondition) { } @Override - public void accept(MergeOperationVisitor mergeOperationVisitor) { - mergeOperationVisitor.visit(this); + public T accept(MergeOperationVisitor mergeOperationVisitor, S context) { + return mergeOperationVisitor.visit(this, context); } @Override diff --git a/src/main/java/net/sf/jsqlparser/statement/merge/MergeOperation.java b/src/main/java/net/sf/jsqlparser/statement/merge/MergeOperation.java index 6a4a9ceff..71447d23d 100644 --- a/src/main/java/net/sf/jsqlparser/statement/merge/MergeOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/merge/MergeOperation.java @@ -13,5 +13,5 @@ * Marker interface to cover {@link MergeDelete}, {@link MergeUpdate} and {@link MergeInsert} */ public interface MergeOperation { - void accept(MergeOperationVisitor mergeOperationVisitor); + T accept(MergeOperationVisitor mergeOperationVisitor, S context); } diff --git a/src/main/java/net/sf/jsqlparser/statement/merge/MergeOperationVisitor.java b/src/main/java/net/sf/jsqlparser/statement/merge/MergeOperationVisitor.java index 5a0f217d6..fef9682fe 100644 --- a/src/main/java/net/sf/jsqlparser/statement/merge/MergeOperationVisitor.java +++ b/src/main/java/net/sf/jsqlparser/statement/merge/MergeOperationVisitor.java @@ -9,11 +9,11 @@ */ package net.sf.jsqlparser.statement.merge; -public interface MergeOperationVisitor { +public interface MergeOperationVisitor { - void visit(MergeDelete mergeDelete); + T visit(MergeDelete mergeDelete, S context); - void visit(MergeUpdate mergeUpdate); + T visit(MergeUpdate mergeUpdate, S context); - void visit(MergeInsert mergeInsert); + T visit(MergeInsert mergeInsert, S context); } diff --git a/src/main/java/net/sf/jsqlparser/statement/merge/MergeOperationVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/statement/merge/MergeOperationVisitorAdapter.java index 80883192c..546b44604 100644 --- a/src/main/java/net/sf/jsqlparser/statement/merge/MergeOperationVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/statement/merge/MergeOperationVisitorAdapter.java @@ -10,19 +10,19 @@ package net.sf.jsqlparser.statement.merge; @SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) -public class MergeOperationVisitorAdapter implements MergeOperationVisitor { +public class MergeOperationVisitorAdapter implements MergeOperationVisitor { @Override - public void visit(MergeDelete mergeDelete) { - + public T visit(MergeDelete mergeDelete, S context) { + return null; } @Override - public void visit(MergeUpdate mergeUpdate) { - + public T visit(MergeUpdate mergeUpdate, S context) { + return null; } @Override - public void visit(MergeInsert mergeInsert) { - + public T visit(MergeInsert mergeInsert, S context) { + return null; } } diff --git a/src/main/java/net/sf/jsqlparser/statement/merge/MergeUpdate.java b/src/main/java/net/sf/jsqlparser/statement/merge/MergeUpdate.java index c744ac4f2..2cae3e176 100644 --- a/src/main/java/net/sf/jsqlparser/statement/merge/MergeUpdate.java +++ b/src/main/java/net/sf/jsqlparser/statement/merge/MergeUpdate.java @@ -62,8 +62,8 @@ public void setDeleteWhereCondition(Expression deleteWhereCondition) { } @Override - public void accept(MergeOperationVisitor mergeOperationVisitor) { - mergeOperationVisitor.visit(this); + public T accept(MergeOperationVisitor mergeOperationVisitor, S context) { + return mergeOperationVisitor.visit(this, context); } @Override diff --git a/src/main/java/net/sf/jsqlparser/statement/refresh/RefreshMaterializedViewStatement.java b/src/main/java/net/sf/jsqlparser/statement/refresh/RefreshMaterializedViewStatement.java index 86b530ed3..6519cfe5c 100644 --- a/src/main/java/net/sf/jsqlparser/statement/refresh/RefreshMaterializedViewStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/refresh/RefreshMaterializedViewStatement.java @@ -91,8 +91,8 @@ public String toString() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public RefreshMaterializedViewStatement withTableName(Table view) { diff --git a/src/main/java/net/sf/jsqlparser/statement/select/AllColumns.java b/src/main/java/net/sf/jsqlparser/statement/select/AllColumns.java index 433dffdc6..a1b16dae9 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/AllColumns.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/AllColumns.java @@ -20,12 +20,21 @@ public class AllColumns extends ASTNodeAccessImpl implements Expression { protected ExpressionList exceptColumns; - protected List> replaceExpressions; + protected List> replaceExpressions; + private String exceptKeyword; public AllColumns(ExpressionList exceptColumns, - List> replaceExpressions) { + List> replaceExpressions) { this.exceptColumns = exceptColumns; this.replaceExpressions = replaceExpressions; + this.exceptKeyword = exceptColumns != null ? "Except" : null; + } + + public AllColumns(ExpressionList exceptColumns, + List> replaceExpressions, String exceptKeyword) { + this.exceptColumns = exceptColumns; + this.replaceExpressions = replaceExpressions; + this.exceptKeyword = exceptKeyword; } public AllColumns() { @@ -36,6 +45,11 @@ public ExpressionList getExceptColumns() { return exceptColumns; } + public AllColumns setExceptColumns(ExpressionList exceptColumns) { + this.exceptColumns = exceptColumns; + return this; + } + public ExpressionList addExceptColumn(Column column) { if (exceptColumns == null) { exceptColumns = new ExpressionList<>(); @@ -44,16 +58,16 @@ public ExpressionList addExceptColumn(Column column) { return exceptColumns; } - public AllColumns setExceptColumns(ExpressionList exceptColumns) { - this.exceptColumns = exceptColumns; - return this; + public List> getReplaceExpressions() { + return replaceExpressions; } - public List> getReplaceExpressions() { - return replaceExpressions; + public AllColumns setReplaceExpressions(List> replaceExpressions) { + this.replaceExpressions = replaceExpressions; + return this; } - public List> addReplaceExpression(SelectItem selectItem) { + public List> addReplaceExpression(SelectItem selectItem) { if (replaceExpressions == null) { replaceExpressions = new ArrayList<>(); } @@ -61,19 +75,23 @@ public List> addReplaceExpression(SelectItem selectItem) { return replaceExpressions; } - public AllColumns setReplaceExpressions(List> replaceExpressions) { - this.replaceExpressions = replaceExpressions; + public String getExceptKeyword() { + return exceptKeyword; + } + + public AllColumns setExceptKeyword(String exceptKeyword) { + this.exceptKeyword = exceptKeyword; return this; } public StringBuilder appendTo(StringBuilder builder) { builder.append("*"); - if (exceptColumns != null && exceptColumns.size() > 0) { - builder.append(" Except( "); + if (exceptColumns != null && !exceptColumns.isEmpty()) { + builder.append(" ").append(exceptKeyword).append("( "); exceptColumns.appendTo(builder); builder.append(" )"); } - if (replaceExpressions != null && replaceExpressions.size() > 0) { + if (replaceExpressions != null && !replaceExpressions.isEmpty()) { builder.append(" Replace("); int i = 0; for (SelectItem selectItem : replaceExpressions) { @@ -91,7 +109,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/statement/select/AllTableColumns.java b/src/main/java/net/sf/jsqlparser/statement/select/AllTableColumns.java index cda2e8136..d5c41e7c7 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/AllTableColumns.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/AllTableColumns.java @@ -21,17 +21,23 @@ public class AllTableColumns extends AllColumns { private Table table; public AllTableColumns(Table table, ExpressionList exceptColumns, - List> replaceExpressions) { - super(exceptColumns, replaceExpressions); + List> replaceExpressions, String exceptKeyword) { + super(exceptColumns, replaceExpressions, exceptKeyword); this.table = table; } + public AllTableColumns(Table table, ExpressionList exceptColumns, + List> replaceExpressions) { + this(table, exceptColumns, replaceExpressions, "EXCEPT"); + } + public AllTableColumns(Table table) { this(table, null, null); } public AllTableColumns(Table table, AllColumns allColumns) { - this(table, allColumns.exceptColumns, allColumns.replaceExpressions); + this(table, allColumns.exceptColumns, allColumns.replaceExpressions, + allColumns.getExceptKeyword()); } public Table getTable() { @@ -53,7 +59,7 @@ public StringBuilder appendTo(StringBuilder builder) { } @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/statement/select/Fetch.java b/src/main/java/net/sf/jsqlparser/statement/select/Fetch.java index f4590d7df..4e8fd9db6 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Fetch.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Fetch.java @@ -19,9 +19,9 @@ import java.util.List; public class Fetch implements Serializable { + private final List fetchParameters = new ArrayList<>(); private Expression expression = null; private boolean isFetchParamFirst = false; - private final List fetchParameters = new ArrayList<>(); @Deprecated public long getRowCount() { @@ -51,6 +51,11 @@ public JdbcParameter getFetchJdbcParameter() { return expression instanceof JdbcParameter ? (JdbcParameter) expression : null; } + @Deprecated + public void setFetchJdbcParameter(JdbcParameter jdbc) { + this.setExpression(jdbc); + } + public Fetch addFetchParameter(String parameter) { fetchParameters.add(parameter); return this; @@ -69,15 +74,6 @@ public String getFetchParam() { return parameterStr.trim(); } - public boolean isFetchParamFirst() { - return isFetchParamFirst; - } - - @Deprecated - public void setFetchJdbcParameter(JdbcParameter jdbc) { - this.setExpression(jdbc); - } - @Deprecated public void setFetchParam(String s) { fetchParameters.clear(); @@ -86,6 +82,10 @@ public void setFetchParam(String s) { } } + public boolean isFetchParamFirst() { + return isFetchParamFirst; + } + public void setFetchParamFirst(boolean b) { this.isFetchParamFirst = b; } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/First.java b/src/main/java/net/sf/jsqlparser/statement/select/First.java index b6d872941..3744e30a3 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/First.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/First.java @@ -15,14 +15,6 @@ public class First implements Serializable { - public enum Keyword { - FIRST, LIMIT; - - public static Keyword from(String keyword) { - return Enum.valueOf(Keyword.class, keyword.toUpperCase()); - } - } - private Keyword keyword; private Long rowCount; private JdbcParameter jdbcParameter; @@ -94,4 +86,12 @@ public First withVariable(String variable) { this.setVariable(variable); return this; } + + public enum Keyword { + FIRST, LIMIT; + + public static Keyword from(String keyword) { + return Enum.valueOf(Keyword.class, keyword.toUpperCase()); + } + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/ForClause.java b/src/main/java/net/sf/jsqlparser/statement/select/ForClause.java index 28af1c276..4604425a3 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/ForClause.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/ForClause.java @@ -12,14 +12,6 @@ import net.sf.jsqlparser.parser.ASTNodeAccessImpl; public class ForClause extends ASTNodeAccessImpl { - public enum ForOption { - BROWSE, XML, JSON; - - public static ForOption from(String option) { - return Enum.valueOf(ForOption.class, option.toUpperCase()); - } - } - private ForOption forOption; public ForOption getForOption() { @@ -35,4 +27,12 @@ public ForClause setForOption(String forOption) { public String toString() { return appendTo(new StringBuilder()).toString(); } + + public enum ForOption { + BROWSE, XML, JSON; + + public static ForOption from(String option) { + return Enum.valueOf(ForOption.class, option.toUpperCase()); + } + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/ForMode.java b/src/main/java/net/sf/jsqlparser/statement/select/ForMode.java index a58233ed1..846faf9ed 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/ForMode.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/ForMode.java @@ -24,11 +24,11 @@ public enum ForMode { private final String value; - public String getValue() { - return value; - } - ForMode(String s) { this.value = s; } + + public String getValue() { + return value; + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/FromItem.java b/src/main/java/net/sf/jsqlparser/statement/select/FromItem.java index eb2ee84c4..667331481 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/FromItem.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/FromItem.java @@ -9,39 +9,43 @@ */ package net.sf.jsqlparser.statement.select; -import net.sf.jsqlparser.Model; import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.parser.ASTNodeAccess; -public interface FromItem extends Model { +public interface FromItem extends ASTNodeAccess { - void accept(FromItemVisitor fromItemVisitor); + T accept(FromItemVisitor fromItemVisitor, S context); + + default void accept(FromItemVisitor fromItemVisitor) { + this.accept(fromItemVisitor, null); + } Alias getAlias(); + void setAlias(Alias alias); + default FromItem withAlias(Alias alias) { setAlias(alias); return this; } - void setAlias(Alias alias); - Pivot getPivot(); + void setPivot(Pivot pivot); + default FromItem withPivot(Pivot pivot) { setPivot(pivot); return this; } - void setPivot(Pivot pivot); - UnPivot getUnPivot(); + void setUnPivot(UnPivot unpivot); + default FromItem withUnPivot(UnPivot unpivot) { setUnPivot(unpivot); return this; } - void setUnPivot(UnPivot unpivot); - } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/FromItemVisitor.java b/src/main/java/net/sf/jsqlparser/statement/select/FromItemVisitor.java index a25f5d03e..13b78201c 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/FromItemVisitor.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/FromItemVisitor.java @@ -11,15 +11,41 @@ import net.sf.jsqlparser.schema.Table; -public interface FromItemVisitor { +public interface FromItemVisitor { - void visit(Table tableName); + T visit(Table tableName, S context); - void visit(ParenthesedSelect selectBody); + default void visit(Table tableName) { + this.visit(tableName, null); + } - void visit(LateralSubSelect lateralSubSelect); + T visit(ParenthesedSelect selectBody, S context); - void visit(TableFunction tableFunction); + default void visit(ParenthesedSelect selectBody) { + this.visit(selectBody, null); + } - void visit(ParenthesedFromItem aThis); + T visit(LateralSubSelect lateralSubSelect, S context); + + default void visit(LateralSubSelect lateralSubSelect) { + this.visit(lateralSubSelect, null); + } + + T visit(TableFunction tableFunction, S context); + + default void visit(TableFunction tableFunction) { + this.visit(tableFunction, null); + } + + T visit(ParenthesedFromItem parenthesedFromItem, S context); + + default void visit(ParenthesedFromItem parenthesedFromItem) { + this.visit(parenthesedFromItem, null); + } + + T visit(Values values, S context); + + default void visit(Values values) { + this.visit(values, null); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/FromItemVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/statement/select/FromItemVisitorAdapter.java index 8c25b6327..7daad1cab 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/FromItemVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/FromItemVisitorAdapter.java @@ -12,30 +12,41 @@ import net.sf.jsqlparser.schema.Table; @SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) -public class FromItemVisitorAdapter implements FromItemVisitor { +public class FromItemVisitorAdapter implements FromItemVisitor { @Override - public void visit(Table table) { + public T visit(Table table, S context) { + return null; } @Override - public void visit(ParenthesedSelect selectBody) { + public T visit(ParenthesedSelect select, S context) { + return null; } @Override - public void visit(LateralSubSelect lateralSubSelect) { + public T visit(LateralSubSelect lateralSubSelect, S context) { + return null; } @Override - public void visit(TableFunction valuesList) { + public T visit(TableFunction tableFunction, S context) { + return null; } @Override - public void visit(ParenthesedFromItem aThis) { + public T visit(ParenthesedFromItem fromItem, S context) { + return null; + } + + @Override + public T visit(Values values, S context) { + + return null; } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/GroupByElement.java b/src/main/java/net/sf/jsqlparser/statement/select/GroupByElement.java index d052ad465..a4517cf84 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/GroupByElement.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/GroupByElement.java @@ -16,6 +16,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; + import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; @@ -30,23 +31,23 @@ public boolean isUsingBrackets() { return groupByExpressions.isUsingBrackets(); } - public void accept(GroupByVisitor groupByVisitor) { - groupByVisitor.visit(this); + public T accept(GroupByVisitor groupByVisitor, S context) { + return groupByVisitor.visit(this, context); } public ExpressionList getGroupByExpressionList() { return groupByExpressions; } - public void setGroupByExpressions(ExpressionList groupByExpressions) { - this.groupByExpressions = groupByExpressions; - } - @Deprecated public ExpressionList getGroupByExpressions() { return groupByExpressions; } + public void setGroupByExpressions(ExpressionList groupByExpressions) { + this.groupByExpressions = groupByExpressions; + } + @Deprecated public void addGroupByExpression(Expression groupByExpression) { if (groupByExpressions.getExpressions() == null) { diff --git a/src/main/java/net/sf/jsqlparser/statement/select/GroupByVisitor.java b/src/main/java/net/sf/jsqlparser/statement/select/GroupByVisitor.java index 21bfc5784..24ade130d 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/GroupByVisitor.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/GroupByVisitor.java @@ -9,7 +9,11 @@ */ package net.sf.jsqlparser.statement.select; -public interface GroupByVisitor { +public interface GroupByVisitor { - void visit(GroupByElement groupBy); + T visit(GroupByElement groupBy, S context); + + default void visit(GroupByElement groupBy) { + this.visit(groupBy, null); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/IntoTableVisitor.java b/src/main/java/net/sf/jsqlparser/statement/select/IntoTableVisitor.java index 64a85ca9c..40be04581 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/IntoTableVisitor.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/IntoTableVisitor.java @@ -11,7 +11,11 @@ import net.sf.jsqlparser.schema.Table; -public interface IntoTableVisitor { +public interface IntoTableVisitor { - void visit(Table tableName); + T visit(Table tableName, S context); + + default void visit(Table tableName) { + this.visit(tableName, null); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/IntoTableVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/statement/select/IntoTableVisitorAdapter.java index 77e56e6e9..44393beb3 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/IntoTableVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/IntoTableVisitorAdapter.java @@ -12,10 +12,10 @@ import net.sf.jsqlparser.schema.Table; @SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) -public class IntoTableVisitorAdapter implements IntoTableVisitor { +public class IntoTableVisitorAdapter implements IntoTableVisitor { @Override - public void visit(Table tableName) { - + public T visit(Table tableName, S context) { + return null; } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Join.java b/src/main/java/net/sf/jsqlparser/statement/select/Join.java index d057a5381..bbd32df01 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Join.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Join.java @@ -23,6 +23,8 @@ @SuppressWarnings({"PMD.CyclomaticComplexity"}) public class Join extends ASTNodeAccessImpl { + private final LinkedList onExpressions = new LinkedList<>(); + private final LinkedList usingColumns = new LinkedList<>(); private boolean outer = false; private boolean right = false; private boolean left = false; @@ -36,8 +38,6 @@ public class Join extends ASTNodeAccessImpl { private boolean straight = false; private boolean apply = false; private FromItem fromItem; - private final LinkedList onExpressions = new LinkedList<>(); - private final LinkedList usingColumns = new LinkedList<>(); private KSQLJoinWindow joinWindow; private JoinHint joinHint = null; @@ -46,20 +46,19 @@ public boolean isSimple() { return simple; } + public void setSimple(boolean b) { + simple = b; + } + public Join withSimple(boolean b) { this.setSimple(b); return this; } - public void setSimple(boolean b) { - simple = b; - } - /** * A JOIN means INNER when the INNER keyword is set or when no other qualifier has been set. * * @return Tells, if a JOIN means a qualified INNER JOIN. - * */ public boolean isInnerJoin() { return inner @@ -75,20 +74,13 @@ public boolean isInnerJoin() { } /** - * * @return Tells, if the INNER keyword has been set. */ public boolean isInner() { return inner; } - public Join withInner(boolean b) { - this.setInner(b); - return this; - } - /** - * * Sets the INNER keyword and switches off any contradicting qualifiers automatically. */ public void setInner(boolean b) { @@ -102,19 +94,24 @@ public void setInner(boolean b) { inner = b; } + public Join withInner(boolean b) { + this.setInner(b); + return this; + } + public boolean isStraight() { return straight; } + public void setStraight(boolean b) { + straight = b; + } + public Join withStraight(boolean b) { this.setStraight(b); return this; } - public void setStraight(boolean b) { - straight = b; - } - /** * Whether is a "OUTER" join * @@ -124,13 +121,7 @@ public boolean isOuter() { return outer; } - public Join withOuter(boolean b) { - this.setOuter(b); - return this; - } - /** - * * Sets the OUTER keyword and switches off any contradicting qualifiers automatically. */ public void setOuter(boolean b) { @@ -140,19 +131,24 @@ public void setOuter(boolean b) { outer = b; } + public Join withOuter(boolean b) { + this.setOuter(b); + return this; + } + public boolean isApply() { return apply; } + public void setApply(boolean apply) { + this.apply = apply; + } + public Join withApply(boolean apply) { this.setApply(apply); return this; } - public void setApply(boolean apply) { - this.apply = apply; - } - /** * Whether is a "SEMI" join * @@ -162,15 +158,15 @@ public boolean isSemi() { return semi; } + public void setSemi(boolean b) { + semi = b; + } + public Join withSemi(boolean b) { this.setSemi(b); return this; } - public void setSemi(boolean b) { - semi = b; - } - /** * Whether is a "LEFT" join * @@ -180,13 +176,7 @@ public boolean isLeft() { return left; } - public Join withLeft(boolean b) { - this.setLeft(b); - return this; - } - /** - * * Sets the LEFT keyword and switches off any contradicting qualifiers automatically. */ public void setLeft(boolean b) { @@ -197,6 +187,11 @@ public void setLeft(boolean b) { left = b; } + public Join withLeft(boolean b) { + this.setLeft(b); + return this; + } + /** * Whether is a "RIGHT" join * @@ -206,13 +201,7 @@ public boolean isRight() { return right; } - public Join withRight(boolean b) { - this.setRight(b); - return this; - } - /** - * * Sets the RIGHT keyword and switches off any contradicting qualifiers automatically. */ public void setRight(boolean b) { @@ -223,6 +212,11 @@ public void setRight(boolean b) { right = b; } + public Join withRight(boolean b) { + this.setRight(b); + return this; + } + /** * Whether is a "NATURAL" join * @@ -232,23 +226,23 @@ public boolean isNatural() { return natural; } + public void setNatural(boolean b) { + natural = b; + } + public boolean isGlobal() { return global; } + public void setGlobal(boolean b) { + global = b; + } + public Join withNatural(boolean b) { this.setNatural(b); return this; } - public void setNatural(boolean b) { - natural = b; - } - - public void setGlobal(boolean b) { - global = b; - } - /** * Whether is a "FULL" join * @@ -258,46 +252,45 @@ public boolean isFull() { return full; } + public void setFull(boolean b) { + full = b; + } + public Join withFull(boolean b) { this.setFull(b); return this; } - public void setFull(boolean b) { - full = b; - } - public boolean isCross() { return cross; } + public void setCross(boolean cross) { + this.cross = cross; + } + public Join withCross(boolean cross) { this.setCross(cross); return this; } - public void setCross(boolean cross) { - this.cross = cross; - } - /** * Returns the right item of the join - * */ public FromItem getRightItem() { return fromItem; } + public void setRightItem(FromItem item) { + fromItem = item; + } + @Deprecated public Join withRightItem(FromItem item) { this.setFromItem(item); return this; } - public void setRightItem(FromItem item) { - fromItem = item; - } - public FromItem getFromItem() { return fromItem; } @@ -315,19 +308,25 @@ public Expression getOnExpression() { return onExpressions.get(0); } + @Deprecated + public void setOnExpression(Expression expression) { + onExpressions.add(0, expression); + } + public Collection getOnExpressions() { return onExpressions; } - @Deprecated - public Join withOnExpression(Expression expression) { - this.setOnExpression(expression); + public Join setOnExpressions(Collection expressions) { + onExpressions.clear(); + onExpressions.addAll(expressions); return this; } @Deprecated - public void setOnExpression(Expression expression) { - onExpressions.add(0, expression); + public Join withOnExpression(Expression expression) { + this.setOnExpression(expression); + return this; } public Join addOnExpression(Expression expression) { @@ -335,12 +334,6 @@ public Join addOnExpression(Expression expression) { return this; } - public Join setOnExpressions(Collection expressions) { - onExpressions.clear(); - onExpressions.addAll(expressions); - return this; - } - /** * Returns the "USING" list of {@link net.sf.jsqlparser.schema.Column}s (if any) */ @@ -348,38 +341,38 @@ public List getUsingColumns() { return usingColumns; } - public Join withUsingColumns(List list) { - this.setUsingColumns(list); - return this; - } - public void setUsingColumns(List list) { usingColumns.clear(); usingColumns.addAll(list); } + public Join withUsingColumns(List list) { + this.setUsingColumns(list); + return this; + } + public boolean isWindowJoin() { return joinWindow != null; } /** * Return the "WITHIN" join window (if any) - * + * * @return */ public KSQLJoinWindow getJoinWindow() { return joinWindow; } + public void setJoinWindow(KSQLJoinWindow joinWindow) { + this.joinWindow = joinWindow; + } + public Join withJoinWindow(KSQLJoinWindow joinWindow) { this.setJoinWindow(joinWindow); return this; } - public void setJoinWindow(KSQLJoinWindow joinWindow) { - this.joinWindow = joinWindow; - } - public JoinHint getJoinHint() { return joinHint; } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/KSQLJoinWindow.java b/src/main/java/net/sf/jsqlparser/statement/select/KSQLJoinWindow.java index a1598aac8..4bcc6a0a1 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/KSQLJoinWindow.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/KSQLJoinWindow.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.statement.select; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; + import static net.sf.jsqlparser.statement.select.KSQLWindow.TimeUnit; public class KSQLJoinWindow extends ASTNodeAccessImpl { @@ -22,6 +23,10 @@ public class KSQLJoinWindow extends ASTNodeAccessImpl { private long afterDuration; private TimeUnit afterTimeUnit; + public final static TimeUnit from(String timeUnitStr) { + return Enum.valueOf(TimeUnit.class, timeUnitStr.toUpperCase()); + } + public boolean isBeforeAfterWindow() { return beforeAfter; } @@ -116,8 +121,4 @@ public KSQLJoinWindow withAfterTimeUnit(TimeUnit afterTimeUnit) { this.setAfterTimeUnit(afterTimeUnit); return this; } - - public final static TimeUnit from(String timeUnitStr) { - return Enum.valueOf(TimeUnit.class, timeUnitStr.toUpperCase()); - } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/KSQLWindow.java b/src/main/java/net/sf/jsqlparser/statement/select/KSQLWindow.java index 79d0b5492..12b98d0f8 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/KSQLWindow.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/KSQLWindow.java @@ -13,32 +13,6 @@ public class KSQLWindow extends ASTNodeAccessImpl { - public enum TimeUnit { - DAY, HOUR, MINUTE, SECOND, MILLISECOND, DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS; - - public static TimeUnit from(String unit) { - return Enum.valueOf(TimeUnit.class, unit.toUpperCase()); - } - } - - public enum WindowType { - HOPPING("HOPPING"), SESSION("SESSION"), TUMBLING("TUMBLING"); - - private String windowType; - - WindowType(String windowType) { - this.windowType = windowType; - } - - public String getWindowType() { - return windowType; - } - - public static WindowType from(String type) { - return Enum.valueOf(WindowType.class, type.toUpperCase()); - } - } - private boolean hopping; private boolean tumbling; private boolean session; @@ -47,6 +21,8 @@ public static WindowType from(String type) { private long advanceDuration; private TimeUnit advanceTimeUnit; + public KSQLWindow() {} + public boolean isHoppingWindow() { return hopping; } @@ -103,8 +79,6 @@ public void setAdvanceTimeUnit(TimeUnit advanceTimeUnit) { this.advanceTimeUnit = advanceTimeUnit; } - public KSQLWindow() {} - @Override public String toString() { if (isHoppingWindow()) { @@ -137,4 +111,30 @@ public KSQLWindow withAdvanceTimeUnit(TimeUnit advanceTimeUnit) { return this; } + public enum TimeUnit { + DAY, HOUR, MINUTE, SECOND, MILLISECOND, DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS; + + public static TimeUnit from(String unit) { + return Enum.valueOf(TimeUnit.class, unit.toUpperCase()); + } + } + + public enum WindowType { + HOPPING("HOPPING"), SESSION("SESSION"), TUMBLING("TUMBLING"); + + private String windowType; + + WindowType(String windowType) { + this.windowType = windowType; + } + + public static WindowType from(String type) { + return Enum.valueOf(WindowType.class, type.toUpperCase()); + } + + public String getWindowType() { + return windowType; + } + } + } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/LateralSubSelect.java b/src/main/java/net/sf/jsqlparser/statement/select/LateralSubSelect.java index 23592d6db..736a6c8c0 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/LateralSubSelect.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/LateralSubSelect.java @@ -9,9 +9,11 @@ */ package net.sf.jsqlparser.statement.select; +import net.sf.jsqlparser.expression.Alias; + /** * lateral sub select - * + * * @author tobens */ public class LateralSubSelect extends ParenthesedSelect { @@ -22,7 +24,21 @@ public LateralSubSelect() { } public LateralSubSelect(String prefix) { + this(prefix, null, null); + } + + public LateralSubSelect(String prefix, Select select) { + this(prefix, select, null); + } + + public LateralSubSelect(Select select, Alias alias) { + this("LATERAL", select, alias); + } + + public LateralSubSelect(String prefix, Select select, Alias alias) { this.prefix = prefix; + this.select = select; + this.alias = alias; } public String getPrefix() { @@ -43,16 +59,22 @@ public LateralSubSelect withSelect(Select select) { return this; } + public LateralSubSelect withAlias(Alias alias) { + setAlias(alias); + return this; + } + public String toString() { return prefix + super.toString(); } - public void accept(SelectVisitor selectVisitor) { - selectVisitor.visit(this); + @Override + public T accept(SelectVisitor selectVisitor, S context) { + return selectVisitor.visit(this, context); } @Override - public void accept(FromItemVisitor fromItemVisitor) { - fromItemVisitor.visit(this); + public T accept(FromItemVisitor fromItemVisitor, S context) { + return fromItemVisitor.visit(this, context); } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Limit.java b/src/main/java/net/sf/jsqlparser/statement/select/Limit.java index 0c39bde05..9257daa6d 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Limit.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Limit.java @@ -25,7 +25,7 @@ public class Limit extends ASTNodeAccessImpl { /** * A query with the LIMIT n BY expressions clause selects the first n rows for each distinct * value of expressions. The key for LIMIT BY can contain any number of expressions. - * + * * @see ClickHouse * LIMIT BY Clause @@ -36,14 +36,14 @@ public Expression getOffset() { return offset; } - public Expression getRowCount() { - return rowCount; - } - public void setOffset(Expression l) { offset = l; } + public Expression getRowCount() { + return rowCount; + } + public void setRowCount(Expression l) { rowCount = l; } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/MySqlSqlCacheFlags.java b/src/main/java/net/sf/jsqlparser/statement/select/MySqlSqlCacheFlags.java index de7ba026e..1656e302a 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/MySqlSqlCacheFlags.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/MySqlSqlCacheFlags.java @@ -10,7 +10,6 @@ package net.sf.jsqlparser.statement.select; /** - * * @author tw */ public enum MySqlSqlCacheFlags { diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Offset.java b/src/main/java/net/sf/jsqlparser/statement/select/Offset.java index c9b1337e7..eeb354a3f 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Offset.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Offset.java @@ -21,14 +21,14 @@ public Expression getOffset() { return offsetExpression; } - public String getOffsetParam() { - return offsetParam; - } - public void setOffset(Expression offsetExpression) { this.offsetExpression = offsetExpression; } + public String getOffsetParam() { + return offsetParam; + } + public void setOffsetParam(String s) { offsetParam = s; } @@ -36,7 +36,7 @@ public void setOffsetParam(String s) { @Override public String toString() { - return " OFFSET " + offsetExpression + (offsetParam != null ? " " + offsetParam : ""); + return " OFFSET " + offsetExpression + (offsetParam != null ? " " + offsetParam : ""); } public Offset withOffset(Expression offsetExpression) { diff --git a/src/main/java/net/sf/jsqlparser/statement/select/OrderByElement.java b/src/main/java/net/sf/jsqlparser/statement/select/OrderByElement.java index 36597fde4..8ac4de9fd 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/OrderByElement.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/OrderByElement.java @@ -10,18 +10,11 @@ package net.sf.jsqlparser.statement.select; import java.io.Serializable; + import net.sf.jsqlparser.expression.Expression; public class OrderByElement implements Serializable { - public enum NullOrdering { - NULLS_FIRST, NULLS_LAST; - - public static NullOrdering from(String ordering) { - return Enum.valueOf(NullOrdering.class, ordering.toUpperCase()); - } - } - private Expression expression; // postgres rollup is an ExpressionList private boolean mysqlWithRollup = false; @@ -33,6 +26,10 @@ public boolean isAsc() { return asc; } + public void setAsc(boolean asc) { + this.asc = asc; + } + public NullOrdering getNullOrdering() { return nullOrdering; } @@ -41,20 +38,16 @@ public void setNullOrdering(NullOrdering nullOrdering) { this.nullOrdering = nullOrdering; } - public void setAsc(boolean asc) { - this.asc = asc; + public boolean isAscDescPresent() { + return ascDescPresent; } public void setAscDescPresent(boolean ascDescPresent) { this.ascDescPresent = ascDescPresent; } - public boolean isAscDescPresent() { - return ascDescPresent; - } - - public void accept(OrderByVisitor orderByVisitor) { - orderByVisitor.visit(this); + public T accept(OrderByVisitor orderByVisitor, S context) { + return orderByVisitor.visit(this, context); } public Expression getExpression() { @@ -119,4 +112,12 @@ public OrderByElement setMysqlWithRollup(boolean mysqlWithRollup) { return this; } + public enum NullOrdering { + NULLS_FIRST, NULLS_LAST; + + public static NullOrdering from(String ordering) { + return Enum.valueOf(NullOrdering.class, ordering.toUpperCase()); + } + } + } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/OrderByVisitor.java b/src/main/java/net/sf/jsqlparser/statement/select/OrderByVisitor.java index e54b8fc0a..8b43f7c26 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/OrderByVisitor.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/OrderByVisitor.java @@ -9,7 +9,11 @@ */ package net.sf.jsqlparser.statement.select; -public interface OrderByVisitor { +public interface OrderByVisitor { - void visit(OrderByElement orderBy); + T visit(OrderByElement orderBy, S context); + + default void visit(OrderByElement orderBy) { + this.visit(orderBy, null); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/OrderByVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/statement/select/OrderByVisitorAdapter.java index a22396334..2ab0a50e3 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/OrderByVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/OrderByVisitorAdapter.java @@ -10,10 +10,10 @@ package net.sf.jsqlparser.statement.select; @SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) -public class OrderByVisitorAdapter implements OrderByVisitor { +public class OrderByVisitorAdapter implements OrderByVisitor { @Override - public void visit(OrderByElement orderBy) { - + public T visit(OrderByElement orderBy, S context) { + return null; } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedFromItem.java b/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedFromItem.java index ae4312319..2e4c44e28 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedFromItem.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedFromItem.java @@ -10,13 +10,14 @@ package net.sf.jsqlparser.statement.select; import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; -public class ParenthesedFromItem implements FromItem { +public class ParenthesedFromItem extends ASTNodeAccessImpl implements FromItem { private FromItem fromItem; private List joins; private Alias alias; @@ -41,6 +42,10 @@ public List getJoins() { return joins; } + public void setJoins(List list) { + joins = list; + } + public Join getJoin(int index) { return joins.get(index); } @@ -56,13 +61,9 @@ public FromItem withJoins(List joins) { return this; } - public void setJoins(List list) { - joins = list; - } - @Override - public void accept(FromItemVisitor fromItemVisitor) { - fromItemVisitor.visit(this); + public T accept(FromItemVisitor fromItemVisitor, S context) { + return fromItemVisitor.visit(this, context); } public StringBuilder appendTo(StringBuilder builder) { diff --git a/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java b/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java index 5bbf8391d..0fc99972e 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java @@ -10,6 +10,11 @@ package net.sf.jsqlparser.statement.select; import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.schema.Table; + +import java.util.Collection; +import java.util.List; public class ParenthesedSelect extends Select implements FromItem { Alias alias; @@ -17,6 +22,62 @@ public class ParenthesedSelect extends Select implements FromItem { UnPivot unPivot; Select select; + public ParenthesedSelect() {} + + public ParenthesedSelect(FromItem fromItem) { + this.select = new PlainSelect(fromItem); + this.alias = getAliasFromItem(fromItem); + } + + public ParenthesedSelect(FromItem fromItem, Expression whereExpressions) { + this.select = new PlainSelect(fromItem, whereExpressions); + this.alias = getAliasFromItem(fromItem); + } + + public ParenthesedSelect(FromItem fromItem, Collection orderByExpressions) { + this.select = new PlainSelect(fromItem, orderByExpressions); + this.alias = getAliasFromItem(fromItem); + } + + public ParenthesedSelect(FromItem fromItem, Expression whereExpressions, + Collection orderByExpressions) { + this.select = new PlainSelect(fromItem, whereExpressions, orderByExpressions); + this.alias = getAliasFromItem(fromItem); + } + + public ParenthesedSelect(Collection selectExpressions, FromItem fromItem) { + this.select = new PlainSelect(selectExpressions, fromItem); + this.alias = getAliasFromItem(fromItem); + } + + public ParenthesedSelect(Collection selectExpressions, FromItem fromItem, + Expression whereExpressions) { + this.select = new PlainSelect(selectExpressions, fromItem, whereExpressions); + this.alias = getAliasFromItem(fromItem); + } + + public ParenthesedSelect(Collection selectExpressions, FromItem fromItem, + Collection orderByExpressions) { + this.select = new PlainSelect(selectExpressions, fromItem, orderByExpressions); + this.alias = getAliasFromItem(fromItem); + } + + public ParenthesedSelect(Collection selectExpressions, FromItem fromItem, + Expression whereExpressions, Collection orderByExpressions) { + this.select = + new PlainSelect(selectExpressions, fromItem, whereExpressions, orderByExpressions); + this.alias = getAliasFromItem(fromItem); + } + + private static Alias getAliasFromItem(FromItem fromItem) { + if (fromItem instanceof Table && fromItem.getAlias() == null) { + Table t = (Table) fromItem; + return new Alias(t.getName(), true); + } else { + return new Alias(fromItem.getAlias().getName(), true); + } + } + @Override public Alias getAlias() { return alias; @@ -54,6 +115,10 @@ public Select getSelect() { return select; } + public void setSelect(Select select) { + this.select = select; + } + public Values getValues() { return (Values) select; } @@ -66,23 +131,24 @@ public SetOperationList getSetOperationList() { return (SetOperationList) select; } - public void setSelect(Select select) { - this.select = select; - } - public ParenthesedSelect withSelect(Select selectBody) { setSelect(selectBody); return this; } + public ParenthesedSelect withOrderByElements(List orderByElements) { + this.select.setOrderByElements(orderByElements); + return this; + } + @Override - public void accept(SelectVisitor selectVisitor) { - selectVisitor.visit(this); + public T accept(SelectVisitor selectVisitor, S context) { + return selectVisitor.visit(this, context); } @Override - public void accept(FromItemVisitor fromItemVisitor) { - fromItemVisitor.visit(this); + public T accept(FromItemVisitor fromItemVisitor, S context) { + return fromItemVisitor.visit(this, context); } public StringBuilder appendSelectBodyTo(StringBuilder builder) { diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Pivot.java b/src/main/java/net/sf/jsqlparser/statement/select/Pivot.java index fd6f43035..87d20dbee 100755 --- a/src/main/java/net/sf/jsqlparser/statement/select/Pivot.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Pivot.java @@ -27,11 +27,11 @@ public class Pivot implements Serializable { private List> functionItems; private ExpressionList forColumns; private List> singleInItems; - private List> multiInItems; + private List>> multiInItems; private Alias alias; - public void accept(PivotVisitor pivotVisitor) { - pivotVisitor.visit(this); + public T accept(PivotVisitor pivotVisitor, S context) { + return pivotVisitor.visit(this, context); } public List> getSingleInItems() { @@ -42,11 +42,11 @@ public void setSingleInItems(List> singleInItems) { this.singleInItems = singleInItems; } - public List> getMultiInItems() { + public List>> getMultiInItems() { return multiInItems; } - public void setMultiInItems(List> multiInItems) { + public void setMultiInItems(List>> multiInItems) { this.multiInItems = multiInItems; } @@ -104,7 +104,7 @@ public Pivot withSingleInItems(List> singleInItems) { return this; } - public Pivot withMultiInItems(List> multiInItems) { + public Pivot withMultiInItems(List>> multiInItems) { this.setMultiInItems(multiInItems); return this; } @@ -153,15 +153,15 @@ public Pivot addSingleInItems(Collection> singleInItems) return this.withSingleInItems(collection); } - public Pivot addMultiInItems(SelectItem... multiInItems) { - List> collection = + public Pivot addMultiInItems(SelectItem>... multiInItems) { + List>> collection = Optional.ofNullable(getMultiInItems()).orElseGet(ArrayList::new); Collections.addAll(collection, multiInItems); return this.withMultiInItems(collection); } - public Pivot addMultiInItems(Collection> multiInItems) { - List> collection = + public Pivot addMultiInItems(Collection>> multiInItems) { + List>> collection = Optional.ofNullable(getMultiInItems()).orElseGet(ArrayList::new); collection.addAll(multiInItems); return this.withMultiInItems(collection); diff --git a/src/main/java/net/sf/jsqlparser/statement/select/PivotVisitor.java b/src/main/java/net/sf/jsqlparser/statement/select/PivotVisitor.java index e348aa9d8..27069423e 100755 --- a/src/main/java/net/sf/jsqlparser/statement/select/PivotVisitor.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/PivotVisitor.java @@ -9,12 +9,23 @@ */ package net.sf.jsqlparser.statement.select; -public interface PivotVisitor { +public interface PivotVisitor { - void visit(Pivot pivot); + T visit(Pivot pivot, S context); - void visit(PivotXml pivot); + default void visit(Pivot pivot) { + this.visit(pivot, null); + } - void visit(UnPivot unpivot); + T visit(PivotXml pivotXml, S context); + default void visit(PivotXml pivotXml) { + this.visit(pivotXml, null); + } + + T visit(UnPivot unpivot, S context); + + default void visit(UnPivot unpivot) { + this.visit(unpivot, null); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/PivotVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/statement/select/PivotVisitorAdapter.java index b988e2e6a..6e7fce93f 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/PivotVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/PivotVisitorAdapter.java @@ -10,20 +10,23 @@ package net.sf.jsqlparser.statement.select; @SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) -public class PivotVisitorAdapter implements PivotVisitor { +public class PivotVisitorAdapter implements PivotVisitor { @Override - public void visit(Pivot pivot) { + public T visit(Pivot pivot, S context) { + return null; } @Override - public void visit(PivotXml pivot) { + public T visit(PivotXml pivot, S context) { + return null; } @Override - public void visit(UnPivot unpivot) { + public T visit(UnPivot unpivot, S context) { + return null; } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/PivotXml.java b/src/main/java/net/sf/jsqlparser/statement/select/PivotXml.java index 0c6929c40..b016d79dd 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/PivotXml.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/PivotXml.java @@ -23,8 +23,8 @@ public class PivotXml extends Pivot { private boolean inAny = false; @Override - public void accept(PivotVisitor pivotVisitor) { - pivotVisitor.visit(this); + public T accept(PivotVisitor pivotVisitor, S context) { + return pivotVisitor.visit(this, context); } public Select getInSelect() { @@ -91,7 +91,7 @@ public PivotXml withSingleInItems(List> singleInItems) { } @Override - public PivotXml withMultiInItems(List> multiInItems) { + public PivotXml withMultiInItems(List>> multiInItems) { return (PivotXml) super.withMultiInItems(multiInItems); } @@ -126,12 +126,13 @@ public PivotXml addSingleInItems(SelectItem... singleInItems) { } @Override - public PivotXml addMultiInItems(SelectItem... multiInItems) { + public PivotXml addMultiInItems(SelectItem>... multiInItems) { return (PivotXml) super.addMultiInItems(multiInItems); } @Override - public PivotXml addMultiInItems(Collection> multiInItems) { + public PivotXml addMultiInItems( + Collection>> multiInItems) { return (PivotXml) super.addMultiInItems(multiInItems); } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java b/src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java index 2745dae6d..eb106869c 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java @@ -9,7 +9,12 @@ */ package net.sf.jsqlparser.statement.select; -import static java.util.stream.Collectors.joining; +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.OracleHierarchicalExpression; +import net.sf.jsqlparser.expression.OracleHint; +import net.sf.jsqlparser.expression.WindowDefinition; +import net.sf.jsqlparser.schema.Table; import java.util.ArrayList; import java.util.Arrays; @@ -18,17 +23,14 @@ import java.util.Iterator; import java.util.List; import java.util.Optional; -import net.sf.jsqlparser.expression.Alias; -import net.sf.jsqlparser.expression.Expression; -import net.sf.jsqlparser.expression.OracleHierarchicalExpression; -import net.sf.jsqlparser.expression.OracleHint; -import net.sf.jsqlparser.expression.WindowDefinition; -import net.sf.jsqlparser.schema.Table; + +import static java.util.stream.Collectors.joining; @SuppressWarnings({"PMD.CyclomaticComplexity"}) public class PlainSelect extends Select { private Distinct distinct = null; + private BigQuerySelectQualifier bigQuerySelectQualifier = null; private List> selectItems; private List

intoTables; private FromItem fromItem; @@ -45,32 +47,76 @@ public class PlainSelect extends Select { private Top top; private OracleHierarchicalExpression oracleHierarchical = null; private OracleHint oracleHint = null; - private ForMode forMode = null; - private Table forUpdateTable = null; - private boolean skipLocked; - private Wait wait; private boolean mySqlSqlCalcFoundRows = false; private MySqlSqlCacheFlags mySqlCacheFlag = null; private String forXmlPath; private KSQLWindow ksqlWindow = null; - private boolean noWait = false; private boolean emitChanges = false; - private List windowDefinitions; - /** * @see Clickhouse * FINAL */ private boolean isUsingFinal = false; - private boolean isUsingOnly = false; - private boolean useWithNoLog = false; - private Table intoTempTable = null; + public PlainSelect() {} + + public PlainSelect(FromItem fromItem) { + addSelectItem(new AllColumns()); + setFromItem(fromItem); + } + + public PlainSelect(FromItem fromItem, Expression whereExpressions) { + addSelectItem(new AllColumns()); + setFromItem(fromItem); + setWhere(whereExpressions); + } + + public PlainSelect(FromItem fromItem, Collection orderByExpressions) { + addSelectItem(new AllColumns()); + setFromItem(fromItem); + addOrderByExpressions(orderByExpressions); + } + + public PlainSelect(FromItem fromItem, Expression whereExpressions, + Collection orderByExpressions) { + addSelectItem(new AllColumns()); + setFromItem(fromItem); + setWhere(whereExpressions); + addOrderByExpressions(orderByExpressions); + } + + public PlainSelect(Collection selectExpressions, FromItem fromItem) { + addSelectExpressions(selectExpressions); + setFromItem(fromItem); + } + + public PlainSelect(Collection selectExpressions, FromItem fromItem, + Expression whereExpressions) { + addSelectExpressions(selectExpressions); + setFromItem(fromItem); + setWhere(whereExpressions); + } + + public PlainSelect(Collection selectExpressions, FromItem fromItem, + Collection orderByExpressions) { + addSelectExpressions(selectExpressions); + setFromItem(fromItem); + addOrderByExpressions(orderByExpressions); + } + + public PlainSelect(Collection selectExpressions, FromItem fromItem, + Expression whereExpressions, Collection orderByExpressions) { + addSelectExpressions(selectExpressions); + setFromItem(fromItem); + setWhere(whereExpressions); + addOrderByExpressions(orderByExpressions); + } + @Deprecated public boolean isUseBrackets() { return false; @@ -80,14 +126,26 @@ public FromItem getFromItem() { return fromItem; } + public void setFromItem(FromItem item) { + fromItem = item; + } + public List
getIntoTables() { return intoTables; } + public void setIntoTables(List
intoTables) { + this.intoTables = intoTables; + } + public List> getSelectItems() { return selectItems; } + public void setSelectItems(List> list) { + selectItems = list; + } + public SelectItem getSelectItem(int index) { return selectItems.get(index); } @@ -96,26 +154,22 @@ public Expression getWhere() { return where; } + public void setWhere(Expression where) { + this.where = where; + } + public PlainSelect withFromItem(FromItem item) { this.setFromItem(item); return this; } - public void setFromItem(FromItem item) { - fromItem = item; - } - - public void setIntoTables(List
intoTables) { - this.intoTables = intoTables; - } - public PlainSelect withSelectItems(List> list) { this.setSelectItems(list); return this; } - public void setSelectItems(List> list) { - selectItems = list; + public PlainSelect withSelectItems(SelectItem... selectItems) { + return this.withSelectItems(Arrays.asList(selectItems)); } public PlainSelect addSelectItems(SelectItem... items) { @@ -124,7 +178,7 @@ public PlainSelect addSelectItems(SelectItem... items) { return this; } - public PlainSelect addSelectItems(Expression... expressions) { + public PlainSelect addSelectExpressions(Collection expressions) { selectItems = Optional.ofNullable(selectItems).orElseGet(ArrayList::new); for (Expression expression : expressions) { selectItems.add(SelectItem.from(expression)); @@ -132,6 +186,10 @@ public PlainSelect addSelectItems(Expression... expressions) { return this; } + public PlainSelect addSelectItems(Expression... expressions) { + return this.addSelectExpressions(Arrays.asList(expressions)); + } + public PlainSelect addSelectItem(Expression expression, Alias alias) { selectItems = Optional.ofNullable(selectItems).orElseGet(ArrayList::new); selectItems.add(new SelectItem<>(expression, alias)); @@ -142,10 +200,6 @@ public PlainSelect addSelectItem(Expression expression) { return addSelectItem(expression, null); } - public void setWhere(Expression where) { - this.where = where; - } - public List getLateralViews() { return lateralViews; } @@ -187,6 +241,10 @@ public List getJoins() { return joins; } + public void setJoins(List list) { + joins = list; + } + public Join getJoin(int index) { return joins.get(index); } @@ -202,10 +260,6 @@ public PlainSelect withJoins(List joins) { return this; } - public void setJoins(List list) { - joins = list; - } - public boolean isUsingFinal() { return isUsingFinal; } @@ -259,8 +313,8 @@ public PlainSelect withIntoTempTable(Table intoTempTable) { } @Override - public void accept(SelectVisitor selectVisitor) { - selectVisitor.visit(this); + public T accept(SelectVisitor selectVisitor, S context) { + return selectVisitor.visit(this, context); } public OptimizeFor getOptimizeFor() { @@ -311,6 +365,15 @@ public void setDistinct(Distinct distinct) { this.distinct = distinct; } + public BigQuerySelectQualifier getBigQuerySelectQualifier() { + return bigQuerySelectQualifier; + } + + public PlainSelect setBigQuerySelectQualifier(BigQuerySelectQualifier bigQuerySelectQualifier) { + this.bigQuerySelectQualifier = bigQuerySelectQualifier; + return this; + } + public Expression getHaving() { return having; } @@ -356,22 +419,6 @@ public void setOracleHierarchical(OracleHierarchicalExpression oracleHierarchica this.oracleHierarchical = oracleHierarchical; } - public ForMode getForMode() { - return forMode; - } - - public void setForMode(ForMode forMode) { - this.forMode = forMode; - } - - public Table getForUpdateTable() { - return forUpdateTable; - } - - public void setForUpdateTable(Table forUpdateTable) { - this.forUpdateTable = forUpdateTable; - } - public OracleHint getOracleHint() { return oracleHint; } @@ -380,24 +427,6 @@ public void setOracleHint(OracleHint oracleHint) { this.oracleHint = oracleHint; } - /** - * Sets the {@link Wait} for this SELECT - * - * @param wait the {@link Wait} for this SELECT - */ - public void setWait(final Wait wait) { - this.wait = wait; - } - - /** - * Returns the value of the {@link Wait} set for this SELECT - * - * @return the value of the {@link Wait} set for this SELECT - */ - public Wait getWait() { - return wait; - } - public String getForXmlPath() { return forXmlPath; } @@ -414,14 +443,14 @@ public void setKsqlWindow(KSQLWindow ksqlWindow) { this.ksqlWindow = ksqlWindow; } - public void setEmitChanges(boolean emitChanges) { - this.emitChanges = emitChanges; - } - public boolean isEmitChanges() { return emitChanges; } + public void setEmitChanges(boolean emitChanges) { + this.emitChanges = emitChanges; + } + public List getWindowDefinitions() { return windowDefinitions; } @@ -430,14 +459,6 @@ public void setWindowDefinitions(List windowDefinitions) { this.windowDefinitions = windowDefinitions; } - public boolean isSkipLocked() { - return skipLocked; - } - - public void setSkipLocked(boolean skipLocked) { - this.skipLocked = skipLocked; - } - @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.ExcessiveMethodLength", "PMD.NPathComplexity"}) public StringBuilder appendSelectBodyTo(StringBuilder builder) { @@ -462,6 +483,18 @@ public StringBuilder appendSelectBodyTo(StringBuilder builder) { if (distinct != null) { builder.append(distinct).append(" "); } + + if (bigQuerySelectQualifier != null) { + switch (bigQuerySelectQualifier) { + case AS_STRUCT: + builder.append("AS STRUCT "); + break; + case AS_VALUE: + builder.append("AS VALUE "); + break; + } + } + if (top != null) { builder.append(top).append(" "); } @@ -534,25 +567,6 @@ public StringBuilder appendSelectBodyTo(StringBuilder builder) { if (emitChanges) { builder.append(" EMIT CHANGES"); } - if (getForMode() != null) { - builder.append(" FOR "); - builder.append(getForMode().getValue()); - - if (forUpdateTable != null) { - builder.append(" OF ").append(forUpdateTable); - } - - if (wait != null) { - // Wait's toString will do the formatting for us - builder.append(wait); - } - - if (isNoWait()) { - builder.append(" NOWAIT"); - } else if (isSkipLocked()) { - builder.append(" SKIP LOCKED"); - } - } } else { // without from if (where != null) { @@ -596,28 +610,20 @@ public PlainSelect withMySqlSqlNoCache(MySqlSqlCacheFlags mySqlCacheFlag) { return this; } - public void setMySqlSqlCalcFoundRows(boolean mySqlCalcFoundRows) { - this.mySqlSqlCalcFoundRows = mySqlCalcFoundRows; - } - - public void setMySqlSqlCacheFlag(MySqlSqlCacheFlags sqlCacheFlag) { - this.mySqlCacheFlag = sqlCacheFlag; - } - public boolean getMySqlSqlCalcFoundRows() { return this.mySqlSqlCalcFoundRows; } - public MySqlSqlCacheFlags getMySqlSqlCacheFlag() { - return this.mySqlCacheFlag; + public void setMySqlSqlCalcFoundRows(boolean mySqlCalcFoundRows) { + this.mySqlSqlCalcFoundRows = mySqlCalcFoundRows; } - public void setNoWait(boolean noWait) { - this.noWait = noWait; + public MySqlSqlCacheFlags getMySqlSqlCacheFlag() { + return this.mySqlCacheFlag; } - public boolean isNoWait() { - return this.noWait; + public void setMySqlSqlCacheFlag(MySqlSqlCacheFlags sqlCacheFlag) { + this.mySqlCacheFlag = sqlCacheFlag; } public PlainSelect withDistinct(Distinct distinct) { @@ -675,16 +681,6 @@ public PlainSelect withOracleSiblings(boolean oracleSiblings) { return this; } - public PlainSelect withForMode(ForMode forMode) { - this.setForMode(forMode); - return this; - } - - public PlainSelect withForUpdateTable(Table forUpdateTable) { - this.setForUpdateTable(forUpdateTable); - return this; - } - public PlainSelect withForXmlPath(String forXmlPath) { this.setForXmlPath(forXmlPath); return this; @@ -700,21 +696,11 @@ public PlainSelect withNoWait(boolean noWait) { return this; } - public PlainSelect withSkipLocked(boolean skipLocked) { - this.setSkipLocked(skipLocked); - return this; - } - public PlainSelect withHaving(Expression having) { this.setHaving(having); return this; } - public PlainSelect withWait(Wait wait) { - this.setWait(wait); - return this; - } - public PlainSelect addSelectItems(Collection> selectItems) { List> collection = Optional.ofNullable(getSelectItems()).orElseGet(ArrayList::new); @@ -751,4 +737,8 @@ public E getWhere(Class type) { public E getHaving(Class type) { return type.cast(getHaving()); } + + public enum BigQuerySelectQualifier { + AS_STRUCT, AS_VALUE + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SampleClause.java b/src/main/java/net/sf/jsqlparser/statement/select/SampleClause.java index ea15a5921..8aeea8d50 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SampleClause.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SampleClause.java @@ -10,27 +10,10 @@ package net.sf.jsqlparser.statement.select; public class SampleClause { - public enum SampleKeyword { - SAMPLE, TABLESAMPLE; - - public static SampleKeyword from(String sampleKeyword) { - return Enum.valueOf(SampleKeyword.class, sampleKeyword.toUpperCase()); - } - } - - public enum SampleMethod { - BERNOULLI, SYSTEM, BLOCK; - - public static SampleMethod from(String sampleMethod) { - return Enum.valueOf(SampleMethod.class, sampleMethod.toUpperCase()); - } - } - private SampleKeyword keyword; private SampleMethod method; private Number percentageArgument; private Number repeatArgument; - // Oracle Specific private Number seedArgument; @@ -126,4 +109,20 @@ public StringBuilder appendTo(StringBuilder builder) { public String toString() { return appendTo(new StringBuilder()).toString(); } + + public enum SampleKeyword { + SAMPLE, TABLESAMPLE; + + public static SampleKeyword from(String sampleKeyword) { + return Enum.valueOf(SampleKeyword.class, sampleKeyword.toUpperCase()); + } + } + + public enum SampleMethod { + BERNOULLI, SYSTEM, BLOCK; + + public static SampleMethod from(String sampleMethod) { + return Enum.valueOf(SampleMethod.class, sampleMethod.toUpperCase()); + } + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Select.java b/src/main/java/net/sf/jsqlparser/statement/select/Select.java index 2216fada9..e6cc7393a 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Select.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Select.java @@ -12,6 +12,7 @@ import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; @@ -23,6 +24,7 @@ import java.util.Optional; public abstract class Select extends ASTNodeAccessImpl implements Statement, Expression { + protected Table forUpdateTable = null; List withItemsList; Limit limitBy; Limit limit; @@ -34,6 +36,10 @@ public abstract class Select extends ASTNodeAccessImpl implements Statement, Exp ForClause forClause = null; List orderByElements; + ForMode forMode = null; + private boolean skipLocked; + private Wait wait; + private boolean noWait = false; public static String orderByToString(List orderByElements) { return orderByToString(false, orderByElements); @@ -52,8 +58,8 @@ public static String getFormattedList(List list, String expression, boolean u boolean useBrackets) { String sql = getStringList(list, useComma, useBrackets); - if (sql.length() > 0) { - if (expression.length() > 0) { + if (!sql.isEmpty()) { + if (!expression.isEmpty()) { sql = " " + expression + " " + sql; } else { sql = " " + sql; @@ -69,9 +75,9 @@ public static String getFormattedList(List list, String expression, boolean u *

* The same as getStringList(list, true, false) * - * @see #getStringList(List, boolean, boolean) * @param list list of objects with toString methods * @return comma separated list of the elements in the list + * @see #getStringList(List, boolean, boolean) */ public static String getStringList(List list) { return getStringList(list, true, false); @@ -152,6 +158,14 @@ public void setOracleSiblings(boolean oracleSiblings) { this.oracleSiblings = oracleSiblings; } + public boolean isNoWait() { + return this.noWait; + } + + public void setNoWait(boolean noWait) { + this.noWait = noWait; + } + public Select withOracleSiblings(boolean oracleSiblings) { this.setOracleSiblings(oracleSiblings); return this; @@ -187,7 +201,18 @@ public Select addOrderByElements(Collection orderByEle } public Select addOrderByElements(OrderByElement... orderByElements) { - return addOrderByElements(Arrays.asList(orderByElements)); + return this.addOrderByElements(Arrays.asList(orderByElements)); + } + + public Select addOrderByExpressions(Collection orderByExpressions) { + for (Expression e : orderByExpressions) { + addOrderByElements(new OrderByElement().withExpression(e)); + } + return this; + } + + public Select addOrderByElements(Expression... orderByExpressions) { + return addOrderByExpressions(Arrays.asList(orderByExpressions)); } public Limit getLimit() { @@ -255,6 +280,48 @@ public Select withIsolation(WithIsolation isolation) { return this; } + public ForMode getForMode() { + return this.forMode; + } + + public void setForMode(ForMode forMode) { + this.forMode = forMode; + } + + public Table getForUpdateTable() { + return this.forUpdateTable; + } + + public void setForUpdateTable(Table forUpdateTable) { + this.forUpdateTable = forUpdateTable; + } + + /** + * Returns the value of the {@link Wait} set for this SELECT + * + * @return the value of the {@link Wait} set for this SELECT + */ + public Wait getWait() { + return wait; + } + + /** + * Sets the {@link Wait} for this SELECT + * + * @param wait the {@link Wait} for this SELECT + */ + public void setWait(final Wait wait) { + this.wait = wait; + } + + public boolean isSkipLocked() { + return skipLocked; + } + + public void setSkipLocked(boolean skipLocked) { + this.skipLocked = skipLocked; + } + public abstract StringBuilder appendSelectBodyTo(StringBuilder builder); @SuppressWarnings({"PMD.CyclomaticComplexity"}) @@ -294,6 +361,25 @@ public StringBuilder appendTo(StringBuilder builder) { if (isolation != null) { builder.append(isolation); } + if (forMode != null) { + builder.append(" FOR "); + builder.append(forMode.getValue()); + + if (getForUpdateTable() != null) { + builder.append(" OF ").append(forUpdateTable); + } + + if (wait != null) { + // Wait's toString will do the formatting for us + builder.append(wait); + } + + if (isNoWait()) { + builder.append(" NOWAIT"); + } else if (isSkipLocked()) { + builder.append(" SKIP LOCKED"); + } + } return builder; } @@ -303,15 +389,15 @@ public String toString() { return appendTo(new StringBuilder()).toString(); } - public abstract void accept(SelectVisitor selectVisitor); + public abstract T accept(SelectVisitor selectVisitor, S context); - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(this); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); } @Deprecated @@ -334,4 +420,24 @@ public SetOperationList getSetOperationList() { public E as(Class type) { return type.cast(this); } + + public Select withForMode(ForMode forMode) { + this.setForMode(forMode); + return this; + } + + public Select withForUpdateTable(Table forUpdateTable) { + this.setForUpdateTable(forUpdateTable); + return this; + } + + public Select withSkipLocked(boolean skipLocked) { + this.setSkipLocked(skipLocked); + return this; + } + + public Select withWait(Wait wait) { + this.setWait(wait); + return this; + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SelectItem.java b/src/main/java/net/sf/jsqlparser/statement/select/SelectItem.java index 30422122e..4f8112d17 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SelectItem.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SelectItem.java @@ -10,7 +10,10 @@ package net.sf.jsqlparser.statement.select; import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.expression.DoubleValue; import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.LongValue; +import net.sf.jsqlparser.expression.StringValue; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; public class SelectItem extends ASTNodeAccessImpl { @@ -23,12 +26,33 @@ public SelectItem(T expression, Alias alias) { this.alias = alias; } + public SelectItem(T expression, String aliasName) { + this.expression = expression; + this.alias = new Alias(aliasName); + } + + public SelectItem(Long expression, String aliasName) { + this((T) new LongValue(expression), aliasName); + } + + public SelectItem(Integer expression, String aliasName) { + this((T) new LongValue(expression), aliasName); + } + + public SelectItem(Double expression, String aliasName) { + this((T) new DoubleValue(expression), aliasName); + } + + public SelectItem(String expression, String aliasName) { + this((T) new StringValue(expression), aliasName); + } + public SelectItem() { - this(null, null); + this(null, (Alias) null); } public SelectItem(T expression) { - this(expression, null); + this(expression, (Alias) null); } public static SelectItem from(Expression expression, Alias alias) { @@ -55,8 +79,8 @@ public void setExpression(T expression) { this.expression = expression; } - public void accept(SelectItemVisitor selectItemVisitor) { - selectItemVisitor.visit(this); + public K accept(SelectItemVisitor selectItemVisitor, S context) { + return selectItemVisitor.visit(this, context); } @Override diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitor.java b/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitor.java index 2f12539e2..9e23873d3 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitor.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitor.java @@ -9,6 +9,12 @@ */ package net.sf.jsqlparser.statement.select; -public interface SelectItemVisitor { - void visit(SelectItem selectItem); +import net.sf.jsqlparser.expression.Expression; + +public interface SelectItemVisitor { + T visit(SelectItem selectItem, S context); + + default void visit(SelectItem selectItem) { + this.visit(selectItem, null); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitorAdapter.java index eeb2d1b61..1fc7a2322 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SelectItemVisitorAdapter.java @@ -9,10 +9,12 @@ */ package net.sf.jsqlparser.statement.select; +import net.sf.jsqlparser.expression.Expression; + @SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) -public class SelectItemVisitorAdapter implements SelectItemVisitor { +public class SelectItemVisitorAdapter implements SelectItemVisitor { @Override - public void visit(SelectItem item) { - + public T visit(SelectItem item, S context) { + return null; } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitor.java b/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitor.java index 04a6b9d9e..d8ee278be 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitor.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitor.java @@ -9,19 +9,47 @@ */ package net.sf.jsqlparser.statement.select; -public interface SelectVisitor { +public interface SelectVisitor { - void visit(ParenthesedSelect parenthesedSelect); + T visit(ParenthesedSelect parenthesedSelect, S context); - void visit(PlainSelect plainSelect); + default void visit(ParenthesedSelect parenthesedSelect) { + this.visit(parenthesedSelect, null); + } - void visit(SetOperationList setOpList); + T visit(PlainSelect plainSelect, S context); - void visit(WithItem withItem); + default void visit(PlainSelect plainSelect) { + this.visit(plainSelect, null); + } - void visit(Values aThis); + T visit(SetOperationList setOpList, S context); - void visit(LateralSubSelect lateralSubSelect); + default void visit(SetOperationList setOpList) { + this.visit(setOpList, null); + } - void visit(TableStatement tableStatement); + T visit(WithItem withItem, S context); + + default void visit(WithItem withItem) { + this.visit(withItem, null); + } + + T visit(Values values, S context); + + default void visit(Values values) { + this.visit(values, null); + } + + T visit(LateralSubSelect lateralSubSelect, S context); + + default void visit(LateralSubSelect lateralSubSelect) { + this.visit(lateralSubSelect, null); + } + + T visit(TableStatement tableStatement, S context); + + default void visit(TableStatement tableStatement) { + this.visit(tableStatement, null); + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitorAdapter.java index a349a9005..5820fa864 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitorAdapter.java @@ -10,40 +10,40 @@ package net.sf.jsqlparser.statement.select; @SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) -public class SelectVisitorAdapter implements SelectVisitor { +public class SelectVisitorAdapter implements SelectVisitor { @Override - public void visit(ParenthesedSelect parenthesedSelect) { - parenthesedSelect.getSelect().accept(this); + public T visit(ParenthesedSelect parenthesedSelect, S context) { + return parenthesedSelect.getSelect().accept(this, context); } @Override - public void visit(PlainSelect plainSelect) { - + public T visit(PlainSelect plainSelect, S context) { + return null; } @Override - public void visit(SetOperationList setOpList) { - + public T visit(SetOperationList setOpList, S context) { + return null; } @Override - public void visit(WithItem withItem) { - + public T visit(WithItem withItem, S context) { + return null; } @Override - public void visit(Values aThis) { - + public T visit(Values aThis, S context) { + return null; } @Override - public void visit(LateralSubSelect lateralSubSelect) { - + public T visit(LateralSubSelect lateralSubSelect, S context) { + return null; } @Override - public void visit(TableStatement tableStatement) { - + public T visit(TableStatement tableStatement, S context) { + return null; } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SetOperationList.java b/src/main/java/net/sf/jsqlparser/statement/select/SetOperationList.java index 48a609240..46708e8c6 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SetOperationList.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SetOperationList.java @@ -9,6 +9,7 @@ */ package net.sf.jsqlparser.statement.select; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -22,40 +23,40 @@ public class SetOperationList extends Select { private List orderByElements; @Override - public void accept(SelectVisitor selectVisitor) { - selectVisitor.visit(this); + public T accept(SelectVisitor selectVisitor, S context) { + return selectVisitor.visit(this, context); } public List getOrderByElements() { return orderByElements; } - public List getSelects() { + return selects; } public void setSelects(List select, List ops) { diff --git a/src/main/java/net/sf/jsqlparser/statement/select/TableFunction.java b/src/main/java/net/sf/jsqlparser/statement/select/TableFunction.java index 44309b1a9..4f51179fc 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/TableFunction.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/TableFunction.java @@ -33,17 +33,16 @@ public Function getFunction() { return function; } - @Deprecated - public Function getExpression() { - return getFunction(); - } - - public TableFunction setFunction(Function function) { this.function = function; return this; } + @Deprecated + public Function getExpression() { + return getFunction(); + } + public String getPrefix() { return prefix; } @@ -54,8 +53,8 @@ public TableFunction setPrefix(String prefix) { } @Override - public void accept(FromItemVisitor fromItemVisitor) { - fromItemVisitor.visit(this); + public T accept(FromItemVisitor fromItemVisitor, S context) { + return fromItemVisitor.visit(this, context); } @Override diff --git a/src/main/java/net/sf/jsqlparser/statement/select/TableStatement.java b/src/main/java/net/sf/jsqlparser/statement/select/TableStatement.java index b665b16a6..0b1e081c9 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/TableStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/TableStatement.java @@ -12,10 +12,9 @@ import net.sf.jsqlparser.schema.Table; /** + * @author jxnu-liguobin * @see `TABLE table_name [ORDER * BY column_name] [LIMIT number [OFFSET number]]` Union not currently supported - * - * @author jxnu-liguobin */ public class TableStatement extends Select { @@ -53,7 +52,7 @@ public StringBuilder appendTo(StringBuilder builder) { } @Override - public void accept(SelectVisitor selectVisitor) { - selectVisitor.visit(this); + public T accept(SelectVisitor selectVisitor, S context) { + return selectVisitor.visit(this, context); } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Top.java b/src/main/java/net/sf/jsqlparser/statement/select/Top.java index ad57c2a56..dd4541124 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Top.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Top.java @@ -10,10 +10,11 @@ package net.sf.jsqlparser.statement.select; import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; import java.io.Serializable; -public class Top implements Serializable { +public class Top extends ASTNodeAccessImpl implements Serializable { private boolean hasParenthesis = false; private boolean isPercentage = false; @@ -44,14 +45,14 @@ public void setPercentage(boolean percentage) { this.isPercentage = percentage; } - public void setWithTies(boolean withTies) { - this.isWithTies = withTies; - } - public boolean isWithTies() { return isWithTies; } + public void setWithTies(boolean withTies) { + this.isWithTies = withTies; + } + @Override public String toString() { String result = "TOP "; @@ -85,4 +86,5 @@ public Top withExpression(Expression expression) { public E getExpression(Class type) { return type.cast(getExpression()); } + } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/UnPivot.java b/src/main/java/net/sf/jsqlparser/statement/select/UnPivot.java index 8d39f831e..c5549280c 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/UnPivot.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/UnPivot.java @@ -25,8 +25,8 @@ public class UnPivot implements Serializable { private List> unpivotInClause; private Alias alias; - public void accept(PivotVisitor pivotVisitor) { - pivotVisitor.visit(this); + public T accept(PivotVisitor pivotVisitor, S context) { + return pivotVisitor.visit(this, context); } public boolean getIncludeNulls() { diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Values.java b/src/main/java/net/sf/jsqlparser/statement/select/Values.java index 1eba25512..627cbb4cb 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Values.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Values.java @@ -9,6 +9,7 @@ */ package net.sf.jsqlparser.statement.select; +import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; @@ -16,18 +17,24 @@ import java.util.Arrays; import java.util.Collection; -public class Values extends Select { +public class Values extends Select implements FromItem { private ExpressionList expressions; + private Alias alias; public Values() { - // empty constructor + this(null, null); } public Values(ExpressionList expressions) { this.expressions = expressions; } + public Values(ExpressionList expressions, Alias alias) { + this.expressions = expressions; + this.alias = alias; + } + public ExpressionList getExpressions() { return expressions; } @@ -41,12 +48,20 @@ public void setExpressions(ExpressionList expressions) { public StringBuilder appendSelectBodyTo(StringBuilder builder) { builder.append("VALUES "); builder.append(expressions.toString()); + if (alias != null) { + builder.append(" ").append(alias); + } return builder; } @Override - public void accept(SelectVisitor selectVisitor) { - selectVisitor.visit(this); + public T accept(SelectVisitor selectVisitor, S context) { + return selectVisitor.visit(this, context); + } + + @Override + public T accept(FromItemVisitor fromItemVisitor, S context) { + return fromItemVisitor.visit(this, context); } public Values withExpressions(ExpressionList expressions) { @@ -65,4 +80,34 @@ public Values addExpressions(Collection expressions) { this.expressions.addAll(expressions); return this; } + + @Override + public Alias getAlias() { + return alias; + } + + @Override + public void setAlias(Alias alias) { + this.alias = alias; + } + + @Override + public Pivot getPivot() { + return null; + } + + @Override + public void setPivot(Pivot pivot) { + + } + + @Override + public UnPivot getUnPivot() { + return null; + } + + @Override + public void setUnPivot(UnPivot unpivot) { + + } } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Wait.java b/src/main/java/net/sf/jsqlparser/statement/select/Wait.java index 0d94e22a0..e66fc73b5 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Wait.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Wait.java @@ -25,7 +25,7 @@ public void setTimeout(long timeout) { /** * Returns a String containing the WAIT clause and its timeout, where TIMEOUT is specified by - * {@link #getTimeout()}. The returned string will null be: + * {@link #getTimeout()}. The returned string will null be: * " WAIT <TIMEOUT>" * */ diff --git a/src/main/java/net/sf/jsqlparser/statement/select/WithIsolation.java b/src/main/java/net/sf/jsqlparser/statement/select/WithIsolation.java index 7aef6ef4e..e6ac80754 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/WithIsolation.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/WithIsolation.java @@ -19,6 +19,7 @@ public class WithIsolation implements Serializable { public String getIsolation() { return this.isolation; } + public void setIsolation(String s) { this.isolation = s; } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java b/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java index de673f491..b3610a730 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java @@ -59,8 +59,8 @@ public StringBuilder appendSelectBodyTo(StringBuilder builder) { } @Override - public void accept(SelectVisitor visitor) { - visitor.visit(this); + public T accept(SelectVisitor selectVisitor, S context) { + return selectVisitor.visit(this, context); } diff --git a/src/main/java/net/sf/jsqlparser/statement/show/ShowIndexStatement.java b/src/main/java/net/sf/jsqlparser/statement/show/ShowIndexStatement.java index 39a35d07c..d6b4bf72d 100644 --- a/src/main/java/net/sf/jsqlparser/statement/show/ShowIndexStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/show/ShowIndexStatement.java @@ -1,21 +1,20 @@ - /*- - * #%L - * JSQLParser library - * %% - * Copyright (C) 2004 - 2019 JSQLParser - * %% - * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 - * #L% - */ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2019 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ package net.sf.jsqlparser.statement.show; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; /** -* -* @author Jayant Kumar Yadav -*/ + * @author Jayant Kumar Yadav + */ public class ShowIndexStatement implements Statement { @@ -43,12 +42,12 @@ public String toString() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public ShowIndexStatement withTableName(String tableName) { this.setTableName(tableName); return this; } -} \ No newline at end of file +} diff --git a/src/main/java/net/sf/jsqlparser/statement/show/ShowTablesStatement.java b/src/main/java/net/sf/jsqlparser/statement/show/ShowTablesStatement.java index 16106b823..5aaa8c8eb 100644 --- a/src/main/java/net/sf/jsqlparser/statement/show/ShowTablesStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/show/ShowTablesStatement.java @@ -17,7 +17,7 @@ /** * A {@code SHOW TABLES} statement - * + * * @see MySQL show tables */ public class ShowTablesStatement implements Statement { @@ -98,8 +98,8 @@ public String toString() { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public enum SelectionMode { diff --git a/src/main/java/net/sf/jsqlparser/statement/truncate/Truncate.java b/src/main/java/net/sf/jsqlparser/statement/truncate/Truncate.java index 9848c7799..4388f3ddd 100644 --- a/src/main/java/net/sf/jsqlparser/statement/truncate/Truncate.java +++ b/src/main/java/net/sf/jsqlparser/statement/truncate/Truncate.java @@ -15,15 +15,14 @@ public class Truncate implements Statement { - private Table table; - boolean cascade; // to support TRUNCATE TABLE ... CASCADE - - boolean tableToken; // to support TRUNCATE without TABLE + boolean cascade; // to support TRUNCATE TABLE ... CASCADE + boolean tableToken; // to support TRUNCATE without TABLE boolean only; // to support TRUNCATE with ONLY + private Table table; @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public Table getTable() { @@ -56,7 +55,7 @@ public String toString() { sb.append(table); if (cascade) { - sb.append( " CASCADE"); + sb.append(" CASCADE"); } return sb.toString(); } @@ -77,7 +76,7 @@ public void setOnly(boolean only) { this.only = only; } - public Truncate withTableToken(boolean hasTableToken){ + public Truncate withTableToken(boolean hasTableToken) { this.setTableToken(hasTableToken); return this; } @@ -91,6 +90,7 @@ public Truncate withCascade(boolean cascade) { this.setCascade(cascade); return this; } + public Truncate withOnly(boolean only) { this.setOnly(only); return this; diff --git a/src/main/java/net/sf/jsqlparser/statement/update/Update.java b/src/main/java/net/sf/jsqlparser/statement/update/Update.java index 0a6224d76..64da8f64e 100644 --- a/src/main/java/net/sf/jsqlparser/statement/update/Update.java +++ b/src/main/java/net/sf/jsqlparser/statement/update/Update.java @@ -64,22 +64,22 @@ public List getUpdateSets() { return updateSets; } - public UpdateSet getUpdateSet(int index) { - return updateSets.get(index); - } - public void setUpdateSets(List updateSets) { this.updateSets = updateSets; } + public UpdateSet getUpdateSet(int index) { + return updateSets.get(index); + } + public Update withUpdateSets(List updateSets) { this.setUpdateSets(updateSets); return this; } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public List getWithItemsList() { @@ -113,14 +113,14 @@ public Table getTable() { return table; } - public Expression getWhere() { - return where; - } - public void setTable(Table table) { this.table = table; } + public Expression getWhere() { + return where; + } + public void setWhere(Expression expression) { where = expression; } @@ -150,11 +150,6 @@ public List getColumns() { return updateSets.get(0).columns; } - @Deprecated - public List getExpressions() { - return updateSets.get(0).values; - } - @Deprecated public void setColumns(List list) { if (updateSets.isEmpty()) { @@ -164,6 +159,11 @@ public void setColumns(List list) { updateSets.get(0).columns.addAll(list); } + @Deprecated + public List getExpressions() { + return updateSets.get(0).values; + } + @Deprecated public void setExpressions(List list) { updateSets.get(0).values.clear(); @@ -233,22 +233,22 @@ public void setUseSelect(boolean useSelect) { // todo } - public void setOrderByElements(List orderByElements) { - this.orderByElements = orderByElements; - } - - public void setLimit(Limit limit) { - this.limit = limit; - } - public List getOrderByElements() { return orderByElements; } + public void setOrderByElements(List orderByElements) { + this.orderByElements = orderByElements; + } + public Limit getLimit() { return limit; } + public void setLimit(Limit limit) { + this.limit = limit; + } + public ReturningClause getReturningClause() { return returningClause; } diff --git a/src/main/java/net/sf/jsqlparser/statement/update/UpdateSet.java b/src/main/java/net/sf/jsqlparser/statement/update/UpdateSet.java index 84299c0fb..46aa85e7d 100644 --- a/src/main/java/net/sf/jsqlparser/statement/update/UpdateSet.java +++ b/src/main/java/net/sf/jsqlparser/statement/update/UpdateSet.java @@ -36,30 +36,40 @@ public UpdateSet(Column column, Expression value) { this.values.add(value); } - public ExpressionList getColumns() { - return columns; + public final static StringBuilder appendUpdateSetsTo(StringBuilder builder, + Collection updateSets) { + int j = 0; + for (UpdateSet updateSet : updateSets) { + updateSet.appendTo(builder, j); + j++; + } + return builder; } - public Column getColumn(int index) { - return columns.get(index); + public ExpressionList getColumns() { + return columns; } public void setColumns(ExpressionList columns) { this.columns = Objects.requireNonNull(columns); } - public ExpressionList getValues() { - return values; + public Column getColumn(int index) { + return columns.get(index); } - public Expression getValue(int index) { - return values.get(index); + public ExpressionList getValues() { + return values; } public void setValues(ExpressionList values) { this.values = Objects.requireNonNull(values); } + public Expression getValue(int index) { + return values.get(index); + } + public void add(Column column, Expression value) { this.add(column); this.add(value); @@ -95,16 +105,6 @@ public void add(ExpressionList expressionList) { values.addAll(expressionList); } - public final static StringBuilder appendUpdateSetsTo(StringBuilder builder, - Collection updateSets) { - int j = 0; - for (UpdateSet updateSet : updateSets) { - updateSet.appendTo(builder, j); - j++; - } - return builder; - } - @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPath"}) StringBuilder appendTo(StringBuilder builder, int j) { if (j > 0) { diff --git a/src/main/java/net/sf/jsqlparser/statement/upsert/Upsert.java b/src/main/java/net/sf/jsqlparser/statement/upsert/Upsert.java index 4e63782d2..6bb0376b9 100644 --- a/src/main/java/net/sf/jsqlparser/statement/upsert/Upsert.java +++ b/src/main/java/net/sf/jsqlparser/statement/upsert/Upsert.java @@ -55,8 +55,8 @@ public Upsert setDuplicateUpdateSets(List duplicateUpdateSets) { } @Override - public void accept(StatementVisitor statementVisitor) { - statementVisitor.visit(this); + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); } public UpsertType getUpsertType() { diff --git a/src/main/java/net/sf/jsqlparser/util/AddAliasesVisitor.java b/src/main/java/net/sf/jsqlparser/util/AddAliasesVisitor.java index 58ca4326f..17e5ed428 100644 --- a/src/main/java/net/sf/jsqlparser/util/AddAliasesVisitor.java +++ b/src/main/java/net/sf/jsqlparser/util/AddAliasesVisitor.java @@ -11,6 +11,7 @@ import java.util.LinkedList; import java.util.List; + import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.statement.select.LateralSubSelect; import net.sf.jsqlparser.statement.select.ParenthesedSelect; @@ -31,42 +32,45 @@ * * @author tw */ -public class AddAliasesVisitor implements SelectVisitor, SelectItemVisitor { +public class AddAliasesVisitor implements SelectVisitor, SelectItemVisitor { private static final String NOT_SUPPORTED_YET = "Not supported yet."; - private List aliases = new LinkedList(); + private final List aliases = new LinkedList(); private boolean firstRun = true; private int counter = 0; private String prefix = "A"; @Override - public void visit(ParenthesedSelect parenthesedSelect) { - parenthesedSelect.getSelect().accept(this); + public T visit(ParenthesedSelect parenthesedSelect, S context) { + parenthesedSelect.getSelect().accept(this, context); + return null; } @Override - public void visit(PlainSelect plainSelect) { + public T visit(PlainSelect plainSelect, S context) { firstRun = true; counter = 0; aliases.clear(); - for (SelectItem item : plainSelect.getSelectItems()) { - item.accept(this); + for (SelectItem item : plainSelect.getSelectItems()) { + item.accept(this, context); } firstRun = false; - for (SelectItem item : plainSelect.getSelectItems()) { - item.accept(this); + for (SelectItem item : plainSelect.getSelectItems()) { + item.accept(this, context); } + return null; } @Override - public void visit(SetOperationList setOpList) { - for (Select select : setOpList.getSelects()) { - select.accept(this); + public T visit(SetOperationList setOperationList, S context) { + for (Select select : setOperationList.getSelects()) { + select.accept(this, context); } + return null; } @Override - public void visit(SelectItem selectExpressionItem) { + public T visit(SelectItem selectExpressionItem, S context) { if (firstRun) { if (selectExpressionItem.getAlias() != null) { aliases.add(selectExpressionItem.getAlias().getName().toUpperCase()); @@ -83,6 +87,7 @@ public void visit(SelectItem selectExpressionItem) { } } } + return null; } protected String getNextAlias() { @@ -95,26 +100,23 @@ public void setPrefix(String prefix) { } @Override - public void visit(WithItem withItem) { - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); // To change body of generated - // methods, choose Tools | - // Templates. + public T visit(WithItem withItem, S context) { + throw new UnsupportedOperationException(NOT_SUPPORTED_YET); } @Override - public void visit(Values aThis) { - throw new UnsupportedOperationException("Not supported yet."); // To change body of - // generated methods, choose - // Tools | Templates. + public T visit(Values values, S context) { + throw new UnsupportedOperationException(NOT_SUPPORTED_YET); } @Override - public void visit(LateralSubSelect lateralSubSelect) { - lateralSubSelect.getSelect().accept(this); + public T visit(LateralSubSelect lateralSubSelect, S context) { + lateralSubSelect.getSelect().accept(this, context); + return null; } @Override - public void visit(TableStatement tableStatement) { - throw new UnsupportedOperationException("Not supported yet."); + public T visit(TableStatement tableStatement, S context) { + throw new UnsupportedOperationException(NOT_SUPPORTED_YET); } } diff --git a/src/main/java/net/sf/jsqlparser/util/ConnectExpressionsVisitor.java b/src/main/java/net/sf/jsqlparser/util/ConnectExpressionsVisitor.java index 46b746f0a..903b5d722 100644 --- a/src/main/java/net/sf/jsqlparser/util/ConnectExpressionsVisitor.java +++ b/src/main/java/net/sf/jsqlparser/util/ConnectExpressionsVisitor.java @@ -11,8 +11,10 @@ import java.util.LinkedList; import java.util.List; + import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.BinaryExpression; +import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.statement.select.LateralSubSelect; import net.sf.jsqlparser.statement.select.ParenthesedSelect; import net.sf.jsqlparser.statement.select.PlainSelect; @@ -33,10 +35,12 @@ * @author tw */ @SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) -public abstract class ConnectExpressionsVisitor implements SelectVisitor, SelectItemVisitor { +public abstract class ConnectExpressionsVisitor + implements SelectVisitor, SelectItemVisitor { + private final List> itemsExpr = + new LinkedList>(); private String alias = "expr"; - private final List itemsExpr = new LinkedList(); public ConnectExpressionsVisitor() {} @@ -47,19 +51,21 @@ public ConnectExpressionsVisitor(String alias) { protected abstract BinaryExpression createBinaryExpression(); @Override - public void visit(ParenthesedSelect parenthesedSelect) { - parenthesedSelect.getSelect().accept(this); + public T visit(ParenthesedSelect parenthesedSelect, S context) { + parenthesedSelect.getSelect().accept(this, context); + return null; } @Override - public void visit(LateralSubSelect lateralSubSelect) { - lateralSubSelect.getSelect().accept(this); + public T visit(LateralSubSelect lateralSubSelect, S context) { + lateralSubSelect.getSelect().accept(this, context); + return null; } @Override - public void visit(PlainSelect plainSelect) { - for (SelectItem item : plainSelect.getSelectItems()) { - item.accept(this); + public T visit(PlainSelect plainSelect, S context) { + for (SelectItem item : plainSelect.getSelectItems()) { + item.accept(this, context); } if (itemsExpr.size() > 1) { @@ -73,7 +79,7 @@ public void visit(PlainSelect plainSelect) { } binExpr.setRightExpression(itemsExpr.get(itemsExpr.size() - 1).getExpression()); - SelectItem sei = new SelectItem(); + SelectItem sei = new SelectItem<>(); sei.setExpression(binExpr); plainSelect.getSelectItems().clear(); @@ -81,30 +87,35 @@ public void visit(PlainSelect plainSelect) { } plainSelect.getSelectItems().get(0).setAlias(new Alias(alias)); + return null; } @Override - public void visit(SetOperationList setOpList) { + public T visit(SetOperationList setOpList, S context) { for (Select select : setOpList.getSelects()) { - select.accept(this); + select.accept(this, context); } + return null; } @Override - public void visit(WithItem withItem) {} + public T visit(WithItem withItem, S context) { + return null; + } @Override - public void visit(SelectItem selectItem) { + public T visit(SelectItem selectItem, S context) { itemsExpr.add(selectItem); + return null; } @Override - public void visit(Values aThis) { + public T visit(Values aThis, S context) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public void visit(TableStatement tableStatement) { + public T visit(TableStatement tableStatement, S context) { throw new UnsupportedOperationException("Not supported yet."); } } diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index 4dc760925..19d0c7d42 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -9,11 +9,6 @@ */ package net.sf.jsqlparser.util; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.AllValue; import net.sf.jsqlparser.expression.AnalyticExpression; @@ -41,6 +36,7 @@ import net.sf.jsqlparser.expression.JsonFunction; import net.sf.jsqlparser.expression.JsonFunctionExpression; import net.sf.jsqlparser.expression.KeepExpression; +import net.sf.jsqlparser.expression.LambdaExpression; import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.MySQLGroupConcat; import net.sf.jsqlparser.expression.NextValExpression; @@ -51,12 +47,12 @@ import net.sf.jsqlparser.expression.OracleHint; import net.sf.jsqlparser.expression.OracleNamedFunctionParameter; import net.sf.jsqlparser.expression.OverlapsCondition; -import net.sf.jsqlparser.expression.Parenthesis; import net.sf.jsqlparser.expression.RangeExpression; import net.sf.jsqlparser.expression.RowConstructor; import net.sf.jsqlparser.expression.RowGetExpression; import net.sf.jsqlparser.expression.SignedExpression; import net.sf.jsqlparser.expression.StringValue; +import net.sf.jsqlparser.expression.StructType; import net.sf.jsqlparser.expression.TimeKeyExpression; import net.sf.jsqlparser.expression.TimeValue; import net.sf.jsqlparser.expression.TimestampValue; @@ -87,6 +83,7 @@ import net.sf.jsqlparser.expression.operators.relational.Contains; import net.sf.jsqlparser.expression.operators.relational.DoubleAnd; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; +import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression; import net.sf.jsqlparser.expression.operators.relational.ExistsExpression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.FullTextSearch; @@ -94,6 +91,7 @@ import net.sf.jsqlparser.expression.operators.relational.GreaterThan; import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals; import net.sf.jsqlparser.expression.operators.relational.InExpression; +import net.sf.jsqlparser.expression.operators.relational.IncludesExpression; import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression; import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression; import net.sf.jsqlparser.expression.operators.relational.IsNullExpression; @@ -176,6 +174,12 @@ import net.sf.jsqlparser.statement.update.Update; import net.sf.jsqlparser.statement.upsert.Upsert; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * Find all used tables within an select statement. @@ -184,15 +188,35 @@ * Override extractTableName method to modify the extracted table names (e.g. without schema). */ @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.UncommentedEmptyMethodBody"}) -public class TablesNamesFinder implements SelectVisitor, FromItemVisitor, ExpressionVisitor, - SelectItemVisitor, StatementVisitor { +public class TablesNamesFinder + implements SelectVisitor, FromItemVisitor, ExpressionVisitor, + SelectItemVisitor, StatementVisitor { - private static final String NOT_SUPPORTED_YET = "Not supported yet."; private Set tables; private boolean allowColumnProcessing = false; private List otherItemNames; + public static Set findTables(String sqlStr) throws JSQLParserException { + TablesNamesFinder tablesNamesFinder = new TablesNamesFinder<>(); + return tablesNamesFinder.getTables(CCJSqlParserUtil.parse(sqlStr)); + } + + public static Set findTablesOrOtherSources(String sqlStr) throws JSQLParserException { + TablesNamesFinder tablesNamesFinder = new TablesNamesFinder<>(); + return tablesNamesFinder.getTablesOrOtherSources(CCJSqlParserUtil.parse(sqlStr)); + } + + public static Set findTablesInExpression(String exprStr) throws JSQLParserException { + TablesNamesFinder tablesNamesFinder = new TablesNamesFinder<>(); + return tablesNamesFinder.getTables(CCJSqlParserUtil.parseExpression(exprStr)); + } + + private static void throwUnsupported(T type) { + throw new UnsupportedOperationException(String.format( + "Finding tables from %s is not supported", type.getClass().getSimpleName())); + } + @Deprecated public List getTableList(Statement statement) { return new ArrayList(getTables(statement)); @@ -200,45 +224,64 @@ public List getTableList(Statement statement) { public Set getTables(Statement statement) { init(false); - statement.accept(this); + statement.accept(this, null); + + // @todo: assess this carefully, maybe we want to remove more specifically + // only Aliases on WithItems, Parenthesed Selects and Lateral Selects + otherItemNames.forEach(tables::remove); + return tables; } - public static Set findTables(String sqlStr) throws JSQLParserException { - TablesNamesFinder tablesNamesFinder = new TablesNamesFinder(); - return tablesNamesFinder.getTables(CCJSqlParserUtil.parse(sqlStr)); + public Set getTablesOrOtherSources(Statement statement) { + init(false); + statement.accept(this, null); + + HashSet tablesOrOtherSources = new HashSet<>(tables); + tablesOrOtherSources.addAll(otherItemNames); + + return tablesOrOtherSources; } @Override - public void visit(Select select) { + public Void visit(Select select, S context) { List withItemsList = select.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { for (WithItem withItem : withItemsList) { - withItem.accept((SelectVisitor) this); + withItem.accept((SelectVisitor) this, context); } } - select.accept((SelectVisitor) this); + select.accept((SelectVisitor) this, context); + return null; + } + + @Override + public void visit(Select select) { + StatementVisitor.super.visit(select); } @Override - public void visit(TranscodingFunction transcodingFunction) { - transcodingFunction.getExpression().accept(this); + public Void visit(TranscodingFunction transcodingFunction, S context) { + transcodingFunction.getExpression().accept(this, context); + return null; } @Override - public void visit(TrimFunction trimFunction) { + public Void visit(TrimFunction trimFunction, S context) { if (trimFunction.getExpression() != null) { - trimFunction.getExpression().accept(this); + trimFunction.getExpression().accept(this, context); } if (trimFunction.getFromExpression() != null) { - trimFunction.getFromExpression().accept(this); + trimFunction.getFromExpression().accept(this, context); } + return null; } @Override - public void visit(RangeExpression rangeExpression) { - rangeExpression.getStartExpression().accept(this); - rangeExpression.getEndExpression().accept(this); + public Void visit(RangeExpression rangeExpression, S context) { + rangeExpression.getStartExpression().accept(this, context); + rangeExpression.getEndExpression().accept(this, context); + return null; } /** @@ -251,62 +294,78 @@ public List getTableList(Expression expr) { public Set getTables(Expression expr) { init(true); - expr.accept(this); + expr.accept(this, null); return tables; } - public static Set findTablesInExpression(String exprStr) throws JSQLParserException { - TablesNamesFinder tablesNamesFinder = new TablesNamesFinder(); - return tablesNamesFinder.getTables(CCJSqlParserUtil.parseExpression(exprStr)); + @Override + public Void visit(WithItem withItem, S context) { + otherItemNames.add(withItem.getAlias().getName()); + withItem.getSelect().accept((SelectVisitor) this, context); + return null; } @Override public void visit(WithItem withItem) { - otherItemNames.add(withItem.getAlias().getName().toLowerCase()); - withItem.getSelect().accept((SelectVisitor) this); + SelectVisitor.super.visit(withItem); } @Override - public void visit(ParenthesedSelect selectBody) { - List withItemsList = selectBody.getWithItemsList(); + public Void visit(ParenthesedSelect select, S context) { + if (select.getAlias() != null) { + otherItemNames.add(select.getAlias().getName()); + } + List withItemsList = select.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { for (WithItem withItem : withItemsList) { - withItem.accept((SelectVisitor) this); + withItem.accept((SelectVisitor) this, context); } } - selectBody.getSelect().accept((SelectVisitor) this); + select.getSelect().accept((SelectVisitor) this, context); + return null; } @Override - public void visit(PlainSelect plainSelect) { + public void visit(ParenthesedSelect parenthesedSelect) { + SelectVisitor.super.visit(parenthesedSelect); + } + + @Override + public Void visit(PlainSelect plainSelect, S context) { List withItemsList = plainSelect.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { for (WithItem withItem : withItemsList) { - withItem.accept((SelectVisitor) this); + withItem.accept((SelectVisitor) this, context); } } if (plainSelect.getSelectItems() != null) { for (SelectItem item : plainSelect.getSelectItems()) { - item.accept(this); + item.accept(this, context); } } if (plainSelect.getFromItem() != null) { - plainSelect.getFromItem().accept(this); + plainSelect.getFromItem().accept(this, context); } - visitJoins(plainSelect.getJoins()); + visitJoins(plainSelect.getJoins(), context); if (plainSelect.getWhere() != null) { - plainSelect.getWhere().accept(this); + plainSelect.getWhere().accept(this, context); } if (plainSelect.getHaving() != null) { - plainSelect.getHaving().accept(this); + plainSelect.getHaving().accept(this, context); } if (plainSelect.getOracleHierarchical() != null) { - plainSelect.getOracleHierarchical().accept(this); + plainSelect.getOracleHierarchical().accept(this, context); } + return null; + } + + @Override + public void visit(PlainSelect plainSelect) { + SelectVisitor.super.visit(plainSelect); } /** @@ -320,240 +379,295 @@ protected String extractTableName(Table table) { } @Override - public void visit(Table tableName) { + public Void visit(Table tableName, S context) { String tableWholeName = extractTableName(tableName); - if (!otherItemNames.contains(tableWholeName.toLowerCase()) - && !tables.contains(tableWholeName)) { + if (!otherItemNames.contains(tableWholeName)) { tables.add(tableWholeName); } + return null; + } + + @Override + public void visit(Table tableName) { + FromItemVisitor.super.visit(tableName); } @Override - public void visit(Addition addition) { + public Void visit(Addition addition, S context) { visitBinaryExpression(addition); + return null; } @Override - public void visit(AndExpression andExpression) { + public Void visit(AndExpression andExpression, S context) { visitBinaryExpression(andExpression); + return null; } @Override - public void visit(Between between) { - between.getLeftExpression().accept(this); - between.getBetweenExpressionStart().accept(this); - between.getBetweenExpressionEnd().accept(this); + public Void visit(Between between, S context) { + between.getLeftExpression().accept(this, context); + between.getBetweenExpressionStart().accept(this, context); + between.getBetweenExpressionEnd().accept(this, context); + return null; } @Override - public void visit(OverlapsCondition overlapsCondition) { - overlapsCondition.getLeft().accept(this); - overlapsCondition.getRight().accept(this); + public Void visit(OverlapsCondition overlapsCondition, S context) { + overlapsCondition.getLeft().accept(this, context); + overlapsCondition.getRight().accept(this, context); + return null; } @Override - public void visit(Column tableColumn) { + public Void visit(Column tableColumn, S context) { if (allowColumnProcessing && tableColumn.getTable() != null && tableColumn.getTable().getName() != null) { - visit(tableColumn.getTable()); + visit(tableColumn.getTable(), context); } + return null; } @Override - public void visit(Division division) { + public Void visit(Division division, S context) { visitBinaryExpression(division); + return null; } @Override - public void visit(IntegerDivision division) { + public Void visit(IntegerDivision division, S context) { visitBinaryExpression(division); + return null; } @Override - public void visit(DoubleValue doubleValue) { + public Void visit(DoubleValue doubleValue, S context) { + return null; } @Override - public void visit(EqualsTo equalsTo) { + public Void visit(EqualsTo equalsTo, S context) { visitBinaryExpression(equalsTo); + return null; } @Override - public void visit(Function function) { - ExpressionList exprList = function.getParameters(); + public Void visit(Function function, S context) { + ExpressionList exprList = function.getParameters(); if (exprList != null) { - visit(exprList); + visit(exprList, context); } + return null; } @Override - public void visit(GreaterThan greaterThan) { + public Void visit(GreaterThan greaterThan, S context) { visitBinaryExpression(greaterThan); + return null; } @Override - public void visit(GreaterThanEquals greaterThanEquals) { + public Void visit(GreaterThanEquals greaterThanEquals, S context) { visitBinaryExpression(greaterThanEquals); + return null; + } + + @Override + public Void visit(InExpression inExpression, S context) { + inExpression.getLeftExpression().accept(this, context); + inExpression.getRightExpression().accept(this, context); + return null; + } + + @Override + public Void visit(IncludesExpression includesExpression, S context) { + includesExpression.getLeftExpression().accept(this, context); + includesExpression.getRightExpression().accept(this, context); + return null; } @Override - public void visit(InExpression inExpression) { - inExpression.getLeftExpression().accept(this); - inExpression.getRightExpression().accept(this); + public Void visit(ExcludesExpression excludesExpression, S context) { + excludesExpression.getLeftExpression().accept(this, context); + excludesExpression.getRightExpression().accept(this, context); + return null; } @Override - public void visit(FullTextSearch fullTextSearch) { + public Void visit(FullTextSearch fullTextSearch, S context) { + return null; } @Override - public void visit(SignedExpression signedExpression) { - signedExpression.getExpression().accept(this); + public Void visit(SignedExpression signedExpression, S context) { + signedExpression.getExpression().accept(this, context); + return null; } @Override - public void visit(IsNullExpression isNullExpression) { + public Void visit(IsNullExpression isNullExpression, S context) { + return null; } @Override - public void visit(IsBooleanExpression isBooleanExpression) { + public Void visit(IsBooleanExpression isBooleanExpression, S context) { + return null; } @Override - public void visit(JdbcParameter jdbcParameter) { + public Void visit(JdbcParameter jdbcParameter, S context) { + return null; } @Override - public void visit(LikeExpression likeExpression) { + public Void visit(LikeExpression likeExpression, S context) { visitBinaryExpression(likeExpression); + return null; } @Override - public void visit(ExistsExpression existsExpression) { - existsExpression.getRightExpression().accept(this); + public Void visit(ExistsExpression existsExpression, S context) { + existsExpression.getRightExpression().accept(this, context); + return null; } @Override - public void visit(MemberOfExpression memberOfExpression) { - memberOfExpression.getLeftExpression().accept(this); - memberOfExpression.getRightExpression().accept(this); + public Void visit(MemberOfExpression memberOfExpression, S context) { + memberOfExpression.getLeftExpression().accept(this, context); + memberOfExpression.getRightExpression().accept(this, context); + return null; } @Override - public void visit(LongValue longValue) { + public Void visit(LongValue longValue, S context) { + return null; } @Override - public void visit(MinorThan minorThan) { + public Void visit(MinorThan minorThan, S context) { visitBinaryExpression(minorThan); + return null; } @Override - public void visit(MinorThanEquals minorThanEquals) { + public Void visit(MinorThanEquals minorThanEquals, S context) { visitBinaryExpression(minorThanEquals); + return null; } @Override - public void visit(Multiplication multiplication) { + public Void visit(Multiplication multiplication, S context) { visitBinaryExpression(multiplication); + return null; } @Override - public void visit(NotEqualsTo notEqualsTo) { + public Void visit(NotEqualsTo notEqualsTo, S context) { visitBinaryExpression(notEqualsTo); + return null; } @Override - public void visit(DoubleAnd doubleAnd) { + public Void visit(DoubleAnd doubleAnd, S context) { visitBinaryExpression(doubleAnd); + return null; } @Override - public void visit(Contains contains) { + public Void visit(Contains contains, S context) { visitBinaryExpression(contains); + return null; } @Override - public void visit(ContainedBy containedBy) { + public Void visit(ContainedBy containedBy, S context) { visitBinaryExpression(containedBy); + return null; } @Override - public void visit(NullValue nullValue) { + public Void visit(NullValue nullValue, S context) { + return null; } @Override - public void visit(OrExpression orExpression) { + public Void visit(OrExpression orExpression, S context) { visitBinaryExpression(orExpression); + return null; } @Override - public void visit(XorExpression xorExpression) { + public Void visit(XorExpression xorExpression, S context) { visitBinaryExpression(xorExpression); + return null; } @Override - public void visit(Parenthesis parenthesis) { - parenthesis.getExpression().accept(this); - } - - @Override - public void visit(StringValue stringValue) { + public Void visit(StringValue stringValue, S context) { + return null; } @Override - public void visit(Subtraction subtraction) { + public Void visit(Subtraction subtraction, S context) { visitBinaryExpression(subtraction); + return null; } @Override - public void visit(NotExpression notExpr) { - notExpr.getExpression().accept(this); + public Void visit(NotExpression notExpr, S context) { + notExpr.getExpression().accept(this, context); + return null; } @Override - public void visit(BitwiseRightShift expr) { + public Void visit(BitwiseRightShift expr, S context) { visitBinaryExpression(expr); + return null; } @Override - public void visit(BitwiseLeftShift expr) { + public Void visit(BitwiseLeftShift expr, S context) { visitBinaryExpression(expr); + return null; } public void visitBinaryExpression(BinaryExpression binaryExpression) { - binaryExpression.getLeftExpression().accept(this); - binaryExpression.getRightExpression().accept(this); + binaryExpression.getLeftExpression().accept(this, null); + binaryExpression.getRightExpression().accept(this, null); } @Override - public void visit(ExpressionList expressionList) { + public Void visit(ExpressionList expressionList, S context) { for (Expression expression : expressionList) { - expression.accept(this); + expression.accept(this, context); } + return null; } @Override - public void visit(DateValue dateValue) { + public Void visit(DateValue dateValue, S context) { + return null; } @Override - public void visit(TimestampValue timestampValue) { + public Void visit(TimestampValue timestampValue, S context) { + return null; } @Override - public void visit(TimeValue timeValue) { + public Void visit(TimeValue timeValue, S context) { + return null; } /* @@ -563,18 +677,19 @@ public void visit(TimeValue timeValue) { * CaseExpression) */ @Override - public void visit(CaseExpression caseExpression) { + public Void visit(CaseExpression caseExpression, S context) { if (caseExpression.getSwitchExpression() != null) { - caseExpression.getSwitchExpression().accept(this); + caseExpression.getSwitchExpression().accept(this, context); } if (caseExpression.getWhenClauses() != null) { for (WhenClause when : caseExpression.getWhenClauses()) { - when.accept(this); + when.accept(this, context); } } if (caseExpression.getElseExpression() != null) { - caseExpression.getElseExpression().accept(this); + caseExpression.getElseExpression().accept(this, context); } + return null; } /* @@ -584,110 +699,144 @@ public void visit(CaseExpression caseExpression) { * net.sf.jsqlparser.expression.ExpressionVisitor#visit(net.sf.jsqlparser.expression.WhenClause) */ @Override - public void visit(WhenClause whenClause) { + public Void visit(WhenClause whenClause, S context) { if (whenClause.getWhenExpression() != null) { - whenClause.getWhenExpression().accept(this); + whenClause.getWhenExpression().accept(this, context); } if (whenClause.getThenExpression() != null) { - whenClause.getThenExpression().accept(this); + whenClause.getThenExpression().accept(this, context); } + return null; } @Override - public void visit(AnyComparisonExpression anyComparisonExpression) { - anyComparisonExpression.getSelect().accept((ExpressionVisitor) this); + public Void visit(AnyComparisonExpression anyComparisonExpression, S context) { + anyComparisonExpression.getSelect().accept((ExpressionVisitor) this, context); + return null; } @Override - public void visit(Concat concat) { + public Void visit(Concat concat, S context) { visitBinaryExpression(concat); + return null; } @Override - public void visit(Matches matches) { + public Void visit(Matches matches, S context) { visitBinaryExpression(matches); + return null; } @Override - public void visit(BitwiseAnd bitwiseAnd) { + public Void visit(BitwiseAnd bitwiseAnd, S context) { visitBinaryExpression(bitwiseAnd); + return null; } @Override - public void visit(BitwiseOr bitwiseOr) { + public Void visit(BitwiseOr bitwiseOr, S context) { visitBinaryExpression(bitwiseOr); + return null; } @Override - public void visit(BitwiseXor bitwiseXor) { + public Void visit(BitwiseXor bitwiseXor, S context) { visitBinaryExpression(bitwiseXor); + return null; } @Override - public void visit(CastExpression cast) { - cast.getLeftExpression().accept(this); + public Void visit(CastExpression cast, S context) { + cast.getLeftExpression().accept(this, context); + return null; } @Override - public void visit(Modulo modulo) { + public Void visit(Modulo modulo, S context) { visitBinaryExpression(modulo); + return null; } @Override - public void visit(AnalyticExpression analytic) { + public Void visit(AnalyticExpression analytic, S context) { if (analytic.getExpression() != null) { - analytic.getExpression().accept(this); + analytic.getExpression().accept(this, context); } if (analytic.getDefaultValue() != null) { - analytic.getDefaultValue().accept(this); + analytic.getDefaultValue().accept(this, context); } if (analytic.getOffset() != null) { - analytic.getOffset().accept(this); + analytic.getOffset().accept(this, context); } if (analytic.getKeep() != null) { - analytic.getKeep().accept(this); + analytic.getKeep().accept(this, context); } if (analytic.getFuncOrderBy() != null) { for (OrderByElement element : analytic.getOrderByElements()) { - element.getExpression().accept(this); + element.getExpression().accept(this, context); } } if (analytic.getWindowElement() != null) { - analytic.getWindowElement().getRange().getStart().getExpression().accept(this); - analytic.getWindowElement().getRange().getEnd().getExpression().accept(this); - analytic.getWindowElement().getOffset().getExpression().accept(this); + analytic.getWindowElement().getRange().getStart().getExpression().accept(this, + context); + analytic.getWindowElement().getRange().getEnd().getExpression().accept(this, + context); + analytic.getWindowElement().getOffset().getExpression().accept(this, context); } + return null; } @Override - public void visit(SetOperationList list) { + public Void visit(SetOperationList list, S context) { List withItemsList = list.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { for (WithItem withItem : withItemsList) { - withItem.accept((SelectVisitor) this); + withItem.accept((SelectVisitor) this, context); } } for (Select selectBody : list.getSelects()) { - selectBody.accept((SelectVisitor) this); + selectBody.accept((SelectVisitor) this, context); } + return null; } @Override - public void visit(ExtractExpression eexpr) { + public void visit(SetOperationList setOpList) { + SelectVisitor.super.visit(setOpList); + } + + @Override + public Void visit(ExtractExpression eexpr, S context) { if (eexpr.getExpression() != null) { - eexpr.getExpression().accept(this); + eexpr.getExpression().accept(this, context); } + return null; + } + + @Override + public Void visit(LateralSubSelect lateralSubSelect, S context) { + if (lateralSubSelect.getAlias() != null) { + otherItemNames.add(lateralSubSelect.getAlias().getName()); + } + lateralSubSelect.getSelect().accept((SelectVisitor) this, context); + return null; } @Override public void visit(LateralSubSelect lateralSubSelect) { - lateralSubSelect.getSelect().accept((SelectVisitor) this); + SelectVisitor.super.visit(lateralSubSelect); + } + + @Override + public Void visit(TableStatement tableStatement, S context) { + tableStatement.getTable().accept(this, null); + return null; } @Override public void visit(TableStatement tableStatement) { - tableStatement.getTable().accept(this); + SelectVisitor.super.visit(tableStatement); } /** @@ -705,567 +854,886 @@ protected void init(boolean allowColumnProcessing) { } @Override - public void visit(IntervalExpression iexpr) { - if (iexpr.getExpression() != null) { - iexpr.getExpression().accept(this); + public Void visit(IntervalExpression intervalExpression, S context) { + if (intervalExpression.getExpression() != null) { + intervalExpression.getExpression().accept(this, context); } + return null; } @Override - public void visit(JdbcNamedParameter jdbcNamedParameter) { + public Void visit(JdbcNamedParameter jdbcNamedParameter, S context) { + return null; } @Override - public void visit(OracleHierarchicalExpression oexpr) { - if (oexpr.getStartExpression() != null) { - oexpr.getStartExpression().accept(this); + public Void visit(OracleHierarchicalExpression hierarchicalExpression, S context) { + if (hierarchicalExpression.getStartExpression() != null) { + hierarchicalExpression.getStartExpression().accept(this, context); } - if (oexpr.getConnectExpression() != null) { - oexpr.getConnectExpression().accept(this); + if (hierarchicalExpression.getConnectExpression() != null) { + hierarchicalExpression.getConnectExpression().accept(this, context); } + return null; } @Override - public void visit(RegExpMatchOperator rexpr) { - visitBinaryExpression(rexpr); + public Void visit(RegExpMatchOperator regExpMatchOperator, S context) { + visitBinaryExpression(regExpMatchOperator); + return null; } @Override - public void visit(JsonExpression jsonExpr) { + public Void visit(JsonExpression jsonExpr, S context) { if (jsonExpr.getExpression() != null) { - jsonExpr.getExpression().accept(this); + jsonExpr.getExpression().accept(this, context); } + return null; } @Override - public void visit(JsonOperator jsonExpr) { + public Void visit(JsonOperator jsonExpr, S context) { visitBinaryExpression(jsonExpr); + return null; } @Override - public void visit(AllColumns allColumns) { + public Void visit(AllColumns allColumns, S context) { + return null; } @Override - public void visit(AllTableColumns allTableColumns) { + public Void visit(AllTableColumns allTableColumns, S context) { + return null; } @Override - public void visit(AllValue allValue) { + public Void visit(AllValue allValue, S context) { + return null; } @Override - public void visit(IsDistinctExpression isDistinctExpression) { + public Void visit(IsDistinctExpression isDistinctExpression, S context) { visitBinaryExpression(isDistinctExpression); + return null; } @Override - public void visit(SelectItem item) { - item.getExpression().accept(this); + public Void visit(SelectItem item, S context) { + item.getExpression().accept(this, context); + return null; } @Override - public void visit(UserVariable var) { + public void visit(SelectItem selectItem) { + SelectItemVisitor.super.visit(selectItem); + } + + @Override + public Void visit(UserVariable userVariable, S context) { + return null; } @Override - public void visit(NumericBind bind) { + public Void visit(NumericBind numericBind, S context) { + return null; } @Override - public void visit(KeepExpression aexpr) { + public Void visit(KeepExpression keepExpression, S context) { + return null; } @Override - public void visit(MySQLGroupConcat groupConcat) { + public Void visit(MySQLGroupConcat groupConcat, S context) { + return null; } @Override - public void visit(Delete delete) { - visit(delete.getTable()); + public Void visit(Delete delete, S context) { + visit(delete.getTable(), context); if (delete.getUsingList() != null) { for (Table using : delete.getUsingList()) { - visit(using); + visit(using, context); } } - visitJoins(delete.getJoins()); + visitJoins(delete.getJoins(), context); if (delete.getWhere() != null) { - delete.getWhere().accept(this); + delete.getWhere().accept(this, context); } + return null; } @Override - public void visit(Update update) { - visit(update.getTable()); + public void visit(Delete delete) { + StatementVisitor.super.visit(delete); + } + + @Override + public Void visit(Update update, S context) { + visit(update.getTable(), context); if (update.getWithItemsList() != null) { for (WithItem withItem : update.getWithItemsList()) { - withItem.accept((SelectVisitor) this); + withItem.accept((SelectVisitor) this, context); } } if (update.getStartJoins() != null) { for (Join join : update.getStartJoins()) { - join.getRightItem().accept(this); + join.getRightItem().accept(this, context); } } if (update.getExpressions() != null) { for (Expression expression : update.getExpressions()) { - expression.accept(this); + expression.accept(this, context); } } if (update.getFromItem() != null) { - update.getFromItem().accept(this); + update.getFromItem().accept(this, context); } if (update.getJoins() != null) { for (Join join : update.getJoins()) { - join.getRightItem().accept(this); + join.getRightItem().accept(this, context); for (Expression expression : join.getOnExpressions()) { - expression.accept(this); + expression.accept(this, context); } } } if (update.getWhere() != null) { - update.getWhere().accept(this); + update.getWhere().accept(this, context); } + return null; } @Override - public void visit(Insert insert) { - visit(insert.getTable()); + public void visit(Update update) { + StatementVisitor.super.visit(update); + } + + @Override + public Void visit(Insert insert, S context) { + visit(insert.getTable(), context); if (insert.getWithItemsList() != null) { for (WithItem withItem : insert.getWithItemsList()) { - withItem.accept((SelectVisitor) this); + withItem.accept((SelectVisitor) this, context); } } if (insert.getSelect() != null) { - visit(insert.getSelect()); + visit(insert.getSelect(), context); } + return null; + } + + @Override + public void visit(Insert insert) { + StatementVisitor.super.visit(insert); + } + + @Override + public Void visit(Analyze analyze, S context) { + visit(analyze.getTable(), context); + return null; } + @Override public void visit(Analyze analyze) { - visit(analyze.getTable()); + StatementVisitor.super.visit(analyze); + } + + @Override + public Void visit(Drop drop, S context) { + visit(drop.getName(), context); + return null; } @Override public void visit(Drop drop) { - visit(drop.getName()); + StatementVisitor.super.visit(drop); + } + + @Override + public Void visit(Truncate truncate, S context) { + visit(truncate.getTable(), context); + return null; } @Override public void visit(Truncate truncate) { - visit(truncate.getTable()); + StatementVisitor.super.visit(truncate); + } + + @Override + public Void visit(CreateIndex createIndex, S context) { + throwUnsupported(createIndex); + return null; } @Override public void visit(CreateIndex createIndex) { - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + StatementVisitor.super.visit(createIndex); + } + + @Override + public Void visit(CreateSchema createSchema, S context) { + throwUnsupported(createSchema); + return null; } @Override - public void visit(CreateSchema aThis) { - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + public void visit(CreateSchema createSchema) { + StatementVisitor.super.visit(createSchema); } @Override - public void visit(CreateTable create) { - visit(create.getTable()); + public Void visit(CreateTable create, S context) { + visit(create.getTable(), null); if (create.getSelect() != null) { - create.getSelect().accept((SelectVisitor) this); + create.getSelect().accept((SelectVisitor) this, context); } + return null; + } + + @Override + public void visit(CreateTable createTable) { + StatementVisitor.super.visit(createTable); + } + + @Override + public Void visit(CreateView createView, S context) { + throwUnsupported(createView); + return null; } @Override public void visit(CreateView createView) { - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + StatementVisitor.super.visit(createView); + } + + @Override + public Void visit(Alter alter, S context) { + throwUnsupported(alter); + return null; } @Override public void visit(Alter alter) { - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + StatementVisitor.super.visit(alter); + } + + @Override + public Void visit(Statements statements, S context) { + for (Statement statement : statements) { + statement.accept(this, context); + } + return null; + } + + @Override + public void visit(Statements statements) { + StatementVisitor.super.visit(statements); } @Override - public void visit(Statements stmts) { - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + public Void visit(Execute execute, S context) { + throwUnsupported(execute); + return null; } @Override public void visit(Execute execute) { - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + StatementVisitor.super.visit(execute); + } + + @Override + public Void visit(SetStatement setStatement, S context) { + throwUnsupported(setStatement); + return null; } @Override public void visit(SetStatement set) { - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + StatementVisitor.super.visit(set); + } + + @Override + public Void visit(ResetStatement reset, S context) { + throwUnsupported(reset); + return null; } @Override public void visit(ResetStatement reset) { - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + StatementVisitor.super.visit(reset); } @Override - public void visit(ShowColumnsStatement set) { - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + public Void visit(ShowColumnsStatement showColumnsStatement, S context) { + throwUnsupported(showColumnsStatement); + return null; + } + + @Override + public void visit(ShowColumnsStatement showColumns) { + StatementVisitor.super.visit(showColumns); + } + + @Override + public Void visit(ShowIndexStatement showIndex, S context) { + throwUnsupported(showIndex); + return null; } @Override public void visit(ShowIndexStatement showIndex) { - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + StatementVisitor.super.visit(showIndex); } @Override - public void visit(RowConstructor rowConstructor) { + public Void visit(RowConstructor rowConstructor, S context) { for (Expression expr : rowConstructor) { - expr.accept(this); + expr.accept(this, context); } + return null; } @Override - public void visit(RowGetExpression rowGetExpression) { - rowGetExpression.getExpression().accept(this); + public Void visit(RowGetExpression rowGetExpression, S context) { + rowGetExpression.getExpression().accept(this, context); + return null; } @Override - public void visit(HexValue hexValue) { - - + public Void visit(HexValue hexValue, S context) { + return null; } @Override - public void visit(Merge merge) { - visit(merge.getTable()); + public Void visit(Merge merge, S context) { + visit(merge.getTable(), context); if (merge.getWithItemsList() != null) { for (WithItem withItem : merge.getWithItemsList()) { - withItem.accept((SelectVisitor) this); + withItem.accept((SelectVisitor) this, context); } } if (merge.getFromItem() != null) { - merge.getFromItem().accept(this); + merge.getFromItem().accept(this, context); } + return null; } @Override - public void visit(OracleHint hint) { + public void visit(Merge merge) { + StatementVisitor.super.visit(merge); + } + + @Override + public Void visit(OracleHint hint, S context) { + return null; + } + @Override + public Void visit(TableFunction tableFunction, S context) { + visit(tableFunction.getFunction(), null); + return null; } @Override public void visit(TableFunction tableFunction) { - visit(tableFunction.getFunction()); + FromItemVisitor.super.visit(tableFunction); } @Override - public void visit(AlterView alterView) { - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + public Void visit(AlterView alterView, S context) { + throwUnsupported(alterView); + return null; } @Override - public void visit(RefreshMaterializedViewStatement materializedView) { - visit(materializedView.getView()); + public void visit(AlterView alterView) { + StatementVisitor.super.visit(alterView); } @Override - public void visit(TimeKeyExpression timeKeyExpression) { + public Void visit(RefreshMaterializedViewStatement materializedView, S context) { + visit(materializedView.getView(), context); + return null; + } + @Override + public void visit(RefreshMaterializedViewStatement materializedView) { + StatementVisitor.super.visit(materializedView); } @Override - public void visit(DateTimeLiteralExpression literal) { + public Void visit(TimeKeyExpression timeKeyExpression, S context) { + return null; + } + @Override + public Void visit(DateTimeLiteralExpression literal, S context) { + return null; + } + @Override + public Void visit(Commit commit, S context) { + return null; } @Override public void visit(Commit commit) { - - + StatementVisitor.super.visit(commit); } @Override - public void visit(Upsert upsert) { - visit(upsert.getTable()); + public Void visit(Upsert upsert, S context) { + visit(upsert.getTable(), context); if (upsert.getExpressions() != null) { - upsert.getExpressions().accept(this); + upsert.getExpressions().accept(this, context); } if (upsert.getSelect() != null) { - visit(upsert.getSelect()); + visit(upsert.getSelect(), context); } + return null; } @Override - public void visit(UseStatement use) { + public void visit(Upsert upsert) { + StatementVisitor.super.visit(upsert); + } + @Override + public Void visit(UseStatement use, S context) { + return null; } @Override - public void visit(ParenthesedFromItem parenthesis) { - parenthesis.getFromItem().accept(this); + public void visit(UseStatement use) { + StatementVisitor.super.visit(use); + } + + @Override + public Void visit(ParenthesedFromItem parenthesis, S context) { + if (parenthesis.getAlias() != null) { + otherItemNames.add(parenthesis.getAlias().getName()); + } + parenthesis.getFromItem().accept(this, context); // support join keyword in fromItem - visitJoins(parenthesis.getJoins()); + visitJoins(parenthesis.getJoins(), context); + return null; + } + + @Override + public void visit(ParenthesedFromItem parenthesedFromItem) { + FromItemVisitor.super.visit(parenthesedFromItem); } /** * visit join block * - * @param parenthesis join sql block + * @param joins join sql block */ - private void visitJoins(List parenthesis) { - if (parenthesis == null) { + private void visitJoins(List joins, S context) { + if (joins == null) { return; } - for (Join join : parenthesis) { - join.getFromItem().accept(this); - join.getRightItem().accept(this); + for (Join join : joins) { + join.getFromItem().accept(this, context); + join.getRightItem().accept(this, context); for (Expression expression : join.getOnExpressions()) { - expression.accept(this); + expression.accept(this, context); } } } @Override - public void visit(Block block) { + public Void visit(Block block, S context) { if (block.getStatements() != null) { - visit(block.getStatements()); + visit(block.getStatements(), context); } + return null; } @Override - public void visit(Comment comment) { + public void visit(Block block) { + StatementVisitor.super.visit(block); + } + + @Override + public Void visit(Comment comment, S context) { if (comment.getTable() != null) { - visit(comment.getTable()); + visit(comment.getTable(), context); } if (comment.getColumn() != null) { Table table = comment.getColumn().getTable(); if (table != null) { - visit(table); + visit(table, context); } } + return null; + } + + @Override + public void visit(Comment comment) { + StatementVisitor.super.visit(comment); + } + + @Override + public Void visit(Values values, S context) { + values.getExpressions().accept(this, context); + return null; } @Override public void visit(Values values) { - values.getExpressions().accept(this); + SelectVisitor.super.visit(values); + } + + @Override + public Void visit(DescribeStatement describe, S context) { + describe.getTable().accept(this, context); + return null; } @Override public void visit(DescribeStatement describe) { - describe.getTable().accept(this); + StatementVisitor.super.visit(describe); } @Override - public void visit(ExplainStatement explain) { - if (explain.getStatement() != null) { - explain.getStatement().accept((StatementVisitor) this); + public Void visit(ExplainStatement explainStatement, S context) { + if (explainStatement.getStatement() != null) { + explainStatement.getStatement().accept((StatementVisitor) this, context); } + return null; } @Override - public void visit(NextValExpression nextVal) { + public void visit(ExplainStatement explainStatement) { + StatementVisitor.super.visit(explainStatement); + } + @Override + public Void visit(NextValExpression nextVal, S context) { + return null; } @Override - public void visit(CollateExpression col) { - col.getLeftExpression().accept(this); + public Void visit(CollateExpression collateExpression, S context) { + collateExpression.getLeftExpression().accept(this, context); + return null; } @Override - public void visit(ShowStatement aThis) { + public Void visit(ShowStatement showStatement, S context) { + return null; + } + @Override + public void visit(ShowStatement showStatement) { + StatementVisitor.super.visit(showStatement); } @Override - public void visit(SimilarToExpression expr) { + public Void visit(SimilarToExpression expr, S context) { visitBinaryExpression(expr); + return null; } @Override - public void visit(DeclareStatement aThis) { - + public Void visit(DeclareStatement declareStatement, S context) { + return null; } @Override - public void visit(Grant grant) { + public void visit(DeclareStatement declareStatement) { + StatementVisitor.super.visit(declareStatement); + } + @Override + public Void visit(Grant grant, S context) { + return null; + } + @Override + public void visit(Grant grant) { + StatementVisitor.super.visit(grant); } @Override - public void visit(ArrayExpression array) { - array.getObjExpression().accept(this); + public Void visit(ArrayExpression array, S context) { + array.getObjExpression().accept(this, context); if (array.getStartIndexExpression() != null) { - array.getIndexExpression().accept(this); + array.getIndexExpression().accept(this, context); } if (array.getStartIndexExpression() != null) { - array.getStartIndexExpression().accept(this); + array.getStartIndexExpression().accept(this, context); } if (array.getStopIndexExpression() != null) { - array.getStopIndexExpression().accept(this); + array.getStopIndexExpression().accept(this, context); } + return null; } @Override - public void visit(ArrayConstructor array) { + public Void visit(ArrayConstructor array, S context) { for (Expression expression : array.getExpressions()) { - expression.accept(this); + expression.accept(this, context); } + return null; + } + + @Override + public Void visit(CreateSequence createSequence, S context) { + throwUnsupported(createSequence); + return null; } @Override public void visit(CreateSequence createSequence) { - throw new UnsupportedOperationException( - "Finding tables from CreateSequence is not supported"); + StatementVisitor.super.visit(createSequence); + } + + @Override + public Void visit(AlterSequence alterSequence, S context) { + throwUnsupported(alterSequence); + return null; } @Override public void visit(AlterSequence alterSequence) { - throw new UnsupportedOperationException( - "Finding tables from AlterSequence is not supported"); + StatementVisitor.super.visit(alterSequence); + } + + @Override + public Void visit(CreateFunctionalStatement createFunctionalStatement, S context) { + throwUnsupported(createFunctionalStatement); + return null; } @Override public void visit(CreateFunctionalStatement createFunctionalStatement) { - throw new UnsupportedOperationException( - "Finding tables from CreateFunctionalStatement is not supported"); + StatementVisitor.super.visit(createFunctionalStatement); + } + + @Override + public Void visit(ShowTablesStatement showTables, S context) { + throwUnsupported(showTables); + return null; } @Override public void visit(ShowTablesStatement showTables) { - throw new UnsupportedOperationException( - "Finding tables from ShowTablesStatement is not supported"); + StatementVisitor.super.visit(showTables); } @Override - public void visit(TSQLLeftJoin tsqlLeftJoin) { + public Void visit(TSQLLeftJoin tsqlLeftJoin, S context) { visitBinaryExpression(tsqlLeftJoin); + return null; } @Override - public void visit(TSQLRightJoin tsqlRightJoin) { + public Void visit(TSQLRightJoin tsqlRightJoin, S context) { visitBinaryExpression(tsqlRightJoin); + return null; } @Override - public void visit(VariableAssignment var) { - var.getVariable().accept(this); - var.getExpression().accept(this); + public Void visit(StructType structType, S context) { + if (structType.getArguments() != null) { + for (SelectItem selectItem : structType.getArguments()) { + selectItem.getExpression().accept(this, context); + } + } + return null; } @Override - public void visit(XMLSerializeExpr aThis) { + public Void visit(LambdaExpression lambdaExpression, S context) { + lambdaExpression.getExpression().accept(this, context); + return null; + } + @Override + public Void visit(VariableAssignment variableAssignment, S context) { + variableAssignment.getVariable().accept(this, context); + variableAssignment.getExpression().accept(this, context); + return null; } @Override - public void visit(CreateSynonym createSynonym) { + public Void visit(XMLSerializeExpr xmlSerializeExpr, S context) { + + return null; + } + + @Override + public Void visit(CreateSynonym createSynonym, S context) { throwUnsupported(createSynonym); + return null; } - private static void throwUnsupported(T type) { - throw new UnsupportedOperationException(String.format( - "Finding tables from %s is not supported", type.getClass().getSimpleName())); + @Override + public void visit(CreateSynonym createSynonym) { + StatementVisitor.super.visit(createSynonym); + } + + @Override + public Void visit(TimezoneExpression timezoneExpression, S context) { + timezoneExpression.getLeftExpression().accept(this, context); + return null; } @Override - public void visit(TimezoneExpression aThis) { - aThis.getLeftExpression().accept(this); + public Void visit(SavepointStatement savepointStatement, S context) { + return null; } @Override - public void visit(SavepointStatement savepointStatement) {} + public void visit(SavepointStatement savepointStatement) { + StatementVisitor.super.visit(savepointStatement); + } + + @Override + public Void visit(RollbackStatement rollbackStatement, S context) { + + return null; + } @Override public void visit(RollbackStatement rollbackStatement) { + StatementVisitor.super.visit(rollbackStatement); + } + @Override + public Void visit(AlterSession alterSession, S context) { + + return null; } @Override public void visit(AlterSession alterSession) { - + StatementVisitor.super.visit(alterSession); } @Override - public void visit(JsonAggregateFunction expression) { + public Void visit(JsonAggregateFunction expression, S context) { Expression expr = expression.getExpression(); if (expr != null) { - expr.accept(this); + expr.accept(this, context); } expr = expression.getFilterExpression(); if (expr != null) { - expr.accept(this); + expr.accept(this, context); } + return null; } @Override - public void visit(JsonFunction expression) { + public Void visit(JsonFunction expression, S context) { for (JsonFunctionExpression expr : expression.getExpressions()) { - expr.getExpression().accept(this); + expr.getExpression().accept(this, context); } + return null; } @Override - public void visit(ConnectByRootOperator connectByRootOperator) { - connectByRootOperator.getColumn().accept(this); + public Void visit(ConnectByRootOperator connectByRootOperator, S context) { + connectByRootOperator.getColumn().accept(this, context); + return null; } - public void visit(IfElseStatement ifElseStatement) { - ifElseStatement.getIfStatement().accept(this); + @Override + public Void visit(IfElseStatement ifElseStatement, S context) { + ifElseStatement.getIfStatement().accept(this, context); if (ifElseStatement.getElseStatement() != null) { - ifElseStatement.getElseStatement().accept(this); + ifElseStatement.getElseStatement().accept(this, context); } + return null; } - public void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter) { - oracleNamedFunctionParameter.getExpression().accept(this); + @Override + public void visit(IfElseStatement ifElseStatement) { + StatementVisitor.super.visit(ifElseStatement); } @Override - public void visit(RenameTableStatement renameTableStatement) { + public Void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, S context) { + oracleNamedFunctionParameter.getExpression().accept(this, context); + return null; + } + + @Override + public Void visit(RenameTableStatement renameTableStatement, S context) { for (Map.Entry e : renameTableStatement.getTableNames()) { - e.getKey().accept(this); - e.getValue().accept(this); + e.getKey().accept(this, context); + e.getValue().accept(this, context); } + return null; } @Override - public void visit(PurgeStatement purgeStatement) { + public void visit(RenameTableStatement renameTableStatement) { + StatementVisitor.super.visit(renameTableStatement); + } + + @Override + public Void visit(PurgeStatement purgeStatement, S context) { if (purgeStatement.getPurgeObjectType() == PurgeObjectType.TABLE) { - ((Table) purgeStatement.getObject()).accept(this); + ((Table) purgeStatement.getObject()).accept(this, context); } + return null; + } + + @Override + public void visit(PurgeStatement purgeStatement) { + StatementVisitor.super.visit(purgeStatement); + } + + @Override + public Void visit(AlterSystemStatement alterSystemStatement, S context) { + // no tables involved in this statement + return null; } @Override public void visit(AlterSystemStatement alterSystemStatement) { + StatementVisitor.super.visit(alterSystemStatement); + } + + @Override + public Void visit(UnsupportedStatement unsupportedStatement, S context) { // no tables involved in this statement + return null; } @Override public void visit(UnsupportedStatement unsupportedStatement) { - // no tables involved in this statement + StatementVisitor.super.visit(unsupportedStatement); } @Override - public void visit(GeometryDistance geometryDistance) { + public Void visit(GeometryDistance geometryDistance, S context) { visitBinaryExpression(geometryDistance); + return null; } } diff --git a/src/main/java/net/sf/jsqlparser/util/cnfexpression/CNFConverter.java b/src/main/java/net/sf/jsqlparser/util/cnfexpression/CNFConverter.java index fbb4e8499..e1053acfd 100644 --- a/src/main/java/net/sf/jsqlparser/util/cnfexpression/CNFConverter.java +++ b/src/main/java/net/sf/jsqlparser/util/cnfexpression/CNFConverter.java @@ -14,189 +14,72 @@ import java.util.List; import java.util.Queue; import java.util.Stack; + import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.NotExpression; /** - * This class handles the conversion from a normal expression tree into - * the CNF form. - * - * Here is the definition of CNF form: - * https://en.wikipedia.org/wiki/Conjunctive_normal_form - * + * This class handles the conversion from a normal expression tree into the CNF form. + *

+ * Here is the definition of CNF form: https://en.wikipedia.org/wiki/Conjunctive_normal_form + *

* Basically it will follow these steps: - * - * To help understanding, I will generate an example: - * Here is the original tree: - * OR - * / \ - * OR NOT - * / \ | - * NOT H AND - * | / \ - * NOT G OR - * | / \ - * F H NOT - * | - * OR - * / \ - * AND L - * / \ - * ( ) ( ) - * | | - * J K - * - * 1. rebuild the tree by replacing the "and" and "or" operators - * (which are binary) into their counterparts node that could hold - * multiple elements. Also, leave out the parenthesis node between the - * conditional operators to make the tree uniform. - * - * After the transform, the result should be like this: - * OR(M) - * / \ - * OR(M) NOT - * / \ | - * NOT H AND(M) - * | / \ - * NOT G OR(M) - * | / \ - * F H NOT - * | - * OR(M) - * / \ - * AND(M) L - * / \ - * J K - * - * 2. push the not operators into the bottom of the expression. That - * means the not operator will be the root of the expression tree - * where no "and" or "or" exists. Be sure use the De Morgan's law + *

+ * To help understanding, I will generate an example: Here is the original tree: OR / \ OR NOT / \ | + * NOT H AND | / \ NOT G OR | / \ F H NOT | OR / \ AND L / \ ( ) ( ) | | J K + *

+ * 1. rebuild the tree by replacing the "and" and "or" operators (which are binary) into their + * counterparts node that could hold multiple elements. Also, leave out the parenthesis node between + * the conditional operators to make the tree uniform. + *

+ * After the transform, the result should be like this: OR(M) / \ OR(M) NOT / \ | NOT H AND(M) | / \ + * NOT G OR(M) | / \ F H NOT | OR(M) / \ AND(M) L / \ J K + *

+ * 2. push the not operators into the bottom of the expression. That means the not operator will be + * the root of the expression tree where no "and" or "or" exists. Be sure use the De Morgan's law * and double not law. - * - * How to use De Morgan law: - * For example, here is the original expression tree: - * NOT - * | - * AND(M) - * / \ - * G H - * - * After we use the De Morgan law, the result should be like this: - * OR(M) - * / \ - * NOT NOT - * | | - * G H - * - * After the transform, the result should be like this: - * OR(M) - * / \ - * OR(M) OR(M) - * / \ / \ - * F H NOT AND(M) - * | / \ - * G NOT OR(M) - * | / \ - * H AND(M) L - * / \ - * J K - * - * 3. gather all the adjacent "and" or "or" operator together. - * After doing that, the expression tree will be presented as: - * all the and expression will be in either odd or even levels, - * this will be the same for the or operator. - * - * After the transform, the expression tree should be like this: - * OR(M) - * / / \ \ - * F H NOT AND(M) - * | / \ - * G NOT OR(M) - * | / \ - * H AND(M) L - * / \ - * J K - * - * 4. push the and operator upwards until the root is an and - * operator and all the children are or operators with multiple - * components. At this time we get the result: an expression in CNF form. + *

+ * How to use De Morgan law: For example, here is the original expression tree: NOT | AND(M) / \ G H + *

+ * After we use the De Morgan law, the result should be like this: OR(M) / \ NOT NOT | | G H + *

+ * After the transform, the result should be like this: OR(M) / \ OR(M) OR(M) / \ / \ F H NOT AND(M) + * | / \ G NOT OR(M) | / \ H AND(M) L / \ J K + *

+ * 3. gather all the adjacent "and" or "or" operator together. After doing that, the expression tree + * will be presented as: all the and expression will be in either odd or even levels, this will be + * the same for the or operator. + *

+ * After the transform, the expression tree should be like this: OR(M) / / \ \ F H NOT AND(M) | / \ + * G NOT OR(M) | / \ H AND(M) L / \ J K + *

+ * 4. push the and operator upwards until the root is an and operator and all the children are or + * operators with multiple components. At this time we get the result: an expression in CNF form. * How do we push and up? Use distribution law! - * - * For example, here is the way to push the and up and merge them. - * OR - * / \ - * AND L - * / \ - * J K - * - * In the normal form, it could be: (J AND K) OR L. - * If we apply the distribution law, we will get the result like this: - * (J OR L) AND (K OR L), the tree form of this should be like: - * AND - * / \ - * OR OR - * / \ / \ - * J L K L - * - * So after we push the AND at the deepest level up and merge it with the - * existing add, we get this result. - * OR(M) - * / / \ \ - * F H NOT AND(M) - * | / | \ - * G NOT OR(M) OR(M) - * | / \ / \ - * H J L K L - * - * Now let us push the and up and we will get the result like this: - * AND(M) - * / | \ - * OR(M) OR(M) OR(M) - * / / \ \ / / | \ \ / / | \ \ - * F H NOT NOT F H NOT J L F H NOT K L - * | | | | - * G H G G - * - * 5. The last step, convert the Multiple Expression back to the binary - * form. Note the final tree shall be left-inclined. - * - * The final expression tree shall be like this: - * AND - * / \ - * AND ( ) - * / \ | - * ( ) ( ) part1 - * | | - * OR part2 - * / \ - * OR NOT - * / \ | - * OR NOT H - * / \ | - * F H G - * - * part1: OR - * / \ - * OR L - * / \ - * OR K - * / \ - * OR NOT - * / \ | - * F H G - * - * part2: OR - * / \ - * OR L - * / \ - * OR J - * / \ - * OR NOT - * / \ | - * F H G + *

+ * For example, here is the way to push the and up and merge them. OR / \ AND L / \ J K + *

+ * In the normal form, it could be: (J AND K) OR L. If we apply the distribution law, we will get + * the result like this: (J OR L) AND (K OR L), the tree form of this should be like: AND / \ OR OR + * / \ / \ J L K L + *

+ * So after we push the AND at the deepest level up and merge it with the existing add, we get this + * result. OR(M) / / \ \ F H NOT AND(M) | / | \ G NOT OR(M) OR(M) | / \ / \ H J L K L + *

+ * Now let us push the and up and we will get the result like this: AND(M) / | \ OR(M) OR(M) OR(M) / + * / \ \ / / | \ \ / / | \ \ F H NOT NOT F H NOT J L F H NOT K L | | | | G H G G + *

+ * 5. The last step, convert the Multiple Expression back to the binary form. Note the final tree + * shall be left-inclined. + *

+ * The final expression tree shall be like this: AND / \ AND ( ) / \ | ( ) ( ) part1 | | OR part2 / + * \ OR NOT / \ | OR NOT H / \ | F H G + *

+ * part1: OR / \ OR L / \ OR K / \ OR NOT / \ | F H G + *

+ * part2: OR / \ OR L / \ OR J / \ OR NOT / \ | F H G * * @author messfish - * */ public class CNFConverter { @@ -210,31 +93,19 @@ public class CNFConverter { private Expression child; // these two variable mainly serves as nodes that traverse through // the expression tree to change the structure of expression tree. - // notice temp1 will be settled as the root and temp2 will be + // notice temp1 will be settled as the root and temp2 will be // settled as the dummy root. private boolean isUsed = false; - private class Mule { - - private Expression parent; - private Expression child; - private int level; - - private Mule(Expression parent, Expression child, int level) { - this.parent = parent; - this.child = child; - this.level = level; - } - } - public static Expression convertToCNF(Expression expr) { CNFConverter cnf = new CNFConverter(); return cnf.convert(expr); } /** - * this method takes an expression tree and converts that into a CNF form. Notice the 5 steps shown above will turn - * into 5 different methods. For the sake of testing, I set them public. return the converted expression. + * this method takes an expression tree and converts that into a CNF form. Notice the 5 steps + * shown above will turn into 5 different methods. For the sake of testing, I set them public. + * return the converted expression. * * @param express the original expression tree. */ @@ -247,10 +118,11 @@ private Expression convert(Expression express) } reorder(express); pushNotDown(); - /* notice for the gather() function, we do not change the variable - * that points to the root by pointing to others. Also, we do not - * change those temp variables. So there is no need to set those - * variables back to their modified state. */ + /* + * notice for the gather() function, we do not change the variable that points to the root + * by pointing to others. Also, we do not change those temp variables. So there is no need + * to set those variables back to their modified state. + */ gather(); pushAndUp(); changeBack(); @@ -258,8 +130,8 @@ private Expression convert(Expression express) } /** - * this is the first step that rebuild the expression tree. Use the standard specified in the above class. Traverse - * the original tree recursively and rebuild the tree from that. + * this is the first step that rebuild the expression tree. Use the standard specified in the + * above class. Traverse the original tree recursively and rebuild the tree from that. * * @param express the original expression tree. */ @@ -271,15 +143,17 @@ private void reorder(Expression express) { } /** - * This method is used to deal with pushing not operators down. Since it needs an extra parameter, I will create a - * new method to handle this. + * This method is used to deal with pushing not operators down. Since it needs an extra + * parameter, I will create a new method to handle this. */ private void pushNotDown() { /* set the two temp parameters to their staring point. */ temp1 = root; temp2 = dummy; - /* I set it to zero since if the modification happens at the root, - * the parent will have the correct pointer to the children. */ + /* + * I set it to zero since if the modification happens at the root, the parent will have the + * correct pointer to the children. + */ pushNot(0); /* do not forget to set the operators back! */ root = ((MultiAndExpression) dummy).getChild(0); @@ -288,17 +162,20 @@ private void pushNotDown() { } /** - * This method is the helper function to push not operators down. traverse the tree thoroughly, when we meet the not - * operator. We only need to consider these three operators: MultiAndOperator, MultiOrOperator, NotOperator. Handle - * them in a seperate way. when we finish the traverse, the expression tree will have all the not operators pushed - * as downwards as they could. In the method, I use two global variables: temp1 and temp2 to traverse the expression + * This method is the helper function to push not operators down. traverse the tree thoroughly, + * when we meet the not operator. We only need to consider these three operators: + * MultiAndOperator, MultiOrOperator, NotOperator. Handle them in a seperate way. when we finish + * the traverse, the expression tree will have all the not operators pushed as downwards as they + * could. In the method, I use two global variables: temp1 and temp2 to traverse the expression * tree. Notice that temp2 will always be the parent of temp1. * * @param index the index of the children appeared in parents array. */ private void pushNot(int index) { - /* what really matters is the three logical operators: - * and, or, not. so we only deal with these three operators. */ + /* + * what really matters is the three logical operators: and, or, not. so we only deal with + * these three operators. + */ if (temp1 instanceof MultiAndExpression) { MultiAndExpression and = (MultiAndExpression) temp1; for (int i = 0; i < and.size(); i++) { @@ -319,8 +196,8 @@ private void pushNot(int index) { } /** - * This function mainly deals with pushing not operators down. check the child. If it is not a logic operator(and or - * or). stop at that point. Else use De Morgan law to push not downwards. + * This function mainly deals with pushing not operators down. check the child. If it is not a + * logic operator(and or or). stop at that point. Else use De Morgan law to push not downwards. * * @param index the index of the children appeared in parents array. */ @@ -331,29 +208,31 @@ private void handleNot(int index) { child = ((NotExpression) child).getExpression(); nums++; } - /* if the number of not operators are even. we could get - * rid of all the not operators. set the child to the parent. */ + /* + * if the number of not operators are even. we could get rid of all the not operators. set + * the child to the parent. + */ if (nums % 2 == 0) { ((MultipleExpression) temp2).setChild(index, child); temp1 = child; pushNot(-1); } else { - /* otherwise there will be one not left to push. - * if the child is not these two types of operators. - * that means we reach the leaves of the logical part. - * set a new not operator whose child is the current one - * and connect that operator with the parent and return. */ + /* + * otherwise there will be one not left to push. if the child is not these two types of + * operators. that means we reach the leaves of the logical part. set a new not operator + * whose child is the current one and connect that operator with the parent and return. + */ if (!(child instanceof MultiAndExpression) && !(child instanceof MultiOrExpression)) { -// if (child instanceof LikeExpression) { -// ((LikeExpression) child).setNot(); -// } else if (child instanceof BinaryExpression) { -// ((BinaryExpression) child).setNot(); -// } else { + // if (child instanceof LikeExpression) { + // ((LikeExpression) child).setNot(); + // } else if (child instanceof BinaryExpression) { + // ((BinaryExpression) child).setNot(); + // } else { child = new NotExpression(child); -// } + // } ((MultipleExpression) temp2).setChild(index, child); -// return; + // return; } else if (child instanceof MultiAndExpression) { MultiAndExpression and = (MultiAndExpression) child; List list = new ArrayList(); @@ -383,9 +262,10 @@ private void handleNot(int index) { } /** - * This method serves as dealing with the third step. It is used to put all the adjacent same multi operators - * together. BFS the tree and do it node by node. In the end we will get the tree where all the same multi operators - * store in the same odd level of the tree or in the same even level of the tree. + * This method serves as dealing with the third step. It is used to put all the adjacent same + * multi operators together. BFS the tree and do it node by node. In the end we will get the + * tree where all the same multi operators store in the same odd level of the tree or in the + * same even level of the tree. */ @SuppressWarnings({"PMD.CyclomaticComplexity"}) private void gather() { @@ -393,9 +273,11 @@ private void gather() { queue.offer(temp1); while (!queue.isEmpty()) { Expression express = queue.poll(); - /* at this level, we only deal with "multi and" and "multi or" - * operators, so we only consider these two operators. - * that means we do nothing if the operator is not those two. */ + /* + * at this level, we only deal with "multi and" and "multi or" operators, so we only + * consider these two operators. that means we do nothing if the operator is not those + * two. + */ if (express instanceof MultiAndExpression) { MultiAndExpression and = (MultiAndExpression) express; while (true) { @@ -407,14 +289,17 @@ private void gather() { break; } } - /* if the index is the size of the multi operator, - * that means this is already valid. jump out of the loop. */ + /* + * if the index is the size of the multi operator, that means this is already + * valid. jump out of the loop. + */ if (index == and.size()) { break; } else { - /* if not, remove the child out and push the child of that child - * in the operator, starting from the index where the child - * is removed. */ + /* + * if not, remove the child out and push the child of that child in the + * operator, starting from the index where the child is removed. + */ and.removeChild(index); MultipleExpression order = (MultipleExpression) get; for (int i = 0; i < order.size(); i++) { @@ -439,14 +324,17 @@ private void gather() { break; } } - /* if the index is the size of the multi operator, - * that means this is already valid. jump out of the loop. */ + /* + * if the index is the size of the multi operator, that means this is already + * valid. jump out of the loop. + */ if (index == or.size()) { break; } else { - /* if not, remove the child out and push the child of that child - * in the operator, starting from the index where the child - * is removed. */ + /* + * if not, remove the child out and push the child of that child in the + * operator, starting from the index where the child is removed. + */ or.removeChild(index); MultipleExpression order = (MultipleExpression) get; for (int i = 0; i < order.size(); i++) { @@ -464,10 +352,10 @@ private void gather() { } /** - * First, BFS the tree and gather all the or operators and their parents into a stack. Next, pop them out and push - * the and operators under the or operators upwards(if there are). Do this level by level, which means during each - * level we will call the gather() method to make the tree uniform. When we move out of the stack. The expression - * tree shall be in CNF form. + * First, BFS the tree and gather all the or operators and their parents into a stack. Next, pop + * them out and push the and operators under the or operators upwards(if there are). Do this + * level by level, which means during each level we will call the gather() method to make the + * tree uniform. When we move out of the stack. The expression tree shall be in CNF form. */ private void pushAndUp() { Queue queue = new LinkedList(); @@ -475,8 +363,10 @@ private void pushAndUp() { Mule root = new Mule(temp2, temp1, 0); queue.offer(root); int level = 1; - /* do the BFS and store valid mule into the stack. Notice the - * first parameter is parent and the second parameter is children. */ + /* + * do the BFS and store valid mule into the stack. Notice the first parameter is parent and + * the second parameter is children. + */ while (!queue.isEmpty()) { int size = queue.size(); for (int i = 0; i < size; i++) { @@ -507,17 +397,20 @@ private void pushAndUp() { this.root = ((MultiAndExpression) dummy).getChild(0); temp1 = this.root; temp2 = dummy; - /* at last, remember to gather again since there are no gather() - * method called if there are some movements on the root. */ + /* + * at last, remember to gather again since there are no gather() method called if there are + * some movements on the root. + */ gather(); } /** - * This helper function is used to deal with pushing and up: generally, pop the top element out of the stack, use - * BFS to traverse the tree and push and up. It will case the expression tree to have the and as the new root and - * multiple or as the children. Push them on the queue and repeat the same process until the newly generated or - * operator does not have any and operators in it(which means no elements will be added into the queue). when one - * level is finished, regroup the tree. Do this until the stack is empty, the result will be the expression in CNF + * This helper function is used to deal with pushing and up: generally, pop the top element out + * of the stack, use BFS to traverse the tree and push and up. It will case the expression tree + * to have the and as the new root and multiple or as the children. Push them on the queue and + * repeat the same process until the newly generated or operator does not have any and operators + * in it(which means no elements will be added into the queue). when one level is finished, + * regroup the tree. Do this until the stack is empty, the result will be the expression in CNF * form. * * @param stack the stack stores a list of combined data. @@ -536,16 +429,20 @@ private void pushAnd(Stack stack) { level = mule.level; } Queue queue = new LinkedList(); - /* this time we do not need to take down the level of the - * tree, so simply set a 0 to the last parameter. */ + /* + * this time we do not need to take down the level of the tree, so simply set a 0 to the + * last parameter. + */ Mule combined = new Mule(mule.parent, mule.child, 0); queue.offer(combined); while (!queue.isEmpty()) { Mule get = queue.poll(); Expression parent = get.parent; Expression child = get.child; - /* based on the code above, the stack only have the expression - * which they are multi operators. so safely convert them. */ + /* + * based on the code above, the stack only have the expression which they are multi + * operators. so safely convert them. + */ MultipleExpression children = (MultipleExpression) child; int index = 0; MultiAndExpression and = null; @@ -576,10 +473,11 @@ private void pushAnd(Stack stack) { } /** - * This is the final step of the CNF conversion: now we have the Expression tree that has one multiple and - * expression with a list of multiple or expression as the child. So we need to convert the multiple expression back - * to the binary counterparts. Note the converted tree is left inclined. Also I attach a parenthesis node before the - * or expression that is attached to the and expression to make the generated result resembles the CNF form. + * This is the final step of the CNF conversion: now we have the Expression tree that has one + * multiple and expression with a list of multiple or expression as the child. So we need to + * convert the multiple expression back to the binary counterparts. Note the converted tree is + * left inclined. Also I attach a parenthesis node before the or expression that is attached to + * the and expression to make the generated result resembles the CNF form. */ private void changeBack() { if (!(root instanceof MultiAndExpression)) { @@ -592,4 +490,17 @@ private void changeBack() { root = CloneHelper.changeBack(false, temp); } + private class Mule { + + private Expression parent; + private Expression child; + private int level; + + private Mule(Expression parent, Expression child, int level) { + this.parent = parent; + this.child = child; + this.level = level; + } + } + } diff --git a/src/main/java/net/sf/jsqlparser/util/cnfexpression/CloneHelper.java b/src/main/java/net/sf/jsqlparser/util/cnfexpression/CloneHelper.java index 0936fab66..c0e5293e2 100644 --- a/src/main/java/net/sf/jsqlparser/util/cnfexpression/CloneHelper.java +++ b/src/main/java/net/sf/jsqlparser/util/cnfexpression/CloneHelper.java @@ -9,21 +9,22 @@ */ package net.sf.jsqlparser.util.cnfexpression; -import java.util.ArrayList; -import java.util.List; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.NotExpression; -import net.sf.jsqlparser.expression.Parenthesis; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; + +import java.util.ArrayList; +import java.util.List; /** - * This class is mainly used for handling the cloning of an expression tree. Note this is the shallow copy of the tree. - * That means I do not modify or copy the expression other than these expressions: AND, OR, NOT, (), MULTI-AND, - * MULTI-OR. Since the CNF conversion only change the condition part of the tree. + * This class is mainly used for handling the cloning of an expression tree. Note this is the + * shallow copy of the tree. That means I do not modify or copy the expression other than these + * expressions: AND, OR, NOT, (), MULTI-AND, MULTI-OR. Since the CNF conversion only change the + * condition part of the tree. * * @author messfish - * */ class CloneHelper { @@ -31,10 +32,11 @@ public static Expression modify(Expression express) { if (express instanceof NotExpression) { return new NotExpression(modify(((NotExpression) express).getExpression())); } - if (express instanceof Parenthesis) { - Parenthesis parenthesis = (Parenthesis) express; - Expression result = modify(parenthesis.getExpression()); - return result; + if (express instanceof ParenthesedExpressionList) { + ParenthesedExpressionList parenthesis = (ParenthesedExpressionList) express; + if (parenthesis.size() == 1) { + return modify(parenthesis.get(0)); + } } if (express instanceof AndExpression) { AndExpression and = (AndExpression) express; @@ -42,9 +44,9 @@ public static Expression modify(Expression express) { list.add(modify(and.getLeftExpression())); list.add(modify(and.getRightExpression())); MultiAndExpression result = new MultiAndExpression(list); -// if (and.isNot()) { -// return new NotExpression(result); -// } + // if (and.isNot()) { + // return new NotExpression(result); + // } return result; } if (express instanceof OrExpression) { @@ -53,24 +55,24 @@ public static Expression modify(Expression express) { list.add(modify(or.getLeftExpression())); list.add(modify(or.getRightExpression())); MultiOrExpression result = new MultiOrExpression(list); -// if (or.isNot()) { -// return new NotExpression(result); -// } + // if (or.isNot()) { + // return new NotExpression(result); + // } return result; } -// if (express instanceof BinaryExpression) { -// BinaryExpression binary = (BinaryExpression) express; -// if (binary.isNot()) { -// binary.removeNot(); -// return new NotExpression(modify(binary)); -// } -// } + // if (express instanceof BinaryExpression) { + // BinaryExpression binary = (BinaryExpression) express; + // if (binary.isNot()) { + // binary.removeNot(); + // return new NotExpression(modify(binary)); + // } + // } return express; } /** - * This method is used to copy the expression which happens at step four. I only copy the conditional expressions - * since the CNF only changes the conditional part. + * This method is used to copy the expression which happens at step four. I only copy the + * conditional expressions since the CNF only changes the conditional part. * * @param express the expression that will be copied. * @return the copied expression. @@ -85,16 +87,18 @@ public static Expression shallowCopy(Expression express) { if (express instanceof MultiAndExpression) { return new MultiAndExpression(list); } - /* since there only two possibilities of the multiple expression, - * so after the if condition, it is certain this is a multi-or. */ + /* + * since there only two possibilities of the multiple expression, so after the if + * condition, it is certain this is a multi-or. + */ return new MultiOrExpression(list); } return express; } /** - * This helper method is used to change the multiple expression into the binary form, respectively and return the - * root of the expression tree. + * This helper method is used to change the multiple expression into the binary form, + * respectively and return the root of the expression tree. * * @param isMultiOr variable tells whether the expression is or. * @param exp the expression that needs to be converted. @@ -121,26 +125,26 @@ public static Expression changeBack(Boolean isMultiOr, Expression exp) { result = compressed; } if (isMultiOr) { - return new Parenthesis(result.get(0)); + return new ParenthesedExpressionList<>(result.get(0)); } else { return result.get(0); } -// MultipleExpression changed = (MultipleExpression) exp; -// Expression result = changed.getChild(0); -// for (int i = 1; i < changed.size(); i++) { -// Expression left = result; -// Expression right = changed.getChild(i); -// if (isMultiOr) { -// result = new OrExpression(left, right); -// } else { -// result = new AndExpression(left, right); -// } -// } -// if (isMultiOr) { -// return new Parenthesis(result); -// } -// return result; + // MultipleExpression changed = (MultipleExpression) exp; + // Expression result = changed.getChild(0); + // for (int i = 1; i < changed.size(); i++) { + // Expression left = result; + // Expression right = changed.getChild(i); + // if (isMultiOr) { + // result = new OrExpression(left, right); + // } else { + // result = new AndExpression(left, right); + // } + // } + // if (isMultiOr) { + // return new Parenthesis(result); + // } + // return result; } } diff --git a/src/main/java/net/sf/jsqlparser/util/cnfexpression/MultiAndExpression.java b/src/main/java/net/sf/jsqlparser/util/cnfexpression/MultiAndExpression.java index a33c81009..03af12cdc 100644 --- a/src/main/java/net/sf/jsqlparser/util/cnfexpression/MultiAndExpression.java +++ b/src/main/java/net/sf/jsqlparser/util/cnfexpression/MultiAndExpression.java @@ -17,7 +17,6 @@ * This helper class is mainly used for handling the CNF conversion. * * @author messfish - * */ public final class MultiAndExpression extends MultipleExpression { diff --git a/src/main/java/net/sf/jsqlparser/util/cnfexpression/MultipleExpression.java b/src/main/java/net/sf/jsqlparser/util/cnfexpression/MultipleExpression.java index f37e823cd..b06b85399 100644 --- a/src/main/java/net/sf/jsqlparser/util/cnfexpression/MultipleExpression.java +++ b/src/main/java/net/sf/jsqlparser/util/cnfexpression/MultipleExpression.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.util.cnfexpression; import java.util.List; + import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.expression.NullValue; @@ -19,7 +20,6 @@ * This is a helper class that mainly used for handling the CNF conversion. * * @author messfish - * */ public abstract class MultipleExpression extends ASTNodeAccessImpl implements Expression { @@ -34,8 +34,8 @@ public int size() { } @Override - public void accept(ExpressionVisitor expressionVisitor) { - expressionVisitor.visit(new NullValue()); + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(new NullValue(), context); } public List getList() { diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/AbstractDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/AbstractDeParser.java index 4a31a7ace..d9915eb62 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/AbstractDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/AbstractDeParser.java @@ -27,9 +27,9 @@ protected AbstractDeParser(StringBuilder buffer) { } public static void deparseUpdateSets(List updateSets, StringBuilder buffer, - ExpressionVisitor visitor) { - ExpressionListDeParser expressionListDeParser = - new ExpressionListDeParser(visitor, buffer); + ExpressionVisitor visitor) { + ExpressionListDeParser expressionListDeParser = + new ExpressionListDeParser<>(visitor, buffer); int j = 0; if (updateSets != null) { for (UpdateSet updateSet : updateSets) { diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/AlterViewDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/AlterViewDeParser.java index 99c310941..07d6c1907 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/AlterViewDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/AlterViewDeParser.java @@ -15,7 +15,7 @@ public class AlterViewDeParser extends AbstractDeParser { - private SelectVisitor selectVisitor; + private final SelectVisitor selectVisitor; public AlterViewDeParser(StringBuilder buffer) { super(buffer); @@ -25,7 +25,7 @@ public AlterViewDeParser(StringBuilder buffer) { selectVisitor = selectDeParser; } - public AlterViewDeParser(StringBuilder buffer, SelectVisitor selectVisitor) { + public AlterViewDeParser(StringBuilder buffer, SelectVisitor selectVisitor) { super(buffer); this.selectVisitor = selectVisitor; } @@ -43,7 +43,7 @@ public void deParse(AlterView alterView) { } buffer.append(" AS "); - alterView.getSelect().accept(selectVisitor); + alterView.getSelect().accept(selectVisitor, null); } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/CreateSequenceDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/CreateSequenceDeParser.java index b7206691d..a97a12cb3 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/CreateSequenceDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/CreateSequenceDeParser.java @@ -1,11 +1,6 @@ /* - * #%L - * JSQLParser library - * %% - * Copyright (C) 2004 - 2020 JSQLParser - * %% - * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 - * #L% + * #%L JSQLParser library %% Copyright (C) 2004 - 2020 JSQLParser %% Dual licensed under GNU LGPL + * 2.1 or Apache License 2.0 #L% */ package net.sf.jsqlparser.util.deparser; @@ -15,7 +10,7 @@ * A class to de-parse (that is, transform from JSqlParser hierarchy into a string) a * {@link net.sf.jsqlparser.statement.create.sequence.CreateSequence} */ -public class CreateSequenceDeParser extends AbstractDeParser{ +public class CreateSequenceDeParser extends AbstractDeParser { /** * @param buffer the buffer that will be filled with the CreatSequence diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/CreateTableDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/CreateTableDeParser.java index d930e944c..72a82c862 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/CreateTableDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/CreateTableDeParser.java @@ -41,8 +41,9 @@ public void deParse(CreateTable createTable) { if (createTable.isUnlogged()) { buffer.append("UNLOGGED "); } - String params = PlainSelect.getStringList(createTable.getCreateOptionsStrings(), false, false); - if (!"".equals(params)) { + String params = + PlainSelect.getStringList(createTable.getCreateOptionsStrings(), false, false); + if (!params.isEmpty()) { buffer.append(params).append(' '); } @@ -63,7 +64,8 @@ public void deParse(CreateTable createTable) { } if (createTable.getColumnDefinitions() != null) { buffer.append(" ("); - for (Iterator iter = createTable.getColumnDefinitions().iterator(); iter.hasNext();) { + for (Iterator iter = + createTable.getColumnDefinitions().iterator(); iter.hasNext();) { ColumnDefinition columnDefinition = iter.next(); buffer.append(columnDefinition.getColumnName()); buffer.append(" "); @@ -96,7 +98,8 @@ public void deParse(CreateTable createTable) { } if (createTable.getRowMovement() != null) { - buffer.append(' ').append(createTable.getRowMovement().getMode().toString()).append(" ROW MOVEMENT"); + buffer.append(' ').append(createTable.getRowMovement().getMode().toString()) + .append(" ROW MOVEMENT"); } if (createTable.getSelect() != null) { buffer.append(" AS "); @@ -104,7 +107,7 @@ public void deParse(CreateTable createTable) { buffer.append("("); } Select sel = createTable.getSelect(); - sel.accept(this.statementDeParser); + sel.accept(this.statementDeParser, null); if (createTable.isSelectParenthesis()) { buffer.append(")"); } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/CreateViewDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/CreateViewDeParser.java index c0afab53e..8c77ddfe3 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/CreateViewDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/CreateViewDeParser.java @@ -18,7 +18,7 @@ public class CreateViewDeParser extends AbstractDeParser { - private final SelectVisitor selectVisitor; + private final SelectVisitor selectVisitor; public CreateViewDeParser(StringBuilder buffer) { super(buffer); @@ -29,7 +29,7 @@ public CreateViewDeParser(StringBuilder buffer) { selectVisitor = selectDeParser; } - public CreateViewDeParser(StringBuilder buffer, SelectVisitor selectVisitor) { + public CreateViewDeParser(StringBuilder buffer, SelectVisitor selectVisitor) { super(buffer); this.selectVisitor = selectVisitor; } @@ -81,7 +81,7 @@ public void deParse(CreateView createView) { buffer.append(" AS "); Select select = createView.getSelect(); - select.accept(selectVisitor); + select.accept(selectVisitor, null); if (createView.isWithReadOnly()) { buffer.append(" WITH READ ONLY"); } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/DeclareStatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/DeclareStatementDeParser.java index 42951127b..3e1db92e9 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/DeclareStatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/DeclareStatementDeParser.java @@ -15,9 +15,10 @@ public class DeclareStatementDeParser extends AbstractDeParser { - private ExpressionVisitor expressionVisitor; + private ExpressionVisitor expressionVisitor; - public DeclareStatementDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { + public DeclareStatementDeParser(ExpressionVisitor expressionVisitor, + StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; } @@ -28,7 +29,7 @@ public void deParse(DeclareStatement declare) { buffer.append("DECLARE "); if (declare.getUserVariable() != null) { - declare.getUserVariable().accept(expressionVisitor); + declare.getUserVariable().accept(expressionVisitor, null); } if (declare.getType() == DeclareType.AS) { @@ -54,24 +55,24 @@ public void deParse(DeclareStatement declare) { } DeclareStatement.TypeDefExpr type = declare.getTypeDefinitions().get(i); if (type.userVariable != null) { - type.userVariable.accept(expressionVisitor); + type.userVariable.accept(expressionVisitor, null); buffer.append(" "); } buffer.append(type.colDataType.toString()); if (type.defaultExpr != null) { buffer.append(" = "); - type.defaultExpr.accept(expressionVisitor); + type.defaultExpr.accept(expressionVisitor, null); } } } } } - public ExpressionVisitor getExpressionVisitor() { + public ExpressionVisitor getExpressionVisitor() { return expressionVisitor; } - public void setExpressionVisitor(ExpressionVisitor visitor) { + public void setExpressionVisitor(ExpressionVisitor visitor) { expressionVisitor = visitor; } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java index ef4d0922d..52e5a6671 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java @@ -22,13 +22,15 @@ public class DeleteDeParser extends AbstractDeParser { - private ExpressionVisitor expressionVisitor = new ExpressionVisitorAdapter(); + private ExpressionVisitor expressionVisitor = + new ExpressionVisitorAdapter(); public DeleteDeParser() { super(new StringBuilder()); } - public DeleteDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { + public DeleteDeParser(ExpressionVisitor expressionVisitor, + StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; } @@ -90,10 +92,7 @@ public void deParse(Delete delete) { } } - if (delete.getWhere() != null) { - buffer.append(" WHERE "); - delete.getWhere().accept(expressionVisitor); - } + deparseWhereClause(delete); if (delete.getOrderByElements() != null) { new OrderByDeParser(expressionVisitor, buffer).deParse(delete.getOrderByElements()); @@ -108,11 +107,18 @@ public void deParse(Delete delete) { } - public ExpressionVisitor getExpressionVisitor() { + protected void deparseWhereClause(Delete delete) { + if (delete.getWhere() != null) { + buffer.append(" WHERE "); + delete.getWhere().accept(expressionVisitor, null); + } + } + + public ExpressionVisitor getExpressionVisitor() { return expressionVisitor; } - public void setExpressionVisitor(ExpressionVisitor visitor) { + public void setExpressionVisitor(ExpressionVisitor visitor) { expressionVisitor = visitor; } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/DropDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/DropDeParser.java index 090a2cad1..709ed6e8a 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/DropDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/DropDeParser.java @@ -39,7 +39,8 @@ public void deParse(Drop drop) { } if (drop.getParameters() != null && !drop.getParameters().isEmpty()) { - buffer.append(" ").append(PlainSelect.getStringList(drop.getParameters(), false, false)); + buffer.append(" ") + .append(PlainSelect.getStringList(drop.getParameters(), false, false)); } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ExecuteDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ExecuteDeParser.java index 3e257c1f6..f9daaa8a9 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExecuteDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExecuteDeParser.java @@ -17,9 +17,10 @@ public class ExecuteDeParser extends AbstractDeParser { - private ExpressionVisitor expressionVisitor; + private ExpressionVisitor expressionVisitor; - public ExecuteDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { + public ExecuteDeParser(ExpressionVisitor expressionVisitor, + StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; } @@ -38,7 +39,7 @@ public void deParse(Execute execute) { if (i > 0) { buffer.append(", "); } - expressions.get(i).accept(expressionVisitor); + expressions.get(i).accept(expressionVisitor, null); } } if (execute.isParenthesis()) { @@ -46,11 +47,11 @@ public void deParse(Execute execute) { } } - public ExpressionVisitor getExpressionVisitor() { + public ExpressionVisitor getExpressionVisitor() { return expressionVisitor; } - public void setExpressionVisitor(ExpressionVisitor visitor) { + public void setExpressionVisitor(ExpressionVisitor visitor) { expressionVisitor = visitor; } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java index ad82ac582..a91b77dea 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -35,6 +35,7 @@ import net.sf.jsqlparser.expression.JsonExpression; import net.sf.jsqlparser.expression.JsonFunction; import net.sf.jsqlparser.expression.KeepExpression; +import net.sf.jsqlparser.expression.LambdaExpression; import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.MySQLGroupConcat; import net.sf.jsqlparser.expression.NextValExpression; @@ -45,12 +46,12 @@ import net.sf.jsqlparser.expression.OracleHint; import net.sf.jsqlparser.expression.OracleNamedFunctionParameter; import net.sf.jsqlparser.expression.OverlapsCondition; -import net.sf.jsqlparser.expression.Parenthesis; import net.sf.jsqlparser.expression.RangeExpression; import net.sf.jsqlparser.expression.RowConstructor; import net.sf.jsqlparser.expression.RowGetExpression; import net.sf.jsqlparser.expression.SignedExpression; import net.sf.jsqlparser.expression.StringValue; +import net.sf.jsqlparser.expression.StructType; import net.sf.jsqlparser.expression.TimeKeyExpression; import net.sf.jsqlparser.expression.TimeValue; import net.sf.jsqlparser.expression.TimestampValue; @@ -82,6 +83,7 @@ import net.sf.jsqlparser.expression.operators.relational.Contains; import net.sf.jsqlparser.expression.operators.relational.DoubleAnd; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; +import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression; import net.sf.jsqlparser.expression.operators.relational.ExistsExpression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.FullTextSearch; @@ -89,6 +91,7 @@ import net.sf.jsqlparser.expression.operators.relational.GreaterThan; import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals; import net.sf.jsqlparser.expression.operators.relational.InExpression; +import net.sf.jsqlparser.expression.operators.relational.IncludesExpression; import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression; import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression; import net.sf.jsqlparser.expression.operators.relational.IsNullExpression; @@ -107,37 +110,40 @@ import net.sf.jsqlparser.expression.operators.relational.TSQLRightJoin; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.create.table.ColDataType; import net.sf.jsqlparser.statement.select.AllColumns; import net.sf.jsqlparser.statement.select.AllTableColumns; import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.ParenthesedSelect; import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.SelectVisitor; import net.sf.jsqlparser.statement.select.WithItem; import java.util.Iterator; import java.util.List; +import java.util.Map; import static java.util.stream.Collectors.joining; @SuppressWarnings({"PMD.CyclomaticComplexity"}) public class ExpressionDeParser extends AbstractDeParser // FIXME maybe we should implement an ItemsListDeparser too? - implements ExpressionVisitor { + implements ExpressionVisitor { private static final String NOT = "NOT "; - private SelectVisitor selectVisitor; + private SelectVisitor selectVisitor; private OrderByDeParser orderByDeParser = new OrderByDeParser(); public ExpressionDeParser() { super(new StringBuilder()); } - public ExpressionDeParser(SelectVisitor selectVisitor, StringBuilder buffer) { + public ExpressionDeParser(SelectVisitor selectVisitor, StringBuilder buffer) { this(selectVisitor, buffer, new OrderByDeParser()); } - ExpressionDeParser(SelectVisitor selectVisitor, StringBuilder buffer, + ExpressionDeParser(SelectVisitor selectVisitor, StringBuilder buffer, OrderByDeParser orderByDeParser) { super(buffer); this.selectVisitor = selectVisitor; @@ -145,109 +151,176 @@ public ExpressionDeParser(SelectVisitor selectVisitor, StringBuilder buffer) { } @Override - public void visit(Addition addition) { - visitBinaryExpression(addition, " + "); + public StringBuilder visit(Addition addition, S context) { + deparse(addition, " + ", null); + return buffer; } @Override - public void visit(AndExpression andExpression) { - visitBinaryExpression(andExpression, andExpression.isUseOperator() ? " && " : " AND "); + public StringBuilder visit(AndExpression andExpression, S context) { + deparse(andExpression, andExpression.isUseOperator() ? " && " : " AND ", + null); + return buffer; } @Override - public void visit(Between between) { - between.getLeftExpression().accept(this); + public StringBuilder visit(Between between, S context) { + between.getLeftExpression().accept(this, context); if (between.isNot()) { buffer.append(" NOT"); } buffer.append(" BETWEEN "); - between.getBetweenExpressionStart().accept(this); + between.getBetweenExpressionStart().accept(this, context); buffer.append(" AND "); - between.getBetweenExpressionEnd().accept(this); + between.getBetweenExpressionEnd().accept(this, context); + return buffer; } @Override - public void visit(OverlapsCondition overlapsCondition) { + public StringBuilder visit(OverlapsCondition overlapsCondition, S context) { buffer.append(overlapsCondition.toString()); + return buffer; } @Override - public void visit(EqualsTo equalsTo) { - visitOldOracleJoinBinaryExpression(equalsTo, " = "); + public StringBuilder visit(EqualsTo equalsTo, S context) { + deparse(equalsTo, " = ", null); + return buffer; } @Override - public void visit(Division division) { - visitBinaryExpression(division, " / "); + public StringBuilder visit(Division division, S context) { + deparse(division, " / ", null); + return buffer; } @Override - public void visit(IntegerDivision division) { - visitBinaryExpression(division, " DIV "); + public StringBuilder visit(IntegerDivision division, S context) { + deparse(division, " DIV ", null); + return buffer; } @Override - public void visit(DoubleValue doubleValue) { + public StringBuilder visit(DoubleValue doubleValue, S context) { buffer.append(doubleValue.toString()); + return buffer; } @Override - public void visit(HexValue hexValue) { + public StringBuilder visit(HexValue hexValue, S context) { buffer.append(hexValue.toString()); + return buffer; } @Override - public void visit(NotExpression notExpr) { + public StringBuilder visit(NotExpression notExpr, S context) { if (notExpr.isExclamationMark()) { buffer.append("! "); } else { buffer.append(NOT); } - notExpr.getExpression().accept(this); + notExpr.getExpression().accept(this, context); + return buffer; } @Override - public void visit(BitwiseRightShift expr) { - visitBinaryExpression(expr, " >> "); + public StringBuilder visit(BitwiseRightShift expr, S context) { + deparse(expr, " >> ", null); + return buffer; } @Override - public void visit(BitwiseLeftShift expr) { - visitBinaryExpression(expr, " << "); + public StringBuilder visit(BitwiseLeftShift expr, S context) { + deparse(expr, " << ", null); + return buffer; } - public void visitOldOracleJoinBinaryExpression(OldOracleJoinBinaryExpression expression, - String operator) { + public StringBuilder deparse( + OldOracleJoinBinaryExpression expression, + String operator, S context) { // if (expression.isNot()) { // buffer.append(NOT); // } - expression.getLeftExpression().accept(this); + expression.getLeftExpression().accept(this, context); if (expression.getOldOracleJoinSyntax() == EqualsTo.ORACLE_JOIN_RIGHT) { buffer.append("(+)"); } buffer.append(operator); - expression.getRightExpression().accept(this); + expression.getRightExpression().accept(this, context); if (expression.getOldOracleJoinSyntax() == EqualsTo.ORACLE_JOIN_LEFT) { buffer.append("(+)"); } + + return buffer; } @Override - public void visit(GreaterThan greaterThan) { - visitOldOracleJoinBinaryExpression(greaterThan, " > "); + public StringBuilder visit(GreaterThan greaterThan, S context) { + deparse(greaterThan, " > ", null); + return buffer; } @Override - public void visit(GreaterThanEquals greaterThanEquals) { - visitOldOracleJoinBinaryExpression(greaterThanEquals, " >= "); + public StringBuilder visit(GreaterThanEquals greaterThanEquals, S context) { + deparse(greaterThanEquals, " >= ", null); + + return buffer; + } + + public void visit(Addition addition) { + visit(addition, null); + } + + public void visit(AndExpression andExpression) { + visit(andExpression, null); + } + + public void visit(Between between) { + visit(between, null); + } + + public void visit(OverlapsCondition overlapsCondition) { + visit(overlapsCondition, null); + } + + public void visit(EqualsTo equalsTo) { + visit(equalsTo, null); + } + + public void visit(Division division) { + visit(division, null); + } + public void visit(IntegerDivision division) { + visit(division, null); + } + + public void visit(DoubleValue doubleValue) { + visit(doubleValue, null); } + public void visit(HexValue hexValue) { + visit(hexValue, null); + } + + public void visit(NotExpression notExpr) { + visit(notExpr, null); + } + + public void visit(BitwiseRightShift expr) { + visit(expr, null); + } + + public void visit(BitwiseLeftShift expr) { + visit(expr, null); + } + + @Override - public void visit(InExpression inExpression) { - inExpression.getLeftExpression().accept(this); + public StringBuilder visit(InExpression inExpression, S context) { + inExpression.getLeftExpression().accept(this, context); if (inExpression .getOldOracleJoinSyntax() == SupportsOldOracleJoinSyntax.ORACLE_JOIN_RIGHT) { buffer.append("(+)"); @@ -259,38 +332,57 @@ public void visit(InExpression inExpression) { buffer.append(" NOT"); } buffer.append(" IN "); - inExpression.getRightExpression().accept(this); + inExpression.getRightExpression().accept(this, context); + return buffer; } @Override - public void visit(FullTextSearch fullTextSearch) { + public StringBuilder visit(IncludesExpression includesExpression, S context) { + includesExpression.getLeftExpression().accept(this, context); + buffer.append(" INCLUDES "); + includesExpression.getRightExpression().accept(this, context); + return buffer; + } + + @Override + public StringBuilder visit(ExcludesExpression excludesExpression, S context) { + excludesExpression.getLeftExpression().accept(this, context); + buffer.append(" EXCLUDES "); + excludesExpression.getRightExpression().accept(this, context); + return buffer; + } + + @Override + public StringBuilder visit(FullTextSearch fullTextSearch, S context) { // Build a list of matched columns - String columnsListCommaSeperated = ""; + StringBuilder columnsListCommaSeperated = new StringBuilder(); Iterator iterator = fullTextSearch.getMatchColumns().iterator(); while (iterator.hasNext()) { Column col = iterator.next(); - columnsListCommaSeperated += col.getFullyQualifiedName(); + columnsListCommaSeperated.append(col.getFullyQualifiedName()); if (iterator.hasNext()) { - columnsListCommaSeperated += ","; + columnsListCommaSeperated.append(","); } } - buffer.append("MATCH (" + columnsListCommaSeperated + ") AGAINST (" - + fullTextSearch.getAgainstValue() - + (fullTextSearch.getSearchModifier() != null + buffer.append("MATCH (").append(columnsListCommaSeperated).append(") AGAINST (") + .append(fullTextSearch.getAgainstValue()) + .append(fullTextSearch.getSearchModifier() != null ? " " + fullTextSearch.getSearchModifier() : "") - + ")"); + .append(")"); + return buffer; } @Override - public void visit(SignedExpression signedExpression) { + public StringBuilder visit(SignedExpression signedExpression, S context) { buffer.append(signedExpression.getSign()); - signedExpression.getExpression().accept(this); + signedExpression.getExpression().accept(this, context); + return buffer; } @Override - public void visit(IsNullExpression isNullExpression) { - isNullExpression.getLeftExpression().accept(this); + public StringBuilder visit(IsNullExpression isNullExpression, S context) { + isNullExpression.getLeftExpression().accept(this, context); if (isNullExpression.isUseNotNull()) { buffer.append(" NOTNULL"); } else if (isNullExpression.isUseIsNull()) { @@ -306,11 +398,12 @@ public void visit(IsNullExpression isNullExpression) { buffer.append(" IS NULL"); } } + return buffer; } @Override - public void visit(IsBooleanExpression isBooleanExpression) { - isBooleanExpression.getLeftExpression().accept(this); + public StringBuilder visit(IsBooleanExpression isBooleanExpression, S context) { + isBooleanExpression.getLeftExpression().accept(this, context); if (isBooleanExpression.isTrue()) { if (isBooleanExpression.isNot()) { buffer.append(" IS NOT TRUE"); @@ -324,162 +417,225 @@ public void visit(IsBooleanExpression isBooleanExpression) { buffer.append(" IS FALSE"); } } + return buffer; } @Override - public void visit(JdbcParameter jdbcParameter) { + public StringBuilder visit(JdbcParameter jdbcParameter, S context) { buffer.append(jdbcParameter.getParameterCharacter()); if (jdbcParameter.isUseFixedIndex()) { buffer.append(jdbcParameter.getIndex()); } + return buffer; } @Override - public void visit(LikeExpression likeExpression) { - likeExpression.getLeftExpression().accept(this); + public StringBuilder visit(LikeExpression likeExpression, S context) { + String keywordStr = likeExpression.getLikeKeyWord() == LikeExpression.KeyWord.SIMILAR_TO + ? " SIMILAR TO" + : likeExpression.getLikeKeyWord().toString(); + + likeExpression.getLeftExpression().accept(this, context); buffer.append(" "); if (likeExpression.isNot()) { buffer.append("NOT "); } - buffer.append(likeExpression.getLikeKeyWord()).append(" "); + buffer.append(keywordStr).append(" "); if (likeExpression.isUseBinary()) { buffer.append("BINARY "); } - likeExpression.getRightExpression().accept(this); + likeExpression.getRightExpression().accept(this, context); Expression escape = likeExpression.getEscape(); if (escape != null) { buffer.append(" ESCAPE "); - likeExpression.getEscape().accept(this); + likeExpression.getEscape().accept(this, context); } + return buffer; } @Override - public void visit(ExistsExpression existsExpression) { + public StringBuilder visit(ExistsExpression existsExpression, S context) { if (existsExpression.isNot()) { buffer.append("NOT EXISTS "); } else { buffer.append("EXISTS "); } - existsExpression.getRightExpression().accept(this); + existsExpression.getRightExpression().accept(this, context); + return buffer; } @Override - public void visit(MemberOfExpression memberOfExpression) { - memberOfExpression.getLeftExpression().accept(this); + public StringBuilder visit(MemberOfExpression memberOfExpression, S context) { + memberOfExpression.getLeftExpression().accept(this, context); if (memberOfExpression.isNot()) { buffer.append(" NOT MEMBER OF "); } else { buffer.append(" MEMBER OF "); } - memberOfExpression.getRightExpression().accept(this); + memberOfExpression.getRightExpression().accept(this, context); + return buffer; } - @Override - public void visit(LongValue longValue) { - buffer.append(longValue.getStringValue()); + public void visit(InExpression inExpression) { + visit(inExpression, null); + } + + public void visit(IncludesExpression includesExpression) { + visit(includesExpression, null); + } + + public void visit(ExcludesExpression excludesExpression) { + visit(excludesExpression, null); + } + + public void visit(FullTextSearch fullTextSearch) { + visit(fullTextSearch, null); + } + + public void visit(SignedExpression signedExpression) { + visit(signedExpression, null); + } + + public void visit(IsNullExpression isNullExpression) { + visit(isNullExpression, null); + } + + public void visit(IsBooleanExpression isBooleanExpression) { + visit(isBooleanExpression, null); + } + public void visit(JdbcParameter jdbcParameter) { + visit(jdbcParameter, null); + } + + public void visit(LikeExpression likeExpression) { + visit(likeExpression, null); } + public void visit(ExistsExpression existsExpression) { + visit(existsExpression, null); + } + + public void visit(MemberOfExpression memberOfExpression) { + visit(memberOfExpression, null); + } + + @Override - public void visit(MinorThan minorThan) { - visitOldOracleJoinBinaryExpression(minorThan, " < "); + public StringBuilder visit(LongValue longValue, S context) { + buffer.append(longValue.getStringValue()); + return buffer; } @Override - public void visit(MinorThanEquals minorThanEquals) { - visitOldOracleJoinBinaryExpression(minorThanEquals, " <= "); + public StringBuilder visit(MinorThan minorThan, S context) { + deparse(minorThan, " < ", null); + return buffer; } @Override - public void visit(Multiplication multiplication) { - visitBinaryExpression(multiplication, " * "); + public StringBuilder visit(MinorThanEquals minorThanEquals, S context) { + deparse(minorThanEquals, " <= ", null); + return buffer; } @Override - public void visit(NotEqualsTo notEqualsTo) { - visitOldOracleJoinBinaryExpression(notEqualsTo, - " " + notEqualsTo.getStringExpression() + " "); + public StringBuilder visit(Multiplication multiplication, S context) { + deparse(multiplication, " * ", null); + return buffer; } @Override - public void visit(DoubleAnd doubleAnd) { - visitOldOracleJoinBinaryExpression(doubleAnd, " " + doubleAnd.getStringExpression() + " "); + public StringBuilder visit(NotEqualsTo notEqualsTo, S context) { + deparse(notEqualsTo, + " " + notEqualsTo.getStringExpression() + " ", null); + return buffer; } @Override - public void visit(Contains contains) { - visitOldOracleJoinBinaryExpression(contains, " " + contains.getStringExpression() + " "); + public StringBuilder visit(DoubleAnd doubleAnd, S context) { + deparse(doubleAnd, " " + doubleAnd.getStringExpression() + " ", + null); + return buffer; } @Override - public void visit(ContainedBy containedBy) { - visitOldOracleJoinBinaryExpression(containedBy, - " " + containedBy.getStringExpression() + " "); + public StringBuilder visit(Contains contains, S context) { + deparse(contains, " " + contains.getStringExpression() + " ", + null); + return buffer; } @Override - public void visit(NullValue nullValue) { - buffer.append(nullValue.toString()); + public StringBuilder visit(ContainedBy containedBy, S context) { + deparse(containedBy, + " " + containedBy.getStringExpression() + " ", null); + return buffer; } @Override - public void visit(OrExpression orExpression) { - visitBinaryExpression(orExpression, " OR "); + public StringBuilder visit(NullValue nullValue, S context) { + buffer.append(nullValue.toString()); + return buffer; } @Override - public void visit(XorExpression xorExpression) { - visitBinaryExpression(xorExpression, " XOR "); + public StringBuilder visit(OrExpression orExpression, S context) { + deparse(orExpression, " OR ", null); + return buffer; } @Override - public void visit(Parenthesis parenthesis) { - buffer.append("("); - parenthesis.getExpression().accept(this); - buffer.append(")"); + public StringBuilder visit(XorExpression xorExpression, S context) { + deparse(xorExpression, " XOR ", null); + + return buffer; } @Override - public void visit(StringValue stringValue) { + public StringBuilder visit(StringValue stringValue, S context) { if (stringValue.getPrefix() != null) { buffer.append(stringValue.getPrefix()); } buffer.append("'").append(stringValue.getValue()).append("'"); + return buffer; } @Override - public void visit(Subtraction subtraction) { - visitBinaryExpression(subtraction, " - "); + public StringBuilder visit(Subtraction subtraction, S context) { + deparse(subtraction, " - ", null); + return buffer; } - protected void visitBinaryExpression(BinaryExpression binaryExpression, String operator) { - binaryExpression.getLeftExpression().accept(this); + protected void deparse(BinaryExpression binaryExpression, + String operator, S context) { + binaryExpression.getLeftExpression().accept(this, context); buffer.append(operator); - binaryExpression.getRightExpression().accept(this); + binaryExpression.getRightExpression().accept(this, context); } @Override - public void visit(Select selectBody) { + public StringBuilder visit(Select select, S context) { if (selectVisitor != null) { - if (selectBody.getWithItemsList() != null) { + if (select.getWithItemsList() != null) { buffer.append("WITH "); - for (Iterator iter = selectBody.getWithItemsList().iterator(); iter + for (Iterator iter = select.getWithItemsList().iterator(); iter .hasNext();) { - iter.next().accept(selectVisitor); + iter.next().accept(selectVisitor, null); if (iter.hasNext()) { buffer.append(", "); } @@ -488,20 +644,37 @@ public void visit(Select selectBody) { buffer.append(" "); } - selectBody.accept(selectVisitor); + select.accept(selectVisitor, null); } + return buffer; } @Override - public void visit(TranscodingFunction transcodingFunction) { - buffer.append("CONVERT( "); - transcodingFunction.getExpression().accept(this); - buffer.append(" USING ") - .append(transcodingFunction.getTranscodingName()) - .append(" )"); + public StringBuilder visit(TranscodingFunction transcodingFunction, S context) { + if (transcodingFunction.isTranscodeStyle()) { + buffer.append("CONVERT( "); + transcodingFunction.getExpression().accept(this, context); + buffer.append(" USING ") + .append(transcodingFunction.getTranscodingName()) + .append(" )"); + } else { + buffer + .append("CONVERT( ") + .append(transcodingFunction.getColDataType()) + .append(", "); + transcodingFunction.getExpression().accept(this, context); + + String transCodingName = transcodingFunction.getTranscodingName(); + if (transCodingName != null && !transCodingName.isEmpty()) { + buffer.append(", ").append(transCodingName); + } + buffer.append(" )"); + } + + return buffer; } - public void visit(TrimFunction trimFunction) { + public StringBuilder visit(TrimFunction trimFunction, S context) { buffer.append("Trim("); if (trimFunction.getTrimSpecification() != null) { @@ -510,25 +683,92 @@ public void visit(TrimFunction trimFunction) { if (trimFunction.getExpression() != null) { buffer.append(" "); - trimFunction.getExpression().accept(this); + trimFunction.getExpression().accept(this, context); } if (trimFunction.getFromExpression() != null) { buffer.append(trimFunction.isUsingFromKeyword() ? " FROM " : ", "); - trimFunction.getFromExpression().accept(this); + trimFunction.getFromExpression().accept(this, context); } buffer.append(" )"); + return buffer; + } + + public void visit(LongValue longValue) { + visit(longValue, null); } + public void visit(MinorThan minorThan) { + visit(minorThan, null); + } + + public void visit(MinorThanEquals minorThanEquals) { + visit(minorThanEquals, null); + } + + public void visit(Multiplication multiplication) { + visit(multiplication, null); + } + + public void visit(NotEqualsTo notEqualsTo) { + visit(notEqualsTo, null); + } + + public void visit(DoubleAnd doubleAnd) { + visit(doubleAnd, null); + } + + public void visit(Contains contains) { + visit(contains, null); + } + + public void visit(ContainedBy containedBy) { + visit(containedBy, null); + } + + public void visit(NullValue nullValue) { + visit(nullValue, null); + } + + public void visit(OrExpression orExpression) { + visit(orExpression, null); + } + + public void visit(XorExpression xorExpression) { + visit(xorExpression, null); + } + + public void visit(StringValue stringValue) { + visit(stringValue, null); + } + + public void visit(Subtraction subtraction) { + visit(subtraction, null); + } + + public void visit(Select select) { + visit(select, null); + } + + public void visit(TranscodingFunction transcodingFunction) { + visit(transcodingFunction, null); + } + + public void visit(TrimFunction trimFunction) { + visit(trimFunction, null); + } + + @Override - public void visit(RangeExpression rangeExpression) { - rangeExpression.getStartExpression().accept(this); + public StringBuilder visit(RangeExpression rangeExpression, S context) { + rangeExpression.getStartExpression().accept(this, context); buffer.append(":"); - rangeExpression.getEndExpression().accept(this); + rangeExpression.getEndExpression().accept(this, context); + return buffer; } @Override - public void visit(Column tableColumn) { + public StringBuilder visit(Column tableColumn, S context) { final Table table = tableColumn.getTable(); String tableName = null; if (table != null) { @@ -539,19 +779,20 @@ public void visit(Column tableColumn) { } } if (tableName != null && !tableName.isEmpty()) { - buffer.append(tableName).append("."); + buffer.append(tableName).append(tableColumn.getTableDelimiter()); } buffer.append(tableColumn.getColumnName()); if (tableColumn.getArrayConstructor() != null) { - tableColumn.getArrayConstructor().accept(this); + tableColumn.getArrayConstructor().accept(this, context); } + return buffer; } @Override @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"}) - public void visit(Function function) { + public StringBuilder visit(Function function, S context) { if (function.isEscaped()) { buffer.append("{fn "); } @@ -569,10 +810,27 @@ public void visit(Function function) { buffer.append("UNIQUE "); } if (function.getNamedParameters() != null) { - function.getNamedParameters().accept(this); + function.getNamedParameters().accept(this, context); } if (function.getParameters() != null) { - function.getParameters().accept(this); + function.getParameters().accept(this, context); + } + + Function.HavingClause havingClause = function.getHavingClause(); + if (havingClause != null) { + buffer.append(" HAVING ").append(havingClause.getHavingType()).append(" "); + havingClause.getExpression().accept(this, context); + } + + if (function.getNullHandling() != null && !function.isIgnoreNullsOutside()) { + switch (function.getNullHandling()) { + case IGNORE_NULLS: + buffer.append(" IGNORE NULLS"); + break; + case RESPECT_NULLS: + buffer.append(" RESPECT NULLS"); + break; + } } if (function.getOrderByElements() != null) { buffer.append(" ORDER BY "); @@ -588,9 +846,23 @@ public void visit(Function function) { orderByDeParser.deParseElement(orderByElement); } } + if (function.getLimit() != null) { + new LimitDeparser(this, buffer).deParse(function.getLimit()); + } buffer.append(")"); } + if (function.getNullHandling() != null && function.isIgnoreNullsOutside()) { + switch (function.getNullHandling()) { + case IGNORE_NULLS: + buffer.append(" IGNORE NULLS"); + break; + case RESPECT_NULLS: + buffer.append(" RESPECT NULLS"); + break; + } + } + if (function.getAttribute() != null) { buffer.append(".").append(function.getAttribute()); } @@ -601,222 +873,317 @@ public void visit(Function function) { if (function.isEscaped()) { buffer.append("}"); } + return buffer; } @Override - public void visit(ParenthesedSelect selectBody) { - selectBody.getSelect().accept(this); + public StringBuilder visit(ParenthesedSelect selectBody, S context) { + selectBody.getSelect().accept(this, context); + return buffer; } - public SelectVisitor getSelectVisitor() { + public SelectVisitor getSelectVisitor() { return selectVisitor; } - public void setSelectVisitor(SelectVisitor visitor) { + public void setSelectVisitor(SelectVisitor visitor) { selectVisitor = visitor; } @Override - public void visit(DateValue dateValue) { + public StringBuilder visit(DateValue dateValue, S context) { buffer.append("{d '").append(dateValue.getValue().toString()).append("'}"); + return buffer; } @Override - public void visit(TimestampValue timestampValue) { + public StringBuilder visit(TimestampValue timestampValue, S context) { buffer.append("{ts '").append(timestampValue.getValue().toString()).append("'}"); + return buffer; } @Override - public void visit(TimeValue timeValue) { + public StringBuilder visit(TimeValue timeValue, S context) { buffer.append("{t '").append(timeValue.getValue().toString()).append("'}"); + return buffer; } @Override - public void visit(CaseExpression caseExpression) { + public StringBuilder visit(CaseExpression caseExpression, S context) { buffer.append(caseExpression.isUsingBrackets() ? "(" : "").append("CASE "); Expression switchExp = caseExpression.getSwitchExpression(); if (switchExp != null) { - switchExp.accept(this); + switchExp.accept(this, context); buffer.append(" "); } for (Expression exp : caseExpression.getWhenClauses()) { - exp.accept(this); + exp.accept(this, context); } Expression elseExp = caseExpression.getElseExpression(); if (elseExp != null) { buffer.append("ELSE "); - elseExp.accept(this); + elseExp.accept(this, context); buffer.append(" "); } buffer.append("END").append(caseExpression.isUsingBrackets() ? ")" : ""); + return buffer; } @Override - public void visit(WhenClause whenClause) { + public StringBuilder visit(WhenClause whenClause, S context) { buffer.append("WHEN "); - whenClause.getWhenExpression().accept(this); + whenClause.getWhenExpression().accept(this, context); buffer.append(" THEN "); - whenClause.getThenExpression().accept(this); + whenClause.getThenExpression().accept(this, context); buffer.append(" "); + return buffer; } @Override - public void visit(AnyComparisonExpression anyComparisonExpression) { + public StringBuilder visit(AnyComparisonExpression anyComparisonExpression, S context) { buffer.append(anyComparisonExpression.getAnyType().name()); // VALUES or SELECT - anyComparisonExpression.getSelect().accept((ExpressionVisitor) this); + anyComparisonExpression.getSelect().accept(this, context); + return buffer; } @Override + public StringBuilder visit(Concat concat, S context) { + deparse(concat, " || ", null); + return buffer; + } + + public void visit(RangeExpression rangeExpression) { + visit(rangeExpression, null); + } + + public void visit(Column tableColumn) { + visit(tableColumn, null); + } + + public void visit(Function function) { + visit(function, null); + } + + public void visit(ParenthesedSelect selectBody) { + visit(selectBody, null); + } + + public void visit(DateValue dateValue) { + visit(dateValue, null); + } + + public void visit(TimestampValue timestampValue) { + visit(timestampValue, null); + } + + public void visit(TimeValue timeValue) { + visit(timeValue, null); + } + + public void visit(CaseExpression caseExpression) { + visit(caseExpression, null); + } + + public void visit(WhenClause whenClause) { + visit(whenClause, null); + } + + public void visit(AnyComparisonExpression anyComparisonExpression) { + visit(anyComparisonExpression, null); + } + public void visit(Concat concat) { - visitBinaryExpression(concat, " || "); + visit(concat, null); } + @Override - public void visit(Matches matches) { - visitOldOracleJoinBinaryExpression(matches, " @@ "); + public StringBuilder visit(Matches matches, S context) { + deparse(matches, " @@ ", null); + return buffer; } @Override - public void visit(BitwiseAnd bitwiseAnd) { - visitBinaryExpression(bitwiseAnd, " & "); + public StringBuilder visit(BitwiseAnd bitwiseAnd, S context) { + deparse(bitwiseAnd, " & ", null); + return buffer; } @Override - public void visit(BitwiseOr bitwiseOr) { - visitBinaryExpression(bitwiseOr, " | "); + public StringBuilder visit(BitwiseOr bitwiseOr, S context) { + deparse(bitwiseOr, " | ", null); + return buffer; } @Override - public void visit(BitwiseXor bitwiseXor) { - visitBinaryExpression(bitwiseXor, " ^ "); + public StringBuilder visit(BitwiseXor bitwiseXor, S context) { + deparse(bitwiseXor, " ^ ", null); + return buffer; } @Override - public void visit(CastExpression cast) { - if (cast.isUseCastKeyword()) { + public StringBuilder visit(CastExpression cast, S context) { + if (cast.isImplicitCast()) { + buffer.append(cast.getColDataType()).append(" "); + cast.getLeftExpression().accept(this, context); + } else if (cast.isUseCastKeyword()) { + String formatStr = cast.getFormat() != null && !cast.getFormat().isEmpty() + ? " FORMAT " + cast.getFormat() + : ""; + buffer.append(cast.keyword).append("("); - cast.getLeftExpression().accept(this); + cast.getLeftExpression().accept(this, context); buffer.append(" AS "); buffer.append( cast.getColumnDefinitions().size() > 1 ? "ROW(" + Select.getStringList(cast.getColumnDefinitions()) + ")" : cast.getColDataType().toString()); + buffer.append(formatStr); buffer.append(")"); } else { - cast.getLeftExpression().accept(this); + cast.getLeftExpression().accept(this, context); buffer.append("::"); buffer.append(cast.getColDataType()); } + return buffer; } @Override - public void visit(Modulo modulo) { - visitBinaryExpression(modulo, " % "); + public StringBuilder visit(Modulo modulo, S context) { + deparse(modulo, " % ", null); + return buffer; } @Override @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.ExcessiveMethodLength", "PMD.MissingBreakInSwitch"}) - public void visit(AnalyticExpression aexpr) { - String name = aexpr.getName(); - Expression expression = aexpr.getExpression(); - Expression offset = aexpr.getOffset(); - Expression defaultValue = aexpr.getDefaultValue(); - boolean isAllColumns = aexpr.isAllColumns(); - KeepExpression keep = aexpr.getKeep(); - ExpressionList partitionExpressionList = aexpr.getPartitionExpressionList(); - List orderByElements = aexpr.getOrderByElements(); - WindowElement windowElement = aexpr.getWindowElement(); + public StringBuilder visit(AnalyticExpression analyticExpression, S context) { + String name = analyticExpression.getName(); + Expression expression = analyticExpression.getExpression(); + Expression offset = analyticExpression.getOffset(); + Expression defaultValue = analyticExpression.getDefaultValue(); + boolean isAllColumns = analyticExpression.isAllColumns(); + KeepExpression keep = analyticExpression.getKeep(); + ExpressionList partitionExpressionList = analyticExpression.getPartitionExpressionList(); + List orderByElements = analyticExpression.getOrderByElements(); + WindowElement windowElement = analyticExpression.getWindowElement(); buffer.append(name).append("("); - if (aexpr.isDistinct()) { + if (analyticExpression.isDistinct()) { buffer.append("DISTINCT "); } - if (aexpr.isUnique()) { + if (analyticExpression.isUnique()) { buffer.append("UNIQUE "); } if (expression != null) { - expression.accept(this); + expression.accept(this, context); if (offset != null) { buffer.append(", "); - offset.accept(this); + offset.accept(this, context); if (defaultValue != null) { buffer.append(", "); - defaultValue.accept(this); + defaultValue.accept(this, context); } } } else if (isAllColumns) { buffer.append("*"); } - if (aexpr.isIgnoreNulls()) { - buffer.append(" IGNORE NULLS"); + Function.HavingClause havingClause = analyticExpression.getHavingClause(); + if (havingClause != null) { + buffer.append(" HAVING ").append(havingClause.getHavingType()).append(" "); + havingClause.getExpression().accept(this, context); + } + + if (analyticExpression.getNullHandling() != null + && !analyticExpression.isIgnoreNullsOutside()) { + switch (analyticExpression.getNullHandling()) { + case IGNORE_NULLS: + buffer.append(" IGNORE NULLS"); + break; + case RESPECT_NULLS: + buffer.append(" RESPECT NULLS"); + break; + } } - if (aexpr.getFuncOrderBy() != null) { + if (analyticExpression.getFuncOrderBy() != null) { buffer.append(" ORDER BY "); - buffer.append(aexpr.getFuncOrderBy().stream().map(OrderByElement::toString) + buffer.append(analyticExpression.getFuncOrderBy().stream().map(OrderByElement::toString) .collect(joining(", "))); } + if (analyticExpression.getLimit() != null) { + new LimitDeparser(this, buffer).deParse(analyticExpression.getLimit()); + } + buffer.append(") "); if (keep != null) { - keep.accept(this); + keep.accept(this, context); buffer.append(" "); } - if (aexpr.getFilterExpression() != null) { + if (analyticExpression.getFilterExpression() != null) { buffer.append("FILTER (WHERE "); - aexpr.getFilterExpression().accept(this); + analyticExpression.getFilterExpression().accept(this, context); buffer.append(")"); - if (aexpr.getType() != AnalyticType.FILTER_ONLY) { + if (analyticExpression.getType() != AnalyticType.FILTER_ONLY) { buffer.append(" "); } } - if (aexpr.isIgnoreNullsOutside()) { - buffer.append("IGNORE NULLS "); + if (analyticExpression.getNullHandling() != null + && analyticExpression.isIgnoreNullsOutside()) { + switch (analyticExpression.getNullHandling()) { + case IGNORE_NULLS: + buffer.append(" IGNORE NULLS "); + break; + case RESPECT_NULLS: + buffer.append(" RESPECT NULLS "); + break; + } } - switch (aexpr.getType()) { + switch (analyticExpression.getType()) { case FILTER_ONLY: - return; + return null; case WITHIN_GROUP: buffer.append("WITHIN GROUP"); break; case WITHIN_GROUP_OVER: buffer.append("WITHIN GROUP ("); - aexpr.getWindowDefinition().getOrderBy().toStringOrderByElements(buffer); + analyticExpression.getWindowDefinition().getOrderBy() + .toStringOrderByElements(buffer); buffer.append(") OVER ("); - aexpr.getWindowDefinition().getPartitionBy().toStringPartitionBy(buffer); + analyticExpression.getWindowDefinition().getPartitionBy() + .toStringPartitionBy(buffer); buffer.append(")"); break; default: buffer.append("OVER"); } - if (aexpr.getWindowName() != null) { - buffer.append(" ").append(aexpr.getWindowName()); - } else if (aexpr.getType() != AnalyticType.WITHIN_GROUP_OVER) { + if (analyticExpression.getWindowName() != null) { + buffer.append(" ").append(analyticExpression.getWindowName()); + } else if (analyticExpression.getType() != AnalyticType.WITHIN_GROUP_OVER) { buffer.append(" ("); if (partitionExpressionList != null - && !partitionExpressionList.getExpressions().isEmpty()) { + && !partitionExpressionList.isEmpty()) { buffer.append("PARTITION BY "); - if (aexpr.isPartitionByBrackets()) { + if (analyticExpression.isPartitionByBrackets()) { buffer.append("("); } - List expressions = partitionExpressionList.getExpressions(); - for (int i = 0; i < expressions.size(); i++) { + for (int i = 0; i < ((List) partitionExpressionList).size(); i++) { if (i > 0) { buffer.append(", "); } - expressions.get(i).accept(this); + ((List) partitionExpressionList).get(i).accept(this, context); } - if (aexpr.isPartitionByBrackets()) { + if (analyticExpression.isPartitionByBrackets()) { buffer.append(")"); } buffer.append(" "); @@ -842,153 +1209,281 @@ public void visit(AnalyticExpression aexpr) { buffer.append(")"); } + return buffer; } @Override - public void visit(ExtractExpression eexpr) { - buffer.append("EXTRACT(").append(eexpr.getName()); + public StringBuilder visit(ExtractExpression extractExpression, S context) { + buffer.append("EXTRACT(").append(extractExpression.getName()); buffer.append(" FROM "); - eexpr.getExpression().accept(this); + extractExpression.getExpression().accept(this, context); buffer.append(')'); + return buffer; } @Override - public void visit(IntervalExpression intervalExpression) { + public StringBuilder visit(IntervalExpression intervalExpression, S context) { if (intervalExpression.isUsingIntervalKeyword()) { buffer.append("INTERVAL "); } if (intervalExpression.getExpression() != null) { - intervalExpression.getExpression().accept(this); + intervalExpression.getExpression().accept(this, context); } else { buffer.append(intervalExpression.getParameter()); } if (intervalExpression.getIntervalType() != null) { buffer.append(" ").append(intervalExpression.getIntervalType()); } + return buffer; + } + + public void visit(Matches matches) { + visit(matches, null); + } + + public void visit(BitwiseAnd bitwiseAnd) { + visit(bitwiseAnd, null); } + public void visit(BitwiseOr bitwiseOr) { + visit(bitwiseOr, null); + } + + public void visit(BitwiseXor bitwiseXor) { + visit(bitwiseXor, null); + } + + public void visit(CastExpression cast) { + visit(cast, null); + } + + public void visit(AnalyticExpression analyticExpression) { + visit(analyticExpression, null); + } + + public void visit(ExtractExpression extractExpression) { + visit(extractExpression, null); + } + + public void visit(IntervalExpression intervalExpression) { + visit(intervalExpression, null); + } + + @Override - public void visit(JdbcNamedParameter jdbcNamedParameter) { + public StringBuilder visit(JdbcNamedParameter jdbcNamedParameter, S context) { buffer.append(jdbcNamedParameter.toString()); + return buffer; } @Override - public void visit(OracleHierarchicalExpression oexpr) { - buffer.append(oexpr.toString()); + public StringBuilder visit(OracleHierarchicalExpression hierarchicalExpression, S context) { + buffer.append(hierarchicalExpression.toString()); + return buffer; } @Override - public void visit(RegExpMatchOperator rexpr) { - visitBinaryExpression(rexpr, " " + rexpr.getStringExpression() + " "); + public StringBuilder visit(RegExpMatchOperator regExpMatchOperator, S context) { + deparse(regExpMatchOperator, " " + regExpMatchOperator.getStringExpression() + " ", null); + return buffer; } @Override - public void visit(JsonExpression jsonExpr) { + public StringBuilder visit(JsonExpression jsonExpr, S context) { buffer.append(jsonExpr.toString()); + return buffer; } @Override - public void visit(JsonOperator jsonExpr) { - visitBinaryExpression(jsonExpr, " " + jsonExpr.getStringExpression() + " "); + public StringBuilder visit(JsonOperator jsonExpr, S context) { + deparse(jsonExpr, " " + jsonExpr.getStringExpression() + " ", null); + return buffer; } @Override - public void visit(UserVariable var) { + public StringBuilder visit(UserVariable var, S context) { buffer.append(var.toString()); + return buffer; } @Override - public void visit(NumericBind bind) { + public StringBuilder visit(NumericBind bind, S context) { buffer.append(bind.toString()); + return buffer; } @Override - public void visit(KeepExpression aexpr) { - buffer.append(aexpr.toString()); + public StringBuilder visit(KeepExpression keepExpression, S context) { + buffer.append(keepExpression.toString()); + return buffer; } @Override - public void visit(MySQLGroupConcat groupConcat) { + public StringBuilder visit(MySQLGroupConcat groupConcat, S context) { buffer.append(groupConcat.toString()); + return buffer; } @Override - public void visit(ExpressionList expressionList) { + public StringBuilder visit(ExpressionList expressionList, S context) { ExpressionListDeParser expressionListDeParser = new ExpressionListDeParser<>(this, buffer); expressionListDeParser.deParse(expressionList); + return buffer; } @Override - public void visit(RowConstructor rowConstructor) { + public StringBuilder visit(RowConstructor rowConstructor, S context) { if (rowConstructor.getName() != null) { buffer.append(rowConstructor.getName()); } ExpressionListDeParser expressionListDeParser = new ExpressionListDeParser<>(this, buffer); expressionListDeParser.deParse(rowConstructor); + return buffer; } @Override - public void visit(RowGetExpression rowGetExpression) { - rowGetExpression.getExpression().accept(this); + public StringBuilder visit(RowGetExpression rowGetExpression, S context) { + rowGetExpression.getExpression().accept(this, context); buffer.append(".").append(rowGetExpression.getColumnName()); + return null; } @Override - public void visit(OracleHint hint) { + public StringBuilder visit(OracleHint hint, S context) { buffer.append(hint.toString()); + return buffer; } @Override - public void visit(TimeKeyExpression timeKeyExpression) { + public StringBuilder visit(TimeKeyExpression timeKeyExpression, S context) { buffer.append(timeKeyExpression.toString()); + return buffer; } @Override - public void visit(DateTimeLiteralExpression literal) { + public StringBuilder visit(DateTimeLiteralExpression literal, S context) { buffer.append(literal.toString()); + return buffer; } @Override - public void visit(NextValExpression nextVal) { + public StringBuilder visit(NextValExpression nextVal, S context) { buffer.append(nextVal.isUsingNextValueFor() ? "NEXT VALUE FOR " : "NEXTVAL FOR ") .append(nextVal.getName()); + return buffer; } @Override - public void visit(CollateExpression col) { + public StringBuilder visit(CollateExpression col, S context) { buffer.append(col.getLeftExpression().toString()).append(" COLLATE ") .append(col.getCollate()); + return buffer; } @Override + public StringBuilder visit(SimilarToExpression expr, S context) { + deparse(expr, (expr.isNot() ? " NOT" : "") + " SIMILAR TO ", null); + return buffer; + } + + public void visit(JdbcNamedParameter jdbcNamedParameter) { + visit(jdbcNamedParameter, null); + } + + public void visit(OracleHierarchicalExpression hierarchicalExpression) { + visit(hierarchicalExpression, null); + } + + public void visit(RegExpMatchOperator regExpMatchOperator) { + visit(regExpMatchOperator, null); + } + + public void visit(JsonExpression jsonExpr) { + visit(jsonExpr, null); + } + + public void visit(JsonOperator jsonExpr) { + visit(jsonExpr, null); + } + + public void visit(UserVariable userVariable) { + visit(userVariable, null); + } + + public void visit(NumericBind numericBind) { + visit(numericBind, null); + } + + public void visit(KeepExpression keepExpression) { + visit(keepExpression, null); + } + + public void visit(MySQLGroupConcat groupConcat) { + visit(groupConcat, null); + } + + public void visit(ExpressionList expressionList) { + visit(expressionList, null); + } + + public void visit(RowConstructor rowConstructor) { + visit(rowConstructor, null); + } + + public void visit(RowGetExpression rowGetExpression) { + visit(rowGetExpression, null); + } + + public void visit(OracleHint hint) { + visit(hint, null); + } + + public void visit(TimeKeyExpression timeKeyExpression) { + visit(timeKeyExpression, null); + } + + public void visit(DateTimeLiteralExpression literal) { + visit(literal, null); + } + + public void visit(NextValExpression nextVal) { + visit(nextVal, null); + } + + public void visit(CollateExpression col) { + visit(col, null); + } + public void visit(SimilarToExpression expr) { - visitBinaryExpression(expr, (expr.isNot() ? " NOT" : "") + " SIMILAR TO "); + visit(expr, null); } + @Override - public void visit(ArrayExpression array) { - array.getObjExpression().accept(this); + public StringBuilder visit(ArrayExpression array, S context) { + array.getObjExpression().accept(this, context); buffer.append("["); if (array.getIndexExpression() != null) { - array.getIndexExpression().accept(this); + array.getIndexExpression().accept(this, context); } else { if (array.getStartIndexExpression() != null) { - array.getStartIndexExpression().accept(this); + array.getStartIndexExpression().accept(this, context); } buffer.append(":"); if (array.getStopIndexExpression() != null) { - array.getStopIndexExpression().accept(this); + array.getStopIndexExpression().accept(this, context); } } buffer.append("]"); + return buffer; } @Override - public void visit(ArrayConstructor aThis) { + public StringBuilder visit(ArrayConstructor aThis, S context) { if (aThis.isArrayKeyword()) { buffer.append("ARRAY"); } @@ -1000,28 +1495,30 @@ public void visit(ArrayConstructor aThis) { } else { first = false; } - expression.accept(this); + expression.accept(this, context); } buffer.append("]"); + return buffer; } @Override void deParse(Expression statement) { - statement.accept(this); + statement.accept(this, null); } @Override - public void visit(VariableAssignment var) { - var.getVariable().accept(this); + public StringBuilder visit(VariableAssignment var, S context) { + var.getVariable().accept(this, context); buffer.append(" ").append(var.getOperation()).append(" "); - var.getExpression().accept(this); + var.getExpression().accept(this, context); + return buffer; } @Override - public void visit(XMLSerializeExpr expr) { + public StringBuilder visit(XMLSerializeExpr expr, S context) { // xmlserialize(xmlagg(xmltext(COMMENT_LINE) ORDER BY COMMENT_SEQUENCE) as varchar(1024)) buffer.append("xmlserialize(xmlagg(xmltext("); - expr.getExpression().accept(this); + expr.getExpression().accept(this, context); buffer.append(")"); if (expr.getOrderByElements() != null) { buffer.append(" ORDER BY "); @@ -1033,77 +1530,181 @@ public void visit(XMLSerializeExpr expr) { } } buffer.append(") AS ").append(expr.getDataType()).append(")"); + return buffer; } @Override - public void visit(TimezoneExpression var) { - var.getLeftExpression().accept(this); + public StringBuilder visit(TimezoneExpression var, S context) { + var.getLeftExpression().accept(this, context); for (Expression expr : var.getTimezoneExpressions()) { buffer.append(" AT TIME ZONE "); - expr.accept(this); + expr.accept(this, context); } + return buffer; } @Override - public void visit(JsonAggregateFunction expression) { + public StringBuilder visit(JsonAggregateFunction expression, S context) { expression.append(buffer); + return buffer; } @Override - public void visit(JsonFunction expression) { + public StringBuilder visit(JsonFunction expression, S context) { expression.append(buffer); + return buffer; } @Override - public void visit(ConnectByRootOperator connectByRootOperator) { + public StringBuilder visit(ConnectByRootOperator connectByRootOperator, S context) { buffer.append("CONNECT_BY_ROOT "); - connectByRootOperator.getColumn().accept(this); + connectByRootOperator.getColumn().accept(this, context); + return buffer; } @Override - public void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter) { + public StringBuilder visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, + S context) { buffer.append(oracleNamedFunctionParameter.getName()).append(" => "); - oracleNamedFunctionParameter.getExpression().accept(this); + oracleNamedFunctionParameter.getExpression().accept(this, context); + return buffer; } @Override - public void visit(AllColumns allColumns) { + public StringBuilder visit(AllColumns allColumns, S context) { buffer.append(allColumns.toString()); + return buffer; } @Override - public void visit(AllTableColumns allTableColumns) { + public StringBuilder visit(AllTableColumns allTableColumns, S context) { buffer.append(allTableColumns.toString()); + return buffer; } @Override - public void visit(AllValue allValue) { + public StringBuilder visit(AllValue allValue, S context) { buffer.append(allValue); + return buffer; } @Override - public void visit(IsDistinctExpression isDistinctExpression) { - buffer.append(isDistinctExpression.getLeftExpression() - + isDistinctExpression.getStringExpression() - + isDistinctExpression.getRightExpression()); + public StringBuilder visit(IsDistinctExpression isDistinctExpression, S context) { + buffer.append(isDistinctExpression.getLeftExpression()) + .append(isDistinctExpression.getStringExpression()) + .append(isDistinctExpression.getRightExpression()); + return buffer; } @Override - public void visit(GeometryDistance geometryDistance) { - visitOldOracleJoinBinaryExpression(geometryDistance, - " " + geometryDistance.getStringExpression() + " "); + public StringBuilder visit(GeometryDistance geometryDistance, S context) { + deparse(geometryDistance, + " " + geometryDistance.getStringExpression() + " ", null); + return buffer; } @Override - public void visit(TSQLLeftJoin tsqlLeftJoin) { - visitBinaryExpression(tsqlLeftJoin, " *= "); + public StringBuilder visit(TSQLLeftJoin tsqlLeftJoin, S context) { + this.deparse(tsqlLeftJoin, " *= ", null); + return buffer; } @Override - public void visit(TSQLRightJoin tsqlRightJoin) { - visitBinaryExpression(tsqlRightJoin, " =* "); + public StringBuilder visit(TSQLRightJoin tsqlRightJoin, S context) { + this.deparse(tsqlRightJoin, " =* ", null); + return buffer; } + @Override + public StringBuilder visit(StructType structType, S context) { + if (structType.getDialect() != StructType.Dialect.DUCKDB + && structType.getKeyword() != null) { + buffer.append(structType.getKeyword()); + } + + if (structType.getDialect() != StructType.Dialect.DUCKDB + && structType.getParameters() != null && !structType.getParameters().isEmpty()) { + buffer.append("<"); + int i = 0; + for (Map.Entry e : structType.getParameters()) { + if (0 < i++) { + buffer.append(","); + } + // optional name + if (e.getKey() != null && !e.getKey().isEmpty()) { + buffer.append(e.getKey()).append(" "); + } + + // mandatory type + buffer.append(e.getValue()); + } + + buffer.append(">"); + } + + if (structType.getArguments() != null && !structType.getArguments().isEmpty()) { + if (structType.getDialect() == StructType.Dialect.DUCKDB) { + buffer.append("{ "); + int i = 0; + for (SelectItem e : structType.getArguments()) { + if (0 < i++) { + buffer.append(","); + } + buffer.append(e.getAlias().getName()); + buffer.append(" : "); + e.getExpression().accept(this, context); + } + buffer.append(" }"); + } else { + buffer.append("("); + int i = 0; + for (SelectItem e : structType.getArguments()) { + if (0 < i++) { + buffer.append(","); + } + e.getExpression().accept(this, context); + if (e.getAlias() != null) { + buffer.append(" as "); + buffer.append(e.getAlias().getName()); + } + } + buffer.append(")"); + } + } + + if (structType.getDialect() == StructType.Dialect.DUCKDB + && structType.getParameters() != null && !structType.getParameters().isEmpty()) { + buffer.append("::STRUCT( "); + int i = 0; + for (Map.Entry e : structType.getParameters()) { + if (0 < i++) { + buffer.append(","); + } + buffer.append(e.getKey()).append(" "); + buffer.append(e.getValue()); + } + buffer.append(")"); + } + return buffer; + } + + @Override + public StringBuilder visit(LambdaExpression lambdaExpression, S context) { + if (lambdaExpression.getIdentifiers().size() == 1) { + buffer.append(lambdaExpression.getIdentifiers().get(0)); + } else { + int i = 0; + buffer.append("( "); + for (String s : lambdaExpression.getIdentifiers()) { + buffer.append(i++ > 0 ? ", " : "").append(s); + } + buffer.append(" )"); + } + + buffer.append(" -> "); + lambdaExpression.getExpression().accept(this, context); + return buffer; + } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionListDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionListDeParser.java index f13066ff2..cbba90f94 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionListDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionListDeParser.java @@ -21,9 +21,10 @@ public class ExpressionListDeParser extends AbstractDeParser> { - private final ExpressionVisitor expressionVisitor; + private final ExpressionVisitor expressionVisitor; - public ExpressionListDeParser(ExpressionVisitor expressionVisitor, StringBuilder builder) { + public ExpressionListDeParser(ExpressionVisitor expressionVisitor, + StringBuilder builder) { super(builder); this.expressionVisitor = expressionVisitor; } @@ -36,32 +37,30 @@ public void deParse(ExpressionList expressionList) { : ", "; // @todo: remove this NameExpressionList related part List names = expressionList instanceof NamedExpressionList - ? ((NamedExpressionList) expressionList).getNames() + ? ((NamedExpressionList) expressionList).getNames() : Collections.nCopies(expressionList.size(), ""); - if (expressionList != null) { - if (expressionList instanceof ParenthesedExpressionList) { - buffer.append("("); + if (expressionList instanceof ParenthesedExpressionList) { + buffer.append("("); + } + int i = 0; + for (Expression expression : expressionList) { + if (i > 0) { + buffer.append(comma); } - int i = 0; - for (Expression expression : expressionList) { - if (i > 0) { - buffer.append(comma); - } - // @todo: remove this NameExpressionList related part - String name = names.get(i); - if (!name.equals("")) { - buffer.append(name); - buffer.append(" "); - } - expression.accept(expressionVisitor); - i++; + // @todo: remove this NameExpressionList related part + String name = names.get(i); + if (!name.isEmpty()) { + buffer.append(name); + buffer.append(" "); } + expression.accept(expressionVisitor, null); + i++; + } - if (expressionList instanceof ParenthesedExpressionList) { - buffer.append(")"); - } + if (expressionList instanceof ParenthesedExpressionList) { + buffer.append(")"); } } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/GroupByDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/GroupByDeParser.java index 694a97d38..d9b1dbb82 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/GroupByDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/GroupByDeParser.java @@ -15,15 +15,12 @@ public class GroupByDeParser extends AbstractDeParser { - private ExpressionListDeParser expressionListDeParser; + private final ExpressionListDeParser expressionListDeParser; - GroupByDeParser() { - this(null, new StringBuilder()); - } - - public GroupByDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { + public GroupByDeParser(ExpressionVisitor expressionVisitor, + StringBuilder buffer) { super(buffer); - this.expressionListDeParser = new ExpressionListDeParser(expressionVisitor, buffer); + this.expressionListDeParser = new ExpressionListDeParser<>(expressionVisitor, buffer); this.buffer = buffer; } @@ -39,7 +36,7 @@ public void deParse(GroupByElement groupBy) { buffer.append(' '); } buffer.append("GROUPING SETS ("); - for (ExpressionList expressionList : groupBy.getGroupingSets()) { + for (ExpressionList expressionList : groupBy.getGroupingSets()) { buffer.append(i++ > 0 ? ", " : ""); expressionListDeParser.deParse(expressionList); } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java index dec9f6c0a..6156171dc 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java @@ -20,14 +20,15 @@ public class InsertDeParser extends AbstractDeParser { - private ExpressionVisitor expressionVisitor; - private SelectVisitor selectVisitor; + private ExpressionVisitor expressionVisitor; + private SelectVisitor selectVisitor; public InsertDeParser() { super(new StringBuilder()); } - public InsertDeParser(ExpressionVisitor expressionVisitor, SelectVisitor selectVisitor, + public InsertDeParser(ExpressionVisitor expressionVisitor, + SelectVisitor selectVisitor, StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; @@ -42,7 +43,7 @@ public void deParse(Insert insert) { buffer.append("WITH "); for (Iterator iter = insert.getWithItemsList().iterator(); iter.hasNext();) { WithItem withItem = iter.next(); - withItem.accept(this.selectVisitor); + withItem.accept(this.selectVisitor, null); if (iter.hasNext()) { buffer.append(","); } @@ -82,7 +83,7 @@ public void deParse(Insert insert) { if (insert.getSelect() != null) { buffer.append(" "); Select select = insert.getSelect(); - select.accept(selectVisitor); + select.accept(selectVisitor, null); } if (insert.getSetUpdateSets() != null) { @@ -110,19 +111,19 @@ public void deParse(Insert insert) { } } - public ExpressionVisitor getExpressionVisitor() { + public ExpressionVisitor getExpressionVisitor() { return expressionVisitor; } - public SelectVisitor getSelectVisitor() { - return selectVisitor; + public void setExpressionVisitor(ExpressionVisitor visitor) { + expressionVisitor = visitor; } - public void setExpressionVisitor(ExpressionVisitor visitor) { - expressionVisitor = visitor; + public SelectVisitor getSelectVisitor() { + return selectVisitor; } - public void setSelectVisitor(SelectVisitor visitor) { + public void setSelectVisitor(SelectVisitor visitor) { selectVisitor = visitor; } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/LimitDeparser.java b/src/main/java/net/sf/jsqlparser/util/deparser/LimitDeparser.java index 88aec177d..e0d496d8e 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/LimitDeparser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/LimitDeparser.java @@ -13,9 +13,9 @@ import net.sf.jsqlparser.statement.select.Limit; public class LimitDeparser extends AbstractDeParser { - private ExpressionVisitor expressionVisitor; + private ExpressionVisitor expressionVisitor; - public LimitDeparser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { + public LimitDeparser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; } @@ -30,27 +30,27 @@ public void deParse(Limit limit) { buffer.append("ALL"); } else { if (null != limit.getOffset()) { - limit.getOffset().accept(expressionVisitor); + limit.getOffset().accept(expressionVisitor, null); buffer.append(", "); } if (null != limit.getRowCount()) { - limit.getRowCount().accept(expressionVisitor); + limit.getRowCount().accept(expressionVisitor, null); } } } if (limit.getByExpressions() != null) { buffer.append(" BY "); - limit.getByExpressions().accept(expressionVisitor); + limit.getByExpressions().accept(expressionVisitor, null); } } - public ExpressionVisitor getExpressionVisitor() { + public ExpressionVisitor getExpressionVisitor() { return expressionVisitor; } - public void setExpressionVisitor(ExpressionVisitor expressionVisitor) { + public void setExpressionVisitor(ExpressionVisitor expressionVisitor) { this.expressionVisitor = expressionVisitor; } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/MergeDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/MergeDeParser.java index dfcf83399..36cda69a4 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/MergeDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/MergeDeParser.java @@ -15,7 +15,8 @@ import java.util.Iterator; import java.util.List; -public class MergeDeParser extends AbstractDeParser implements MergeOperationVisitor { +public class MergeDeParser extends AbstractDeParser + implements MergeOperationVisitor { private final ExpressionDeParser expressionDeParser; private final SelectDeParser selectDeParser; @@ -28,12 +29,12 @@ public MergeDeParser(ExpressionDeParser expressionDeParser, SelectDeParser selec } @Override - void deParse(Merge merge) { + public void deParse(Merge merge) { List withItemsList = merge.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { buffer.append("WITH "); for (Iterator iter = withItemsList.iterator(); iter.hasNext();) { - iter.next().accept(expressionDeParser); + iter.next().accept(expressionDeParser, null); if (iter.hasNext()) { buffer.append(","); } @@ -46,17 +47,17 @@ void deParse(Merge merge) { buffer.append(merge.getOracleHint()).append(" "); } buffer.append("INTO "); - merge.getTable().accept(selectDeParser); + merge.getTable().accept(selectDeParser, null); buffer.append(" USING "); - merge.getFromItem().accept(selectDeParser); + merge.getFromItem().accept(selectDeParser, null); buffer.append(" ON "); - merge.getOnCondition().accept(expressionDeParser); + merge.getOnCondition().accept(expressionDeParser, null); List operations = merge.getOperations(); if (operations != null && !operations.isEmpty()) { - operations.forEach(operation -> operation.accept(this)); + operations.forEach(operation -> operation.accept(this, null)); } if (merge.getOutputClause() != null) { @@ -65,54 +66,78 @@ void deParse(Merge merge) { } @Override - public void visit(MergeDelete mergeDelete) { + public StringBuilder visit(MergeDelete mergeDelete, S context) { buffer.append(" WHEN MATCHED"); if (mergeDelete.getAndPredicate() != null) { buffer.append(" AND "); - mergeDelete.getAndPredicate().accept(expressionDeParser); + mergeDelete.getAndPredicate().accept(expressionDeParser, context); } buffer.append(" THEN DELETE"); + return buffer; + } + + public void visit(MergeDelete mergeDelete) { + visit(mergeDelete, null); } @Override - public void visit(MergeUpdate mergeUpdate) { + public StringBuilder visit(MergeUpdate mergeUpdate, S context) { buffer.append(" WHEN MATCHED"); if (mergeUpdate.getAndPredicate() != null) { buffer.append(" AND "); - mergeUpdate.getAndPredicate().accept(expressionDeParser); + mergeUpdate.getAndPredicate().accept(expressionDeParser, context); } buffer.append(" THEN UPDATE SET "); deparseUpdateSets(mergeUpdate.getUpdateSets(), buffer, expressionDeParser); if (mergeUpdate.getWhereCondition() != null) { buffer.append(" WHERE "); - mergeUpdate.getWhereCondition().accept(expressionDeParser); + mergeUpdate.getWhereCondition().accept(expressionDeParser, context); } if (mergeUpdate.getDeleteWhereCondition() != null) { buffer.append(" DELETE WHERE "); - mergeUpdate.getDeleteWhereCondition().accept(expressionDeParser); + mergeUpdate.getDeleteWhereCondition().accept(expressionDeParser, context); } + + return buffer; + } + + public void visit(MergeUpdate mergeUpdate) { + visit(mergeUpdate, null); } @Override - public void visit(MergeInsert mergeInsert) { + public StringBuilder visit(MergeInsert mergeInsert, S context) { buffer.append(" WHEN NOT MATCHED"); if (mergeInsert.getAndPredicate() != null) { buffer.append(" AND "); - mergeInsert.getAndPredicate().accept(expressionDeParser); + mergeInsert.getAndPredicate().accept(expressionDeParser, context); } buffer.append(" THEN INSERT "); if (mergeInsert.getColumns() != null) { - mergeInsert.getColumns().accept(expressionDeParser); + mergeInsert.getColumns().accept(expressionDeParser, context); } buffer.append(" VALUES "); - mergeInsert.getValues().accept(expressionDeParser); + mergeInsert.getValues().accept(expressionDeParser, context); if (mergeInsert.getWhereCondition() != null) { buffer.append(" WHERE "); - mergeInsert.getWhereCondition().accept(expressionDeParser); + mergeInsert.getWhereCondition().accept(expressionDeParser, context); } + + return buffer; + } + + public void visit(MergeInsert mergeInsert) { + visit(mergeInsert, null); + } + + public ExpressionDeParser getExpressionDeParser() { + return expressionDeParser; } + public SelectDeParser getSelectDeParser() { + return selectDeParser; + } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/OrderByDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/OrderByDeParser.java index 8eb137051..90457e73c 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/OrderByDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/OrderByDeParser.java @@ -11,18 +11,20 @@ import java.util.Iterator; import java.util.List; + import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.statement.select.OrderByElement; public class OrderByDeParser extends AbstractDeParser> { - private ExpressionVisitor expressionVisitor; + private ExpressionVisitor expressionVisitor; OrderByDeParser() { super(new StringBuilder()); } - public OrderByDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { + public OrderByDeParser(ExpressionVisitor expressionVisitor, + StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; } @@ -39,17 +41,18 @@ public void deParse(boolean oracleSiblings, List orderByElementL buffer.append(" ORDER BY "); } - for (Iterator iter = orderByElementList.iterator(); iter.hasNext();) { - OrderByElement orderByElement = iter.next(); + for (Iterator iterator = orderByElementList.iterator(); iterator + .hasNext();) { + OrderByElement orderByElement = iterator.next(); deParseElement(orderByElement); - if (iter.hasNext()) { + if (iterator.hasNext()) { buffer.append(", "); } } } public void deParseElement(OrderByElement orderBy) { - orderBy.getExpression().accept(expressionVisitor); + orderBy.getExpression().accept(expressionVisitor, null); if (!orderBy.isAsc()) { buffer.append(" DESC"); } else if (orderBy.isAscDescPresent()) { @@ -66,7 +69,7 @@ public void deParseElement(OrderByElement orderBy) { } } - void setExpressionVisitor(ExpressionVisitor expressionVisitor) { + void setExpressionVisitor(ExpressionVisitor expressionVisitor) { this.expressionVisitor = expressionVisitor; } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ResetStatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ResetStatementDeParser.java index 9f566d93e..903bb1bbc 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ResetStatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ResetStatementDeParser.java @@ -14,9 +14,10 @@ public class ResetStatementDeParser extends AbstractDeParser { - private ExpressionVisitor expressionVisitor; + private ExpressionVisitor expressionVisitor; - public ResetStatementDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { + public ResetStatementDeParser(ExpressionVisitor expressionVisitor, + StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; } @@ -27,11 +28,11 @@ public void deParse(ResetStatement set) { buffer.append(set.getName()); } - public ExpressionVisitor getExpressionVisitor() { + public ExpressionVisitor getExpressionVisitor() { return expressionVisitor; } - public void setExpressionVisitor(ExpressionVisitor visitor) { + public void setExpressionVisitor(ExpressionVisitor visitor) { expressionVisitor = visitor; } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java index d2a53028c..705db155c 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java @@ -9,20 +9,16 @@ */ package net.sf.jsqlparser.util.deparser; -import static java.util.stream.Collectors.joining; - -import java.util.Iterator; -import java.util.List; import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; -import net.sf.jsqlparser.expression.ExpressionVisitorAdapter; import net.sf.jsqlparser.expression.MySQLIndexHint; import net.sf.jsqlparser.expression.OracleHint; import net.sf.jsqlparser.expression.SQLServerHints; import net.sf.jsqlparser.expression.WindowDefinition; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.select.Distinct; import net.sf.jsqlparser.statement.select.Fetch; import net.sf.jsqlparser.statement.select.First; import net.sf.jsqlparser.statement.select.FromItem; @@ -32,6 +28,7 @@ import net.sf.jsqlparser.statement.select.LateralView; import net.sf.jsqlparser.statement.select.Offset; import net.sf.jsqlparser.statement.select.OptimizeFor; +import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.ParenthesedFromItem; import net.sf.jsqlparser.statement.select.ParenthesedSelect; import net.sf.jsqlparser.statement.select.Pivot; @@ -50,81 +47,111 @@ import net.sf.jsqlparser.statement.select.Values; import net.sf.jsqlparser.statement.select.WithItem; +import java.lang.reflect.InvocationTargetException; +import java.util.Iterator; +import java.util.List; + +import static java.util.stream.Collectors.joining; + @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"}) -public class SelectDeParser extends AbstractDeParser implements SelectVisitor, - SelectItemVisitor, FromItemVisitor, PivotVisitor { +public class SelectDeParser extends AbstractDeParser + implements SelectVisitor, SelectItemVisitor, + FromItemVisitor, PivotVisitor { - private ExpressionVisitor expressionVisitor; + private ExpressionVisitor expressionVisitor; public SelectDeParser() { this(new StringBuilder()); } public SelectDeParser(StringBuilder buffer) { - this(new ExpressionVisitorAdapter(), buffer); + super(buffer); + this.expressionVisitor = new ExpressionDeParser(this, buffer); } - public SelectDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { + public SelectDeParser(Class expressionDeparserClass, + StringBuilder builder) throws NoSuchMethodException, InvocationTargetException, + InstantiationException, IllegalAccessException { + super(builder); + this.expressionVisitor = + expressionDeparserClass.getConstructor(SelectDeParser.class, StringBuilder.class) + .newInstance(this, builder); + } + + public SelectDeParser(Class expressionDeparserClass) + throws NoSuchMethodException, InvocationTargetException, InstantiationException, + IllegalAccessException { + this(expressionDeparserClass, new StringBuilder()); + } + + + public SelectDeParser(ExpressionVisitor expressionVisitor, + StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; } @Override - public void visit(ParenthesedSelect selectBody) { - List withItemsList = selectBody.getWithItemsList(); + public StringBuilder visit(ParenthesedSelect select, S context) { + List withItemsList = select.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { buffer.append("WITH "); for (WithItem withItem : withItemsList) { - withItem.accept((SelectVisitor) this); + withItem.accept((SelectVisitor) this, context); buffer.append(" "); } } buffer.append("("); - selectBody.getSelect().accept((SelectVisitor) this); + select.getSelect().accept(this, context); buffer.append(")"); - if (selectBody.getOrderByElements() != null) { - new OrderByDeParser(expressionVisitor, buffer).deParse(selectBody.isOracleSiblings(), - selectBody.getOrderByElements()); + if (select.getOrderByElements() != null) { + new OrderByDeParser(expressionVisitor, buffer).deParse(select.isOracleSiblings(), + select.getOrderByElements()); } - Alias alias = selectBody.getAlias(); + Alias alias = select.getAlias(); if (alias != null) { buffer.append(alias); } - Pivot pivot = selectBody.getPivot(); + Pivot pivot = select.getPivot(); if (pivot != null) { - pivot.accept(this); + pivot.accept(this, context); } - UnPivot unpivot = selectBody.getUnPivot(); + UnPivot unpivot = select.getUnPivot(); if (unpivot != null) { - unpivot.accept(this); + unpivot.accept(this, context); } - if (selectBody.getLimit() != null) { - new LimitDeparser(expressionVisitor, buffer).deParse(selectBody.getLimit()); + if (select.getLimit() != null) { + new LimitDeparser(expressionVisitor, buffer).deParse(select.getLimit()); } - if (selectBody.getOffset() != null) { - visit(selectBody.getOffset()); + if (select.getOffset() != null) { + visit(select.getOffset()); } - if (selectBody.getFetch() != null) { - visit(selectBody.getFetch()); + if (select.getFetch() != null) { + visit(select.getFetch()); } - if (selectBody.getIsolation() != null) { - buffer.append(selectBody.getIsolation().toString()); + if (select.getIsolation() != null) { + buffer.append(select.getIsolation().toString()); } + return buffer; + } + + public void visit(Top top) { + buffer.append(top).append(" "); } @Override @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.ExcessiveMethodLength", "PMD.NPathComplexity"}) - public void visit(PlainSelect plainSelect) { + public StringBuilder visit(PlainSelect plainSelect, S context) { List withItemsList = plainSelect.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { buffer.append("WITH "); for (Iterator iter = withItemsList.iterator(); iter.hasNext();) { - iter.next().accept((SelectVisitor) this); + iter.next().accept((SelectVisitor) this, context); if (iter.hasNext()) { buffer.append(","); } @@ -153,30 +180,22 @@ public void visit(PlainSelect plainSelect) { buffer.append(first).append(" "); } - if (plainSelect.getDistinct() != null) { - if (plainSelect.getDistinct().isUseUnique()) { - buffer.append("UNIQUE "); - } else { - buffer.append("DISTINCT "); - } - if (plainSelect.getDistinct().getOnSelectItems() != null) { - buffer.append("ON ("); - for (Iterator> iter = - plainSelect.getDistinct().getOnSelectItems().iterator(); iter.hasNext();) { - SelectItem selectItem = iter.next(); - selectItem.accept(this); - if (iter.hasNext()) { - buffer.append(", "); - } - } - buffer.append(") "); - } + deparseDistinctClause(plainSelect.getDistinct()); + if (plainSelect.getBigQuerySelectQualifier() != null) { + switch (plainSelect.getBigQuerySelectQualifier()) { + case AS_STRUCT: + buffer.append("AS STRUCT "); + break; + case AS_VALUE: + buffer.append("AS VALUE "); + break; + } } Top top = plainSelect.getTop(); if (top != null) { - buffer.append(top).append(" "); + visit(top); } if (plainSelect.getMySqlSqlCacheFlag() != null) { @@ -187,21 +206,12 @@ public void visit(PlainSelect plainSelect) { buffer.append("SQL_CALC_FOUND_ROWS").append(" "); } - final List> selectItems = plainSelect.getSelectItems(); - if (selectItems != null) { - for (Iterator> iter = selectItems.iterator(); iter.hasNext();) { - SelectItem selectItem = iter.next(); - selectItem.accept(this); - if (iter.hasNext()) { - buffer.append(", "); - } - } - } + deparseSelectItemsClause(plainSelect.getSelectItems()); if (plainSelect.getIntoTables() != null) { buffer.append(" INTO "); for (Iterator

iter = plainSelect.getIntoTables().iterator(); iter.hasNext();) { - visit(iter.next()); + visit(iter.next(), context); if (iter.hasNext()) { buffer.append(", "); } @@ -213,7 +223,7 @@ public void visit(PlainSelect plainSelect) { if (plainSelect.isUsingOnly()) { buffer.append("ONLY "); } - plainSelect.getFromItem().accept(this); + plainSelect.getFromItem().accept(this, context); if (plainSelect.getFromItem() instanceof Table) { Table table = (Table) plainSelect.getFromItem(); @@ -244,13 +254,10 @@ public void visit(PlainSelect plainSelect) { buffer.append(plainSelect.getKsqlWindow().toString()); } - if (plainSelect.getWhere() != null) { - buffer.append(" WHERE "); - plainSelect.getWhere().accept(expressionVisitor); - } + deparseWhereClause(plainSelect); if (plainSelect.getOracleHierarchical() != null) { - plainSelect.getOracleHierarchical().accept(expressionVisitor); + plainSelect.getOracleHierarchical().accept(expressionVisitor, context); } if (plainSelect.getGroupBy() != null) { @@ -260,42 +267,22 @@ public void visit(PlainSelect plainSelect) { if (plainSelect.getHaving() != null) { buffer.append(" HAVING "); - plainSelect.getHaving().accept(expressionVisitor); + plainSelect.getHaving().accept(expressionVisitor, context); } if (plainSelect.getQualify() != null) { buffer.append(" QUALIFY "); - plainSelect.getQualify().accept(expressionVisitor); + plainSelect.getQualify().accept(expressionVisitor, context); } if (plainSelect.getWindowDefinitions() != null) { buffer.append(" WINDOW "); buffer.append(plainSelect.getWindowDefinitions().stream() .map(WindowDefinition::toString).collect(joining(", "))); } - if (plainSelect.getForMode() != null) { - buffer.append(" FOR "); - buffer.append(plainSelect.getForMode().getValue()); - - if (plainSelect.getForUpdateTable() != null) { - buffer.append(" OF ").append(plainSelect.getForUpdateTable()); - } - if (plainSelect.getWait() != null) { - // wait's toString will do the formatting for us - buffer.append(plainSelect.getWait()); - } - if (plainSelect.isNoWait()) { - buffer.append(" NOWAIT"); - } else if (plainSelect.isSkipLocked()) { - buffer.append(" SKIP LOCKED"); - } - } if (plainSelect.getForClause() != null) { plainSelect.getForClause().appendTo(buffer); } - if (plainSelect.getOrderByElements() != null) { - new OrderByDeParser(expressionVisitor, buffer).deParse(plainSelect.isOracleSiblings(), - plainSelect.getOrderByElements()); - } + deparseOrderByElementsClause(plainSelect, plainSelect.getOrderByElements()); if (plainSelect.isEmitChanges()) { buffer.append(" EMIT CHANGES"); } @@ -314,6 +301,23 @@ public void visit(PlainSelect plainSelect) { if (plainSelect.getIsolation() != null) { buffer.append(plainSelect.getIsolation().toString()); } + if (plainSelect.getForMode() != null) { + buffer.append(" FOR "); + buffer.append(plainSelect.getForMode().getValue()); + + if (plainSelect.getForUpdateTable() != null) { + buffer.append(" OF ").append(plainSelect.getForUpdateTable()); + } + if (plainSelect.getWait() != null) { + // wait's toString will do the formatting for us + buffer.append(plainSelect.getWait()); + } + if (plainSelect.isNoWait()) { + buffer.append(" NOWAIT"); + } else if (plainSelect.isSkipLocked()) { + buffer.append(" SKIP LOCKED"); + } + } if (plainSelect.getOptimizeFor() != null) { deparseOptimizeFor(plainSelect.getOptimizeFor()); } @@ -326,20 +330,70 @@ public void visit(PlainSelect plainSelect) { if (plainSelect.isUseWithNoLog()) { buffer.append(" WITH NO LOG"); } + return buffer; + } + protected void deparseWhereClause(PlainSelect plainSelect) { + if (plainSelect.getWhere() != null) { + buffer.append(" WHERE "); + plainSelect.getWhere().accept(expressionVisitor, null); + } + } + + protected void deparseDistinctClause(Distinct distinct) { + if (distinct != null) { + if (distinct.isUseUnique()) { + buffer.append("UNIQUE "); + } else { + buffer.append("DISTINCT "); + } + if (distinct.getOnSelectItems() != null) { + buffer.append("ON ("); + for (Iterator> iter = distinct.getOnSelectItems().iterator(); iter + .hasNext();) { + SelectItem selectItem = iter.next(); + selectItem.accept(this, null); + if (iter.hasNext()) { + buffer.append(", "); + } + } + buffer.append(") "); + } + } + } + + protected void deparseSelectItemsClause(List> selectItems) { + if (selectItems != null) { + for (Iterator> iter = selectItems.iterator(); iter.hasNext();) { + SelectItem selectItem = iter.next(); + selectItem.accept(this, null); + if (iter.hasNext()) { + buffer.append(", "); + } + } + } + } + + protected void deparseOrderByElementsClause(PlainSelect plainSelect, + List orderByElements) { + if (orderByElements != null) { + new OrderByDeParser(expressionVisitor, buffer).deParse(plainSelect.isOracleSiblings(), + orderByElements); + } } @Override - public void visit(SelectItem selectExpressionItem) { - selectExpressionItem.getExpression().accept(expressionVisitor); - if (selectExpressionItem.getAlias() != null) { - buffer.append(selectExpressionItem.getAlias().toString()); + public StringBuilder visit(SelectItem selectItem, S context) { + selectItem.getExpression().accept(expressionVisitor, context); + if (selectItem.getAlias() != null) { + buffer.append(selectItem.getAlias().toString()); } + return buffer; } @Override - public void visit(Table tableName) { + public StringBuilder visit(Table tableName, S context) { buffer.append(tableName.getFullyQualifiedName()); Alias alias = tableName.getAlias(); if (alias != null) { @@ -347,11 +401,11 @@ public void visit(Table tableName) { } Pivot pivot = tableName.getPivot(); if (pivot != null) { - pivot.accept(this); + pivot.accept(this, context); } UnPivot unpivot = tableName.getUnPivot(); if (unpivot != null) { - unpivot.accept(this); + unpivot.accept(this, context); } MySQLIndexHint indexHint = tableName.getIndexHint(); if (indexHint != null) { @@ -361,15 +415,16 @@ public void visit(Table tableName) { if (sqlServerHints != null) { buffer.append(sqlServerHints); } + return buffer; } @Override - public void visit(Pivot pivot) { + public StringBuilder visit(Pivot pivot, S context) { // @todo: implement this as Visitor buffer.append(" PIVOT (").append(PlainSelect.getStringList(pivot.getFunctionItems())); buffer.append(" FOR "); - pivot.getForColumns().accept(expressionVisitor); + pivot.getForColumns().accept(expressionVisitor, context); // @todo: implement this as Visitor buffer.append(" IN ").append(PlainSelect.getStringList(pivot.getInItems(), true, true)); @@ -378,10 +433,11 @@ public void visit(Pivot pivot) { if (pivot.getAlias() != null) { buffer.append(pivot.getAlias().toString()); } + return buffer; } @Override - public void visit(UnPivot unpivot) { + public StringBuilder visit(UnPivot unpivot, S context) { boolean showOptions = unpivot.getIncludeNullsSpecified(); boolean includeNulls = unpivot.getIncludeNulls(); List unPivotClause = unpivot.getUnPivotClause(); @@ -399,10 +455,11 @@ public void visit(UnPivot unpivot) { if (unpivot.getAlias() != null) { buffer.append(unpivot.getAlias().toString()); } + return buffer; } @Override - public void visit(PivotXml pivot) { + public StringBuilder visit(PivotXml pivot, S context) { List forColumns = pivot.getForColumns(); buffer.append(" PIVOT XML (").append(PlainSelect.getStringList(pivot.getFunctionItems())) .append(" FOR ").append(PlainSelect.getStringList(forColumns, true, @@ -416,13 +473,14 @@ public void visit(PivotXml pivot) { buffer.append(PlainSelect.getStringList(pivot.getInItems())); } buffer.append("))"); + return buffer; } public void visit(Offset offset) { // OFFSET offset // or OFFSET offset (ROW | ROWS) buffer.append(" OFFSET "); - offset.getOffset().accept(expressionVisitor); + offset.getOffset().accept(expressionVisitor, null); if (offset.getOffsetParam() != null) { buffer.append(" ").append(offset.getOffsetParam()); } @@ -437,7 +495,7 @@ public void visit(Fetch fetch) { buffer.append("NEXT "); } if (fetch.getExpression() != null) { - fetch.getExpression().accept(expressionVisitor); + fetch.getExpression().accept(expressionVisitor, null); } for (String p : fetch.getFetchParameters()) { @@ -445,11 +503,11 @@ public void visit(Fetch fetch) { } } - public ExpressionVisitor getExpressionVisitor() { + public ExpressionVisitor getExpressionVisitor() { return expressionVisitor; } - public void setExpressionVisitor(ExpressionVisitor visitor) { + public void setExpressionVisitor(ExpressionVisitor visitor) { expressionVisitor = visitor; } @@ -501,16 +559,16 @@ public void deparseJoin(Join join) { } FromItem fromItem = join.getFromItem(); - fromItem.accept(this); + fromItem.accept(this, null); if (join.isWindowJoin()) { buffer.append(" WITHIN "); buffer.append(join.getJoinWindow().toString()); } for (Expression onExpression : join.getOnExpressions()) { buffer.append(" ON "); - onExpression.accept(expressionVisitor); + onExpression.accept(expressionVisitor, null); } - if (join.getUsingColumns().size() > 0) { + if (!join.getUsingColumns().isEmpty()) { buffer.append(" USING ("); for (Iterator iterator = join.getUsingColumns().iterator(); iterator .hasNext();) { @@ -533,7 +591,7 @@ public void deparseLateralView(LateralView lateralView) { } buffer.append(" "); - lateralView.getGeneratorFunction().accept(expressionVisitor); + lateralView.getGeneratorFunction().accept(expressionVisitor, null); if (lateralView.getTableAlias() != null) { buffer.append(" ").append(lateralView.getTableAlias()); @@ -543,12 +601,12 @@ public void deparseLateralView(LateralView lateralView) { } @Override - public void visit(SetOperationList list) { + public StringBuilder visit(SetOperationList list, S context) { List withItemsList = list.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { buffer.append("WITH "); for (Iterator iter = withItemsList.iterator(); iter.hasNext();) { - iter.next().accept((SelectVisitor) this); + iter.next().accept((SelectVisitor) this, context); if (iter.hasNext()) { buffer.append(","); } @@ -560,7 +618,7 @@ public void visit(SetOperationList list) { if (i != 0) { buffer.append(' ').append(list.getOperations().get(i - 1)).append(' '); } - list.getSelects().get(i).accept(this); + list.getSelects().get(i).accept(this, context); } if (list.getOrderByElements() != null) { new OrderByDeParser(expressionVisitor, buffer).deParse(list.getOrderByElements()); @@ -578,10 +636,11 @@ public void visit(SetOperationList list) { if (list.getIsolation() != null) { buffer.append(list.getIsolation().toString()); } + return buffer; } @Override - public void visit(WithItem withItem) { + public StringBuilder visit(WithItem withItem, S context) { if (withItem.isRecursive()) { buffer.append("RECURSIVE "); } @@ -591,30 +650,35 @@ public void visit(WithItem withItem) { .append(PlainSelect.getStringList(withItem.getWithItemList(), true, true)); } buffer.append(" AS "); - withItem.getSelect().accept(this); + withItem.getSelect().accept(this, context); + return buffer; } @Override - public void visit(LateralSubSelect lateralSubSelect) { + public StringBuilder visit(LateralSubSelect lateralSubSelect, S context) { buffer.append(lateralSubSelect.getPrefix()); - visit((ParenthesedSelect) lateralSubSelect); + visit((ParenthesedSelect) lateralSubSelect, context); + + return buffer; } @Override - public void visit(TableStatement tableStatement) { + public StringBuilder visit(TableStatement tableStatement, S context) { new TableStatementDeParser(expressionVisitor, buffer).deParse(tableStatement); + return buffer; } @Override - public void visit(TableFunction tableFunction) { + public StringBuilder visit(TableFunction tableFunction, S context) { buffer.append(tableFunction.toString()); + return buffer; } @Override - public void visit(ParenthesedFromItem fromItem) { + public StringBuilder visit(ParenthesedFromItem fromItem, S context) { buffer.append("("); - fromItem.getFromItem().accept(this); + fromItem.getFromItem().accept(this, context); List joins = fromItem.getJoins(); if (joins != null) { for (Join join : joins) { @@ -632,19 +696,79 @@ public void visit(ParenthesedFromItem fromItem) { } if (fromItem.getPivot() != null) { - visit(fromItem.getPivot()); + visit(fromItem.getPivot(), context); } if (fromItem.getUnPivot() != null) { - visit(fromItem.getUnPivot()); + visit(fromItem.getUnPivot(), context); } + return buffer; } @Override - public void visit(Values values) { + public StringBuilder visit(Values values, S context) { new ValuesStatementDeParser(expressionVisitor, buffer).deParse(values); + return buffer; + } + + @Override + public void visit(Values values) { + SelectVisitor.super.visit(values); } + public void visit(ParenthesedSelect select) { + visit(select, null); + } + + public void visit(PlainSelect plainSelect) { + visit(plainSelect, null); + } + + public void visit(SelectItem selectExpressionItem) { + visit(selectExpressionItem, null); + } + + public void visit(Table tableName) { + visit(tableName, null); + } + + public void visit(Pivot pivot) { + visit(pivot, null); + } + + public void visit(UnPivot unpivot) { + visit(unpivot, null); + } + + public void visit(PivotXml pivot) { + visit(pivot, null); + } + + public void visit(SetOperationList list) { + visit(list, null); + } + + public void visit(WithItem withItem) { + visit(withItem, null); + } + + public void visit(LateralSubSelect lateralSubSelect) { + visit(lateralSubSelect, null); + } + + public void visit(TableStatement tableStatement) { + visit(tableStatement, null); + } + + public void visit(TableFunction tableFunction) { + visit(tableFunction, null); + } + + public void visit(ParenthesedFromItem fromItem) { + visit(fromItem, null); + } + + private void deparseOptimizeFor(OptimizeFor optimizeFor) { buffer.append(" OPTIMIZE FOR "); buffer.append(optimizeFor.getRowCount()); @@ -653,7 +777,7 @@ private void deparseOptimizeFor(OptimizeFor optimizeFor) { @Override void deParse(PlainSelect statement) { - statement.accept((SelectVisitor) this); + statement.accept(this, null); } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/SetStatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/SetStatementDeParser.java index d6371b8f3..e38cb418c 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/SetStatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/SetStatementDeParser.java @@ -17,9 +17,10 @@ public class SetStatementDeParser extends AbstractDeParser { - private ExpressionVisitor expressionVisitor; + private ExpressionVisitor expressionVisitor; - public SetStatementDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { + public SetStatementDeParser(ExpressionVisitor expressionVisitor, + StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; } @@ -44,17 +45,17 @@ public void deParse(SetStatement set) { if (j > 0) { buffer.append(", "); } - expressions.get(j).accept(expressionVisitor); + expressions.get(j).accept(expressionVisitor, null); } } } - public ExpressionVisitor getExpressionVisitor() { + public ExpressionVisitor getExpressionVisitor() { return expressionVisitor; } - public void setExpressionVisitor(ExpressionVisitor visitor) { + public void setExpressionVisitor(ExpressionVisitor visitor) { expressionVisitor = visitor; } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ShowIndexStatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ShowIndexStatementDeParser.java index b79d0bdda..5e4a223bd 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ShowIndexStatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ShowIndexStatementDeParser.java @@ -12,12 +12,11 @@ import net.sf.jsqlparser.statement.show.ShowIndexStatement; /** -* -* @author Jayant Kumar Yadav -*/ + * @author Jayant Kumar Yadav + */ public class ShowIndexStatementDeParser extends AbstractDeParser { - + public ShowIndexStatementDeParser(StringBuilder buffer) { super(buffer); } @@ -26,5 +25,5 @@ public ShowIndexStatementDeParser(StringBuilder buffer) { public void deParse(ShowIndexStatement show) { buffer.append("SHOW INDEX FROM ").append(show.getTableName()); } - -} \ No newline at end of file + +} diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java index f9d314642..30cf27f79 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java @@ -9,7 +9,9 @@ */ package net.sf.jsqlparser.util.deparser; +import java.lang.reflect.InvocationTargetException; import java.util.stream.Collectors; + import net.sf.jsqlparser.statement.Block; import net.sf.jsqlparser.statement.Commit; import net.sf.jsqlparser.statement.CreateFunctionalStatement; @@ -57,12 +59,36 @@ import net.sf.jsqlparser.statement.update.Update; import net.sf.jsqlparser.statement.upsert.Upsert; -public class StatementDeParser extends AbstractDeParser implements StatementVisitor { +public class StatementDeParser extends AbstractDeParser + implements StatementVisitor { private final ExpressionDeParser expressionDeParser; private final SelectDeParser selectDeParser; + public StatementDeParser(Class expressionDeparserClass, + Class selectDeparserClass, StringBuilder builder) + throws NoSuchMethodException, InvocationTargetException, InstantiationException, + IllegalAccessException { + super(builder); + + this.selectDeParser = selectDeparserClass + .getConstructor(Class.class, StringBuilder.class) + .newInstance(expressionDeparserClass, builder); + + + this.expressionDeParser = + expressionDeparserClass.cast(this.selectDeParser.getExpressionVisitor()); + + } + + public StatementDeParser(Class expressionDeparserClass, + Class selectDeparserClass) + throws NoSuchMethodException, InvocationTargetException, InstantiationException, + IllegalAccessException { + this(expressionDeparserClass, selectDeparserClass, new StringBuilder()); + } + public StatementDeParser(StringBuilder buffer) { this(new ExpressionDeParser(), new SelectDeParser(), buffer); } @@ -82,60 +108,70 @@ public StatementDeParser(ExpressionDeParser expressionDeParser, SelectDeParser s } @Override - public void visit(CreateIndex createIndex) { + public StringBuilder visit(CreateIndex createIndex, S context) { CreateIndexDeParser createIndexDeParser = new CreateIndexDeParser(buffer); createIndexDeParser.deParse(createIndex); + return buffer; } @Override - public void visit(CreateTable createTable) { + public StringBuilder visit(CreateTable createTable, S context) { CreateTableDeParser createTableDeParser = new CreateTableDeParser(this, buffer); createTableDeParser.deParse(createTable); + return buffer; } @Override - public void visit(CreateView createView) { + public StringBuilder visit(CreateView createView, S context) { CreateViewDeParser createViewDeParser = new CreateViewDeParser(buffer); createViewDeParser.deParse(createView); + return buffer; } @Override - public void visit(RefreshMaterializedViewStatement materializedViewStatement) { + public StringBuilder visit(RefreshMaterializedViewStatement materializedViewStatement, + S context) { new RefreshMaterializedViewStatementDeParser(buffer).deParse(materializedViewStatement); + return buffer; } @Override - public void visit(AlterView alterView) { + public StringBuilder visit(AlterView alterView, S context) { AlterViewDeParser alterViewDeParser = new AlterViewDeParser(buffer); alterViewDeParser.deParse(alterView); + return buffer; } @Override - public void visit(Delete delete) { + public StringBuilder visit(Delete delete, S context) { DeleteDeParser deleteDeParser = new DeleteDeParser(expressionDeParser, buffer); deleteDeParser.deParse(delete); + return buffer; } @Override - public void visit(Drop drop) { + public StringBuilder visit(Drop drop, S context) { DropDeParser dropDeParser = new DropDeParser(buffer); dropDeParser.deParse(drop); + return buffer; } @Override - public void visit(Insert insert) { + public StringBuilder visit(Insert insert, S context) { InsertDeParser insertDeParser = new InsertDeParser(expressionDeParser, selectDeParser, buffer); insertDeParser.deParse(insert); + return buffer; } @Override - public void visit(Select select) { - select.accept(selectDeParser); + public StringBuilder visit(Select select, S context) { + select.accept(selectDeParser, context); + return buffer; } @Override - public void visit(Truncate truncate) { + public StringBuilder visit(Truncate truncate, S context) { buffer.append("TRUNCATE"); if (truncate.isTableToken()) { buffer.append(" TABLE"); @@ -150,105 +186,122 @@ public void visit(Truncate truncate) { buffer.append(" CASCADE"); } + return buffer; } @Override - public void visit(Update update) { + public StringBuilder visit(Update update, S context) { UpdateDeParser updateDeParser = new UpdateDeParser(expressionDeParser, buffer); updateDeParser.deParse(update); + return buffer; } - public void visit(Analyze analyzer) { + public StringBuilder visit(Analyze analyzer, S context) { buffer.append("ANALYZE "); buffer.append(analyzer.getTable()); + return buffer; } @Override - public void visit(Alter alter) { + public StringBuilder visit(Alter alter, S context) { AlterDeParser alterDeParser = new AlterDeParser(buffer); alterDeParser.deParse(alter); + return buffer; } @Override - public void visit(Statements stmts) { - stmts.accept(this); + public StringBuilder visit(Statements statements, S context) { + statements.accept(this, context); + return buffer; } @Override - public void visit(Execute execute) { + public StringBuilder visit(Execute execute, S context) { ExecuteDeParser executeDeParser = new ExecuteDeParser(expressionDeParser, buffer); executeDeParser.deParse(execute); + return buffer; } @Override - public void visit(SetStatement set) { + public StringBuilder visit(SetStatement set, S context) { SetStatementDeParser setStatementDeparser = new SetStatementDeParser(expressionDeParser, buffer); setStatementDeparser.deParse(set); + return buffer; } @Override - public void visit(ResetStatement reset) { + public StringBuilder visit(ResetStatement reset, S context) { ResetStatementDeParser setStatementDeparser = new ResetStatementDeParser(expressionDeParser, buffer); setStatementDeparser.deParse(reset); + return buffer; } @SuppressWarnings({"PMD.CyclomaticComplexity"}) @Override - public void visit(Merge merge) { + public StringBuilder visit(Merge merge, S context) { new MergeDeParser(expressionDeParser, selectDeParser, buffer).deParse(merge); + return buffer; } @Override - public void visit(SavepointStatement savepointStatement) { + public StringBuilder visit(SavepointStatement savepointStatement, S context) { buffer.append(savepointStatement.toString()); + return buffer; } @Override - public void visit(RollbackStatement rollbackStatement) { + public StringBuilder visit(RollbackStatement rollbackStatement, S context) { buffer.append(rollbackStatement.toString()); + return buffer; } @Override - public void visit(Commit commit) { + public StringBuilder visit(Commit commit, S context) { buffer.append(commit.toString()); + return buffer; } @Override - public void visit(Upsert upsert) { + public StringBuilder visit(Upsert upsert, S context) { UpsertDeParser upsertDeParser = new UpsertDeParser(expressionDeParser, selectDeParser, buffer); upsertDeParser.deParse(upsert); + return buffer; } @Override - public void visit(UseStatement use) { + public StringBuilder visit(UseStatement use, S context) { new UseStatementDeParser(buffer).deParse(use); + return buffer; } @Override - public void visit(ShowColumnsStatement show) { + public StringBuilder visit(ShowColumnsStatement show, S context) { new ShowColumnsStatementDeParser(buffer).deParse(show); + return buffer; } @Override - public void visit(ShowIndexStatement showIndexes) { + public StringBuilder visit(ShowIndexStatement showIndexes, S context) { new ShowIndexStatementDeParser(buffer).deParse(showIndexes); + return buffer; } @Override - public void visit(ShowTablesStatement showTables) { + public StringBuilder visit(ShowTablesStatement showTables, S context) { new ShowTablesStatementDeparser(buffer).deParse(showTables); + return buffer; } @Override - public void visit(Block block) { + public StringBuilder visit(Block block, S context) { buffer.append("BEGIN\n"); if (block.getStatements() != null) { for (Statement stmt : block.getStatements().getStatements()) { - stmt.accept(this); + stmt.accept(this, context); buffer.append(";\n"); } } @@ -256,109 +309,134 @@ public void visit(Block block) { if (block.hasSemicolonAfterEnd()) { buffer.append(";"); } + return buffer; } @Override - public void visit(Comment comment) { + public StringBuilder visit(Comment comment, S context) { buffer.append(comment.toString()); + return buffer; } @Override - public void visit(DescribeStatement describe) { + public StringBuilder visit(DescribeStatement describe, S context) { buffer.append(describe.getDescribeType()); buffer.append(" "); buffer.append(describe.getTable()); + return buffer; } @Override - public void visit(ExplainStatement explain) { + public StringBuilder visit(ExplainStatement explainStatement, S context) { buffer.append("EXPLAIN "); - if (explain.getTable() != null) { - buffer.append(explain.getTable()); - } else if (explain.getOptions() != null) { - buffer.append(explain.getOptions().values().stream() + if (explainStatement.getTable() != null) { + buffer.append(explainStatement.getTable()); + } else if (explainStatement.getOptions() != null) { + buffer.append(explainStatement.getOptions().values().stream() .map(ExplainStatement.Option::formatOption).collect(Collectors.joining(" "))); buffer.append(" "); } - if (explain.getStatement() != null) { - explain.getStatement().accept(this); - + if (explainStatement.getStatement() != null) { + explainStatement.getStatement().accept(this, context); } + return buffer; } @Override - public void visit(ShowStatement show) { - new ShowStatementDeParser(buffer).deParse(show); + public StringBuilder visit(ShowStatement showStatement, S context) { + new ShowStatementDeParser(buffer).deParse(showStatement); + return buffer; } @Override - public void visit(DeclareStatement declare) { - new DeclareStatementDeParser(expressionDeParser, buffer).deParse(declare); + public StringBuilder visit(DeclareStatement declareStatement, S context) { + new DeclareStatementDeParser(expressionDeParser, buffer).deParse(declareStatement); + return buffer; } @Override - public void visit(Grant grant) { + public StringBuilder visit(Grant grant, S context) { GrantDeParser grantDeParser = new GrantDeParser(buffer); grantDeParser.deParse(grant); + return buffer; } @Override - public void visit(CreateSchema aThis) { + public StringBuilder visit(CreateSchema aThis, S context) { buffer.append(aThis.toString()); + return buffer; } @Override - public void visit(CreateSequence createSequence) { + public StringBuilder visit(CreateSequence createSequence, S context) { new CreateSequenceDeParser(buffer).deParse(createSequence); + return buffer; } @Override - public void visit(AlterSequence alterSequence) { + public StringBuilder visit(AlterSequence alterSequence, S context) { new AlterSequenceDeParser(buffer).deParse(alterSequence); + return buffer; } @Override - public void visit(CreateFunctionalStatement createFunctionalStatement) { + public StringBuilder visit(CreateFunctionalStatement createFunctionalStatement, S context) { buffer.append(createFunctionalStatement.toString()); + return buffer; } @Override - public void visit(CreateSynonym createSynonym) { + public StringBuilder visit(CreateSynonym createSynonym, S context) { new CreateSynonymDeparser(buffer).deParse(createSynonym); + return buffer; } @Override void deParse(Statement statement) { - statement.accept(this); + statement.accept(this, null); } @Override - public void visit(AlterSession alterSession) { + public StringBuilder visit(AlterSession alterSession, S context) { new AlterSessionDeParser(buffer).deParse(alterSession); + return buffer; } @Override - public void visit(IfElseStatement ifElseStatement) { + public StringBuilder visit(IfElseStatement ifElseStatement, S context) { ifElseStatement.appendTo(buffer); + return buffer; } @Override - public void visit(RenameTableStatement renameTableStatement) { + public StringBuilder visit(RenameTableStatement renameTableStatement, S context) { renameTableStatement.appendTo(buffer); + return buffer; } @Override - public void visit(PurgeStatement purgeStatement) { + public StringBuilder visit(PurgeStatement purgeStatement, S context) { purgeStatement.appendTo(buffer); + return buffer; } @Override - public void visit(AlterSystemStatement alterSystemStatement) { + public StringBuilder visit(AlterSystemStatement alterSystemStatement, S context) { alterSystemStatement.appendTo(buffer); + return buffer; } @Override - public void visit(UnsupportedStatement unsupportedStatement) { + public StringBuilder visit(UnsupportedStatement unsupportedStatement, S context) { unsupportedStatement.appendTo(buffer); + return buffer; + } + + public ExpressionDeParser getExpressionDeParser() { + return expressionDeParser; + } + + public SelectDeParser getSelectDeParser() { + return selectDeParser; } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/TableStatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/TableStatementDeParser.java index 962849c6e..be83df5bb 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/TableStatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/TableStatementDeParser.java @@ -24,23 +24,24 @@ * @author jxnu-liguobin */ public class TableStatementDeParser extends AbstractDeParser - implements SelectVisitor { + implements SelectVisitor { - private final ExpressionVisitor expressionVisitor; + private final ExpressionVisitor expressionVisitor; - public TableStatementDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { + public TableStatementDeParser(ExpressionVisitor expressionVisitor, + StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; } @Override public void deParse(TableStatement tableStatement) { - tableStatement.accept(this); + tableStatement.accept(this, null); } - public void visit(Offset offset) { + public void deparse(Offset offset) { buffer.append(" OFFSET "); - offset.getOffset().accept(expressionVisitor); + offset.getOffset().accept(expressionVisitor, null); if (offset.getOffsetParam() != null) { buffer.append(" ").append(offset.getOffsetParam()); } @@ -48,37 +49,43 @@ public void visit(Offset offset) { } @Override - public void visit(ParenthesedSelect parenthesedSelect) { + public StringBuilder visit(ParenthesedSelect parenthesedSelect, S context) { + return buffer; } @Override - public void visit(PlainSelect plainSelect) { + public StringBuilder visit(PlainSelect plainSelect, S context) { + return buffer; } @Override - public void visit(SetOperationList setOpList) { + public StringBuilder visit(SetOperationList setOperationList, S context) { + return buffer; } @Override - public void visit(WithItem withItem) { + public StringBuilder visit(WithItem withItem, S context) { + return buffer; } @Override - public void visit(Values aThis) { + public StringBuilder visit(Values values, S context) { + return buffer; } @Override - public void visit(LateralSubSelect lateralSubSelect) { + public StringBuilder visit(LateralSubSelect lateralSubSelect, S context) { + return buffer; } @Override - public void visit(TableStatement tableStatement) { + public StringBuilder visit(TableStatement tableStatement, S context) { buffer.append("TABLE "); buffer.append(tableStatement.getTable()); if (tableStatement.getOrderByElements() != null) { @@ -90,9 +97,10 @@ public void visit(TableStatement tableStatement) { new LimitDeparser(expressionVisitor, buffer).deParse(tableStatement.getLimit()); } if (tableStatement.getOffset() != null) { - visit(tableStatement.getOffset()); + deparse(tableStatement.getOffset()); } // TODO UNION + return buffer; } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java index 0ba4003c4..682c1c067 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java @@ -19,15 +19,17 @@ import java.util.Iterator; -public class UpdateDeParser extends AbstractDeParser implements OrderByVisitor { +public class UpdateDeParser extends AbstractDeParser + implements OrderByVisitor { - private ExpressionVisitor expressionVisitor = new ExpressionVisitorAdapter(); + private ExpressionVisitor expressionVisitor = new ExpressionVisitorAdapter<>(); public UpdateDeParser() { super(new StringBuilder()); } - public UpdateDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { + public UpdateDeParser(ExpressionVisitor expressionVisitor, + StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; } @@ -69,7 +71,7 @@ public void deParse(Update update) { } buffer.append(" SET "); - deparseUpdateSets(update.getUpdateSets(), buffer, expressionVisitor); + deparseUpdateSetsClause(update); if (update.getOutputClause() != null) { update.getOutputClause().appendTo(buffer); @@ -88,10 +90,8 @@ public void deParse(Update update) { } } - if (update.getWhere() != null) { - buffer.append(" WHERE "); - update.getWhere().accept(expressionVisitor); - } + deparseWhereClause(update); + if (update.getOrderByElements() != null) { new OrderByDeParser(expressionVisitor, buffer).deParse(update.getOrderByElements()); } @@ -104,17 +104,29 @@ public void deParse(Update update) { } } - public ExpressionVisitor getExpressionVisitor() { + protected void deparseWhereClause(Update update) { + if (update.getWhere() != null) { + buffer.append(" WHERE "); + update.getWhere().accept(expressionVisitor, null); + } + } + + protected void deparseUpdateSetsClause(Update update) { + deparseUpdateSets(update.getUpdateSets(), buffer, expressionVisitor); + } + + + public ExpressionVisitor getExpressionVisitor() { return expressionVisitor; } - public void setExpressionVisitor(ExpressionVisitor visitor) { + public void setExpressionVisitor(ExpressionVisitor visitor) { expressionVisitor = visitor; } @Override - public void visit(OrderByElement orderBy) { - orderBy.getExpression().accept(expressionVisitor); + public StringBuilder visit(OrderByElement orderBy, S context) { + orderBy.getExpression().accept(expressionVisitor, context); if (!orderBy.isAsc()) { buffer.append(" DESC"); } else if (orderBy.isAscDescPresent()) { @@ -126,5 +138,6 @@ public void visit(OrderByElement orderBy) { ? "NULLS FIRST" : "NULLS LAST"); } + return buffer; } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/UpsertDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/UpsertDeParser.java index 407a4c6e7..719c12a80 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/UpsertDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/UpsertDeParser.java @@ -66,16 +66,16 @@ public void deParse(Upsert upsert) { deparseUpdateSets(upsert.getUpdateSets(), buffer, expressionVisitor); } else { if (upsert.getColumns() != null) { - upsert.getColumns().accept(expressionVisitor); + upsert.getColumns().accept(expressionVisitor, null); } if (upsert.getExpressions() != null) { - upsert.getExpressions().accept(expressionVisitor); + upsert.getExpressions().accept(expressionVisitor, null); } if (upsert.getSelect() != null) { buffer.append(" "); - upsert.getSelect().accept(selectVisitor); + upsert.getSelect().accept(selectVisitor, null); } if (upsert.getDuplicateUpdateSets() != null) { @@ -85,18 +85,18 @@ public void deParse(Upsert upsert) { } } - public ExpressionVisitor getExpressionVisitor() { + public ExpressionVisitor getExpressionVisitor() { return expressionVisitor; } - public SelectVisitor getSelectVisitor() { - return selectVisitor; - } - public void setExpressionVisitor(ExpressionDeParser visitor) { expressionVisitor = visitor; } + public SelectVisitor getSelectVisitor() { + return selectVisitor; + } + public void setSelectVisitor(SelectDeParser visitor) { selectVisitor = visitor; } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ValuesStatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ValuesStatementDeParser.java index 233ec71c3..8b57da126 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ValuesStatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ValuesStatementDeParser.java @@ -14,9 +14,10 @@ public class ValuesStatementDeParser extends AbstractDeParser { - private final ExpressionVisitor expressionVisitor; + private final ExpressionVisitor expressionVisitor; - public ValuesStatementDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) { + public ValuesStatementDeParser(ExpressionVisitor expressionVisitor, + StringBuilder buffer) { super(buffer); this.expressionVisitor = expressionVisitor; } @@ -24,6 +25,9 @@ public ValuesStatementDeParser(ExpressionVisitor expressionVisitor, StringBuilde @Override public void deParse(Values values) { buffer.append("VALUES "); - values.getExpressions().accept(expressionVisitor); + values.getExpressions().accept(expressionVisitor, null); + if (values.getAlias() != null) { + buffer.append(" ").append(values.getAlias()); + } } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/ContextKey.java b/src/main/java/net/sf/jsqlparser/util/validation/ContextKey.java index ffd95f652..774d4fb3b 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/ContextKey.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/ContextKey.java @@ -10,8 +10,8 @@ package net.sf.jsqlparser.util.validation; /** - * the context key - a ValidationCapability should define constants of expected - * context - values needed for validation. + * the context key - a ValidationCapability should define constants of expected context - values + * needed for validation. */ public interface ContextKey { diff --git a/src/main/java/net/sf/jsqlparser/util/validation/ParseCapability.java b/src/main/java/net/sf/jsqlparser/util/validation/ParseCapability.java index b0cf02ff0..a57cf3e5c 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/ParseCapability.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/ParseCapability.java @@ -12,6 +12,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.function.Consumer; + import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.statement.Statements; diff --git a/src/main/java/net/sf/jsqlparser/util/validation/ParseException.java b/src/main/java/net/sf/jsqlparser/util/validation/ParseException.java index 16a226a38..f9cee3ce3 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/ParseException.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/ParseException.java @@ -12,9 +12,8 @@ import net.sf.jsqlparser.JSQLParserException; /** - * wraps a {@link JSQLParserException} to add to the errors collected by - * validation - * + * wraps a {@link JSQLParserException} to add to the errors collected by validation + * * @author gitmotte */ public class ParseException extends ValidationException { diff --git a/src/main/java/net/sf/jsqlparser/util/validation/UnexpectedValidationException.java b/src/main/java/net/sf/jsqlparser/util/validation/UnexpectedValidationException.java index 0cec642ff..5f1f28be6 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/UnexpectedValidationException.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/UnexpectedValidationException.java @@ -11,7 +11,7 @@ /** * can be used on unexpected errors during validation - * + * * @author gitmotte */ public class UnexpectedValidationException extends ValidationException { diff --git a/src/main/java/net/sf/jsqlparser/util/validation/Validation.java b/src/main/java/net/sf/jsqlparser/util/validation/Validation.java index 9fdeaf878..3d7c4f7af 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/Validation.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/Validation.java @@ -16,17 +16,18 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; + import net.sf.jsqlparser.parser.feature.FeatureConfiguration; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.Statements; import net.sf.jsqlparser.util.validation.validator.StatementValidator; /** - * Parses the given statement list with {@link ParseCapability} and performs - * validation with configured {@link ValidationCapability}'s. - * + * Parses the given statement list with {@link ParseCapability} and performs validation with + * configured {@link ValidationCapability}'s. + *

* Errors are are reported by calling {@link #validate()}. - * + * * @author gitmotte * @see #getErrors() * @see #validate() @@ -40,7 +41,8 @@ public class Validation { private List errors; private Statements parsedStatements; - public Validation(Collection capabilities, String... statements) { + public Validation(Collection capabilities, + String... statements) { this(new FeatureConfiguration(), capabilities, statements); } @@ -51,58 +53,13 @@ public Validation(FeatureConfiguration featureConfiguration, this.statementsList = Arrays.asList(statements); } - /** - * @return the errors - may be an empty list. - */ - public List validate() { - this.errors = new ArrayList<>(); - - ValidationContext context = createValidationContext(featureConfiguration, capabilities); - for (String statements : statementsList) { - - ParseCapability parse = new ParseCapability(statements); - parse.validate(context, e -> errors.add(new ValidationError(statements).withCapability(parse).addError(e))); - - parsedStatements = parse.getParsedStatements(); - if (parsedStatements != null && parsedStatements.getStatements() != null && !capabilities.isEmpty() ) { - for (Statement parsedStatement : parsedStatements.getStatements()) { - Map> errorMap = validate(parsedStatement, context); - errors.addAll(toValidationErrors(statements, parsedStatement, errorMap)); - } - } - - } - return errors; - } - - public FeatureConfiguration getFeatureConfiguration() { - return featureConfiguration; - } - - public Collection getCapabilities() { - return capabilities; - } - - public List getStatements() { - return statementsList; - } - - public List getErrors() { - return errors; - } - - public Statements getParsedStatements() { - return parsedStatements; - } - - // STATIC util-methods - /** * @param capabilities * @param statements * @return a list of {@link ValidationError}'s */ - public static List validate(Collection capabilities, + public static List validate( + Collection capabilities, String... statements) { return new Validation(capabilities, statements).validate(); } @@ -127,7 +84,8 @@ public static ValidationContext createValidationContext(FeatureConfiguration con * @return a list of {@link ValidationError}' */ public static List toValidationErrors(String statements, - Statement parsedStatement, Map> errorMap) { + Statement parsedStatement, + Map> errorMap) { List errors = new ArrayList<>(); for (Entry> e : errorMap.entrySet()) { errors.add(new ValidationError(statements).withParsedStatement(parsedStatement) @@ -150,4 +108,53 @@ public static Map> validate(State return validator.getValidationErrors(); } + /** + * @return the errors - may be an empty list. + */ + public List validate() { + this.errors = new ArrayList<>(); + + ValidationContext context = createValidationContext(featureConfiguration, capabilities); + for (String statements : statementsList) { + + ParseCapability parse = new ParseCapability(statements); + parse.validate(context, e -> errors + .add(new ValidationError(statements).withCapability(parse).addError(e))); + + parsedStatements = parse.getParsedStatements(); + if (parsedStatements != null && parsedStatements.getStatements() != null + && !capabilities.isEmpty()) { + for (Statement parsedStatement : parsedStatements.getStatements()) { + Map> errorMap = + validate(parsedStatement, context); + errors.addAll(toValidationErrors(statements, parsedStatement, errorMap)); + } + } + + } + return errors; + } + + public FeatureConfiguration getFeatureConfiguration() { + return featureConfiguration; + } + + // STATIC util-methods + + public Collection getCapabilities() { + return capabilities; + } + + public List getStatements() { + return statementsList; + } + + public List getErrors() { + return errors; + } + + public Statements getParsedStatements() { + return parsedStatements; + } + } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/ValidationContext.java b/src/main/java/net/sf/jsqlparser/util/validation/ValidationContext.java index 3f71822d0..994be3b4a 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/ValidationContext.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/ValidationContext.java @@ -46,15 +46,15 @@ public ValidationContext reinit(boolean reInit) { return this; } + public FeatureConfiguration getConfiguration() { + return configuration; + } + public ValidationContext setConfiguration(FeatureConfiguration configuration) { this.configuration = configuration; return this; } - public FeatureConfiguration getConfiguration() { - return configuration; - } - public boolean getAsBoolean(Feature f) { return getConfiguration().getAsBoolean(f); } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/ValidationError.java b/src/main/java/net/sf/jsqlparser/util/validation/ValidationError.java index 45bf5810c..f0ef8c5e1 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/ValidationError.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/ValidationError.java @@ -12,6 +12,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; + import net.sf.jsqlparser.statement.Statement; public class ValidationError { @@ -50,6 +51,10 @@ public ValidationCapability getCapability() { return capability; } + public void setCapability(ValidationCapability databaseType) { + this.capability = databaseType; + } + /** * @return the parsed {@link Statement}, if parsing was possible */ @@ -57,6 +62,10 @@ public Statement getParsedStatement() { return parsedStatement; } + public void setParsedStatement(Statement parsedStatement) { + this.parsedStatement = parsedStatement; + } + /** * @return the statements (may be more than one) given for validation */ @@ -64,14 +73,6 @@ public String getStatements() { return statements; } - public void setCapability(ValidationCapability databaseType) { - this.capability = databaseType; - } - - public void setParsedStatement(Statement parsedStatement) { - this.parsedStatement = parsedStatement; - } - public ValidationError withCapability(ValidationCapability databaseType) { setCapability(databaseType); return this; @@ -85,7 +86,8 @@ public ValidationError withParsedStatement(Statement parsedStatement) { @Override public String toString() { return "ValidationError [\nstatement=" + statements + "\ncapability=" - + (capability != null ? capability.getName() : "") + "\nerrors=" + errors + "\n]"; + + (capability != null ? capability.getName() : "") + "\nerrors=" + errors + + "\n]"; } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/ValidationException.java b/src/main/java/net/sf/jsqlparser/util/validation/ValidationException.java index a154eaa52..99295f469 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/ValidationException.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/ValidationException.java @@ -39,7 +39,8 @@ public boolean equals(Object o) { if (o.getClass().equals(this.getClass())) { // exact type match! ValidationException ve = (ValidationException) o; - return Objects.equals(getMessage(), ve.getMessage()) && Objects.equals(getCause(), ve.getCause()); + return Objects.equals(getMessage(), ve.getMessage()) + && Objects.equals(getCause(), ve.getCause()); } else { return false; } @@ -47,11 +48,12 @@ public boolean equals(Object o) { @Override public int hashCode() { - return getMessage().hashCode() + (getCause() == null ? 0 : getCause().toString().hashCode()); + return getMessage().hashCode() + + (getCause() == null ? 0 : getCause().toString().hashCode()); } @Override - public String toString () { + public String toString() { return getClass().getSimpleName() + ": " + getMessage(); } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/ValidationUtil.java b/src/main/java/net/sf/jsqlparser/util/validation/ValidationUtil.java index 378a6707d..cb83662d5 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/ValidationUtil.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/ValidationUtil.java @@ -13,6 +13,7 @@ import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; + import net.sf.jsqlparser.expression.Alias; public class ValidationUtil { diff --git a/src/main/java/net/sf/jsqlparser/util/validation/Validator.java b/src/main/java/net/sf/jsqlparser/util/validation/Validator.java index 80ac8d326..c1cc3d276 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/Validator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/Validator.java @@ -1,102 +1,103 @@ -/*- - * #%L - * JSQLParser library - * %% - * Copyright (C) 2004 - 2020 JSQLParser - * %% - * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 - * #L% - */ -package net.sf.jsqlparser.util.validation; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -import java.util.Set; - -/** - * @author gitmotte - * @param - */ -public interface Validator { - - /** - * @return true, all {@link ValidationCapability}'s have no errors - */ - default boolean isValid() { - return getValidationErrors().isEmpty(); - } - - /** - * @param capabilities - * @return true, if the given {@link ValidationCapability}'s have no errors. - * false otherwise. - */ - default boolean isValid(ValidationCapability... capabilities) { - return getValidationErrors(capabilities).isEmpty(); - } - - /** - * @return the {@link ValidationCapability}'s requested mapped to a set of error-messages - */ - Map> getValidationErrors(); - - /** - * @param capabilities - * @return the filtered view of requested {@link ValidationCapability}'s mapped to a set - * of error-messages - */ - default Map> getValidationErrors( - ValidationCapability... capabilities) { - return getValidationErrors(Arrays.asList(capabilities)); - } - - /** - * @param capabilities - * @return the filtered view of requested {@link ValidationCapability}'s mapped - * to a set of error-messages - */ - default Map> getValidationErrors( - Collection capabilities) { - Map> map = new HashMap<>(); - for (Entry> e : getValidationErrors().entrySet()) { - if (capabilities.contains(e.getKey())) { - map.put(e.getKey(), e.getValue()); - } - } - return map; - } - - // /** - // * Set the {@link ValidationCapability}'s this {@link Validator} should - // check. - // * - // * @param capabilities - // */ - // public void setCapabilities(Collection - // capabilities); - // - // /** - // * @param configuration - // */ - // public void setConfiguration(FeatureConfiguration configuration); - - /** - * @param ctx - */ - void setContext(ValidationContext ctx); - - /** - * validates given statement. - * - * @param statement - * @see #getValidationErrors() - * @see #getValidationErrors(Collection) - * @see #getValidationErrors(ValidationCapability...) - */ - void validate(S statement); - -} +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2020 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.util.validation; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import java.util.Set; + +/** + * @param + * @author gitmotte + */ +public interface Validator { + + /** + * @return true, all {@link ValidationCapability}'s have no errors + */ + default boolean isValid() { + return getValidationErrors().isEmpty(); + } + + /** + * @param capabilities + * @return true, if the given {@link ValidationCapability}'s have no errors. + * false otherwise. + */ + default boolean isValid(ValidationCapability... capabilities) { + return getValidationErrors(capabilities).isEmpty(); + } + + /** + * @return the {@link ValidationCapability}'s requested mapped to a set of error-messages + */ + Map> getValidationErrors(); + + /** + * @param capabilities + * @return the filtered view of requested {@link ValidationCapability}'s mapped to a set of + * error-messages + */ + default Map> getValidationErrors( + ValidationCapability... capabilities) { + return getValidationErrors(Arrays.asList(capabilities)); + } + + /** + * @param capabilities + * @return the filtered view of requested {@link ValidationCapability}'s mapped to a set of + * error-messages + */ + default Map> getValidationErrors( + Collection capabilities) { + Map> map = new HashMap<>(); + for (Entry> e : getValidationErrors() + .entrySet()) { + if (capabilities.contains(e.getKey())) { + map.put(e.getKey(), e.getValue()); + } + } + return map; + } + + // /** + // * Set the {@link ValidationCapability}'s this {@link Validator} should + // check. + // * + // * @param capabilities + // */ + // public void setCapabilities(Collection + // capabilities); + // + // /** + // * @param configuration + // */ + // public void setConfiguration(FeatureConfiguration configuration); + + /** + * @param ctx + */ + void setContext(ValidationContext ctx); + + /** + * validates given statement. + * + * @param statement + * @see #getValidationErrors() + * @see #getValidationErrors(Collection) + * @see #getValidationErrors(ValidationCapability...) + */ + void validate(S statement); + +} diff --git a/src/main/java/net/sf/jsqlparser/util/validation/allowedtypes/AllowedTypesValidation.java b/src/main/java/net/sf/jsqlparser/util/validation/allowedtypes/AllowedTypesValidation.java index b5e27b91f..14b0a403a 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/allowedtypes/AllowedTypesValidation.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/allowedtypes/AllowedTypesValidation.java @@ -25,7 +25,8 @@ public void validate(ValidationContext context, Consumer er Object arg = context.getOptional(AllowedTypesContext.argument, Object.class); Boolean allowNull = context.getOptional(AllowedTypesContext.allow_null, Boolean.class); @SuppressWarnings("unchecked") - Collection> allowedTypes = context.get(AllowedTypesContext.allowed_types, Collection.class); + Collection> allowedTypes = + context.get(AllowedTypesContext.allowed_types, Collection.class); if (arg != null) { boolean error = true; for (Class cls : allowedTypes) { @@ -35,7 +36,8 @@ public void validate(ValidationContext context, Consumer er } } if (error) { - errorConsumer.accept(toError(arg.getClass() + " is not a valid argument - expected one of " + allowedTypes)); + errorConsumer.accept(toError(arg.getClass() + + " is not a valid argument - expected one of " + allowedTypes)); } } else if (Boolean.FALSE.equals(allowNull)) { errorConsumer.accept(toError("argument is missing one of " + allowedTypes)); diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/DatabaseType.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/DatabaseType.java index b402fb322..2359f93d0 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/feature/DatabaseType.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/DatabaseType.java @@ -11,28 +11,27 @@ import java.util.EnumSet; import java.util.Set; + import net.sf.jsqlparser.parser.feature.Feature; /** *

- * The DatabaseType is named like the identifier used within the - * jdbc-connection-url (upper case), this may change in future, therefore use - * {@link #get(String)} to retrieve the {@link DatabaseType}. + * The DatabaseType is named like the identifier used within the jdbc-connection-url (upper case), + * this may change in future, therefore use {@link #get(String)} to retrieve the + * {@link DatabaseType}. *

*/ public enum DatabaseType implements FeatureSetValidation, Version { ANSI_SQL("ANSI SQL", SQLVersion.values()), // DBMS - ORACLE(OracleVersion.values()), - MYSQL(MySqlVersion.values()), - SQLSERVER(SqlServerVersion.values()), - MARIADB(MariaDbVersion.values()), - POSTGRESQL(PostgresqlVersion.values()), - H2(H2Version.values()); + ORACLE(OracleVersion.values()), MYSQL(MySqlVersion.values()), SQLSERVER( + SqlServerVersion.values()), MARIADB(MariaDbVersion.values()), POSTGRESQL( + PostgresqlVersion.values()), H2(H2Version.values()); - public static final DatabaseType[] DATABASES = new DatabaseType[] { ORACLE, MYSQL, SQLSERVER, MARIADB, POSTGRESQL, - H2 }; + public static final DatabaseType[] DATABASES = + new DatabaseType[] {ORACLE, MYSQL, SQLSERVER, MARIADB, POSTGRESQL, + H2}; private String name; private Version[] versions; @@ -55,7 +54,8 @@ public enum DatabaseType implements FeatureSetValidation, Version { /** * @param jdbcIdentifier - the database-identifier-part of jdbc-url * @return the {@link DatabaseType} - * @throws IllegalArgumentException - if the specified jdbcIdentifier cannot be mapped to a {@link DatabaseType} + * @throws IllegalArgumentException - if the specified jdbcIdentifier cannot be mapped to a + * {@link DatabaseType} * @throws NullPointerException if {@code jdbcIdentifier} is null */ public static DatabaseType get(String jdbcIdentifier) { @@ -63,7 +63,7 @@ public static DatabaseType get(String jdbcIdentifier) { } /** - * + * */ @Override public String getName() { diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/FeatureSetValidation.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/FeatureSetValidation.java index 2b29f366f..e4e52a085 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/feature/FeatureSetValidation.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/FeatureSetValidation.java @@ -11,6 +11,7 @@ import java.util.Set; import java.util.function.Consumer; + import net.sf.jsqlparser.parser.feature.Feature; import net.sf.jsqlparser.parser.feature.FeatureSet; import net.sf.jsqlparser.util.validation.ValidationCapability; diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/FeaturesAllowed.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/FeaturesAllowed.java index 3ada0ec28..431e4d762 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/feature/FeaturesAllowed.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/FeaturesAllowed.java @@ -18,6 +18,7 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; + import net.sf.jsqlparser.parser.feature.Feature; import net.sf.jsqlparser.parser.feature.FeatureSet; import net.sf.jsqlparser.parser.feature.ModifyableFeatureSet; @@ -30,18 +31,13 @@ */ public class FeaturesAllowed implements FeatureSetValidation, ModifyableFeatureSet { - private static final String SEPERATOR_REGEX = " \\+ "; - private static final String SEPERATOR = " + "; - public static final FeaturesAllowed JDBC = new FeaturesAllowed("jdbc", // always allowed if used with jdbc Feature.jdbcParameter, Feature.jdbcNamedParameter).unmodifyable(); - public static final FeaturesAllowed EXPRESSIONS = new FeaturesAllowed("EXPRESSIONS", Feature.exprLike, Feature.exprSimilarTo); - /** * all {@link Feature}' within SQL SELECT without modification features like * {@link Feature#selectInto}, but jdbc-features like {@link Feature#jdbcParameter} and @@ -90,53 +86,14 @@ public class FeaturesAllowed implements FeatureSetValidation, ModifyableFeatureS Feature.tableStatement, Feature.function).unmodifyable(); - - /** - * all {@link Feature}' for SQL INSERT including {@link #SELECT} and {@link Feature#selectInto} - */ - public static final FeaturesAllowed INSERT = - new FeaturesAllowed("INSERT", Feature.insert, Feature.insertFromSelect, - Feature.insertModifierIgnore, Feature.insertModifierPriority, - Feature.insertReturningAll, - Feature.insertReturningExpressionList, Feature.insertUseSet, - Feature.insertValues, Feature.selectInto).add(SELECT).unmodifyable(); - - /** - * all {@link Feature}' for SQL UPDATE including {@link #SELECT} - */ - public static final FeaturesAllowed UPDATE = new FeaturesAllowed("UPDATE", Feature.update, - Feature.updateJoins, - Feature.updateFrom, Feature.updateLimit, Feature.updateOrderBy, Feature.updateReturning, - Feature.updateUseSelect) - .add(SELECT).unmodifyable(); - - /** - * all {@link Feature}' for SQL UPDATE including {@link #SELECT} - */ - public static final FeaturesAllowed DELETE = - new FeaturesAllowed("DELETE", Feature.delete, Feature.deleteJoin, - Feature.deleteLimit, Feature.deleteOrderBy, Feature.deleteTables, - Feature.deleteReturningExpressionList, - Feature.truncate) - .add(SELECT).unmodifyable(); - /** * all {@link Feature}' for SQL MERGE other similar commands */ public static final FeaturesAllowed MERGE = new FeaturesAllowed("MERGE", Feature.merge, Feature.upsert, Feature.insertUseDuplicateKeyUpdate).unmodifyable(); - - /** - * all DML {@link Feature}'s - */ - public static final FeaturesAllowed DML = - new FeaturesAllowed("DML").add(SELECT, INSERT, UPDATE, DELETE, MERGE) - .unmodifyable(); - public static final FeaturesAllowed EXECUTE = new FeaturesAllowed("EXECUTE", Feature.execute).unmodifyable(); - /** * all "CREATE" {@link Feature}'s */ @@ -148,7 +105,6 @@ public class FeaturesAllowed implements FeatureSetValidation, ModifyableFeatureS Feature.createTableFromSelect, Feature.createTrigger, Feature.createView).unmodifyable(); - /** * all "ALTER" {@link Feature}'s */ @@ -156,7 +112,6 @@ public class FeaturesAllowed implements FeatureSetValidation, ModifyableFeatureS new FeaturesAllowed("ALTER", Feature.alterTable, Feature.alterSequence, Feature.alterView, Feature.alterIndex) .unmodifyable(); - /** * all "DROP" {@link Feature}'s */ @@ -167,13 +122,45 @@ public class FeaturesAllowed implements FeatureSetValidation, ModifyableFeatureS Feature.dropIndexIfExists, Feature.dropViewIfExists, Feature.dropSchemaIfExists, Feature.dropSequenceIfExists) .unmodifyable(); - + private static final String SEPERATOR_REGEX = " \\+ "; + /** + * all {@link Feature}' for SQL INSERT including {@link #SELECT} and {@link Feature#selectInto} + */ + public static final FeaturesAllowed INSERT = + new FeaturesAllowed("INSERT", Feature.insert, Feature.insertFromSelect, + Feature.insertModifierIgnore, Feature.insertModifierPriority, + Feature.insertReturningAll, + Feature.insertReturningExpressionList, Feature.insertUseSet, + Feature.insertValues, Feature.selectInto).add(SELECT).unmodifyable(); + /** + * all {@link Feature}' for SQL UPDATE including {@link #SELECT} + */ + public static final FeaturesAllowed UPDATE = new FeaturesAllowed("UPDATE", Feature.update, + Feature.updateJoins, + Feature.updateFrom, Feature.updateLimit, Feature.updateOrderBy, Feature.updateReturning, + Feature.updateUseSelect) + .add(SELECT).unmodifyable(); + /** + * all {@link Feature}' for SQL UPDATE including {@link #SELECT} + */ + public static final FeaturesAllowed DELETE = + new FeaturesAllowed("DELETE", Feature.delete, Feature.deleteJoin, + Feature.deleteLimit, Feature.deleteOrderBy, Feature.deleteTables, + Feature.deleteReturningExpressionList, + Feature.truncate) + .add(SELECT).unmodifyable(); + /** + * all DML {@link Feature}'s + */ + public static final FeaturesAllowed DML = + new FeaturesAllowed("DML").add(SELECT, INSERT, UPDATE, DELETE, MERGE) + .unmodifyable(); /** * all DDL {@link Feature}'s */ public static final FeaturesAllowed DDL = new FeaturesAllowed("DDL").add(CREATE, ALTER, DROP).unmodifyable(); - + private static final String SEPERATOR = " + "; private Set names = new LinkedHashSet<>(); private Set features = new HashSet<>(); diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/H2Version.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/H2Version.java index 9cd733acf..3984e7fe6 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/feature/H2Version.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/H2Version.java @@ -137,8 +137,7 @@ public enum H2Version implements Version { // http://www.h2database.com/html/commands.html#grant_role Feature.grant, // http://h2database.com/html/commands.html#commit - Feature.commit - )); + Feature.commit)); private Set features; private String versionString; diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/MariaDbVersion.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/MariaDbVersion.java index 983adb4fd..742e84b97 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/feature/MariaDbVersion.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/MariaDbVersion.java @@ -12,6 +12,7 @@ import java.util.Collections; import java.util.EnumSet; import java.util.Set; + import net.sf.jsqlparser.parser.feature.Feature; /** diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/MySqlVersion.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/MySqlVersion.java index a7aeeaae0..cd6c2c038 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/feature/MySqlVersion.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/MySqlVersion.java @@ -12,11 +12,12 @@ import java.util.Collections; import java.util.EnumSet; import java.util.Set; + import net.sf.jsqlparser.parser.feature.Feature; /** * Please add Features supported and place a link to public documentation - * + * * @author gitmotte * @see https://dev.mysql.com/doc/refman/8.0/en/ diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/OracleVersion.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/OracleVersion.java index 26d4e678e..37b193820 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/feature/OracleVersion.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/OracleVersion.java @@ -55,7 +55,8 @@ public enum OracleVersion implements Version { // https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/SELECT.html // see "row_limiting_clause" - Feature.offset, Feature.offsetParam, Feature.fetch, Feature.fetchFirst, Feature.fetchNext, + Feature.offset, Feature.offsetParam, Feature.fetch, Feature.fetchFirst, + Feature.fetchNext, // https://www.oracletutorial.com/oracle-basics/oracle-select-distinct/ Feature.distinct, Feature.selectUnique, @@ -129,7 +130,8 @@ public enum OracleVersion implements Version { // https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/CREATE-MATERIALIZED-VIEW.htm Feature.createViewMaterialized, // https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/CREATE-TABLE.html - Feature.createTable, Feature.createTableCreateOptionStrings, Feature.createTableTableOptionStrings, + Feature.createTable, Feature.createTableCreateOptionStrings, + Feature.createTableTableOptionStrings, Feature.createTableFromSelect, Feature.createTableRowMovement, // https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/CREATE-INDEX.html Feature.createIndex, @@ -143,7 +145,8 @@ public enum OracleVersion implements Version { Feature.commit, // https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/COMMENT.html - Feature.comment, Feature.commentOnTable, Feature.commentOnColumn, Feature.commentOnView, + Feature.comment, Feature.commentOnTable, Feature.commentOnColumn, + Feature.commentOnView, // https://docs.oracle.com/en/database/oracle/oracle-database/19/rcmrf/DESCRIBE.html Feature.describe, @@ -154,7 +157,8 @@ public enum OracleVersion implements Version { // https://www.oracletutorial.com/oracle-basics/oracle-merge/ Feature.merge, - Feature.createFunction, Feature.createProcedure, Feature.functionalStatement, Feature.block, + Feature.createFunction, Feature.createProcedure, Feature.functionalStatement, + Feature.block, Feature.declare, // special oracle features diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/PostgresqlVersion.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/PostgresqlVersion.java index 08bf3bf1a..386274fa1 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/feature/PostgresqlVersion.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/PostgresqlVersion.java @@ -12,6 +12,7 @@ import java.util.Collections; import java.util.EnumSet; import java.util.Set; + import net.sf.jsqlparser.parser.feature.Feature; /** diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/SQLVersion.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/SQLVersion.java index 3b8266c83..225cd0040 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/feature/SQLVersion.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/SQLVersion.java @@ -12,12 +12,12 @@ import java.util.Collections; import java.util.EnumSet; import java.util.Set; + import net.sf.jsqlparser.parser.feature.Feature; /** - * Enum containing the ANSI SQL Standard Versions - features are not guaranteed - * to be complete, just add them if you are sure they are part of the standard - * :) + * Enum containing the ANSI SQL Standard Versions - features are not guaranteed to be complete, just + * add them if you are sure they are part of the standard :) * * @author gitmotte * @see features; private String versionString; @@ -154,7 +155,8 @@ public enum SqlServerVersion implements Version { * @param unsupported * @see #copy() to copy from previous version */ - SqlServerVersion(String versionString, Set featuresSupported, Set unsupported) { + SqlServerVersion(String versionString, Set featuresSupported, + Set unsupported) { this.versionString = versionString; this.features = featuresSupported; this.features.removeAll(unsupported); diff --git a/src/main/java/net/sf/jsqlparser/util/validation/metadata/AbstractDatabaseMetaDataCapability.java b/src/main/java/net/sf/jsqlparser/util/validation/metadata/AbstractDatabaseMetaDataCapability.java index ffb5d1ddc..22f8b6f5f 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/metadata/AbstractDatabaseMetaDataCapability.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/metadata/AbstractDatabaseMetaDataCapability.java @@ -18,11 +18,9 @@ import java.util.function.UnaryOperator; /** - * Adapter class always throwing {@link UnsupportedOperationException} for all - * exists - methods. + * Adapter class always throwing {@link UnsupportedOperationException} for all exists - methods. * * @author gitmotte - * */ public abstract class AbstractDatabaseMetaDataCapability implements DatabaseMetaDataValidation { @@ -33,22 +31,24 @@ public abstract class AbstractDatabaseMetaDataCapability implements DatabaseMeta /** * With caching enabled - see {@link #isCacheResults()} - * + * * @param connection * @param namesLookup - see {@link NamesLookup} * @see #AbstractDatabaseMetaDataCapability(Connection, UnaryOperator, boolean) */ - public AbstractDatabaseMetaDataCapability(Connection connection, UnaryOperator namesLookup) { + public AbstractDatabaseMetaDataCapability(Connection connection, + UnaryOperator namesLookup) { this(connection, namesLookup, true); } /** * @param connection - * @param namesLookup - see {@link NamesLookup} + * @param namesLookup - see {@link NamesLookup} * @param cacheResults - whether the results should be cached for later lookups * @see #AbstractDatabaseMetaDataCapability(Connection, UnaryOperator) */ - public AbstractDatabaseMetaDataCapability(Connection connection, UnaryOperator namesLookup, + public AbstractDatabaseMetaDataCapability(Connection connection, + UnaryOperator namesLookup, boolean cacheResults) { this.connection = connection; this.namesLookup = namesLookup; @@ -81,31 +81,32 @@ public final boolean exists(Named named) { named.setAliasLookup(getNamesLookup().apply(named.getAlias())); switch (named.getNamedObject()) { - case table: - return cache(named, this::tableExists); - case column: - return cache(named, this::columnExists); - case schema: - return cache(named, this::schemaExists); - case index: - return cache(named, this::indexExists); - case database: - return cache(named, this::databaseExists); - case constraint: - case uniqueConstraint: - return cache(named, this::constraintExists); - case view: - return cache(named, this::viewExists); - case procedure: - return cache(named, this::procedureExists); - case user: - return cache(named, this::userExists); - case role: - return cache(named, this::roleExists); - default: + case table: + return cache(named, this::tableExists); + case column: + return cache(named, this::columnExists); + case schema: + return cache(named, this::schemaExists); + case index: + return cache(named, this::indexExists); + case database: + return cache(named, this::databaseExists); + case constraint: + case uniqueConstraint: + return cache(named, this::constraintExists); + case view: + return cache(named, this::viewExists); + case procedure: + return cache(named, this::procedureExists); + case user: + return cache(named, this::userExists); + case role: + return cache(named, this::roleExists); + default: } throw new UnsupportedOperationException( - named.getFqn() + ": evaluation of " + named.getNamedObject() + "-name not implemented."); + named.getFqn() + ": evaluation of " + named.getNamedObject() + + "-name not implemented."); } protected boolean cache(Named named, BiPredicate, Named> fn) { @@ -159,7 +160,8 @@ protected boolean tableExists(Map results, Named name) { protected UnsupportedOperationException unsupported(Named name) { return new UnsupportedOperationException( - name.getFqn() + ": evaluation of " + name.getNamedObject() + "-name not supported."); + name.getFqn() + ": evaluation of " + name.getNamedObject() + + "-name not supported."); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/metadata/DatabaseException.java b/src/main/java/net/sf/jsqlparser/util/validation/metadata/DatabaseException.java index cbe872042..9a7ff15f3 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/metadata/DatabaseException.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/metadata/DatabaseException.java @@ -10,10 +10,12 @@ package net.sf.jsqlparser.util.validation.metadata; import java.sql.SQLException; + import net.sf.jsqlparser.util.validation.ValidationException; /** * database-errors wrapping a {@link SQLException} or PersistenceException + * * @author gitmotte */ public class DatabaseException extends ValidationException { diff --git a/src/main/java/net/sf/jsqlparser/util/validation/metadata/DatabaseMetaDataValidation.java b/src/main/java/net/sf/jsqlparser/util/validation/metadata/DatabaseMetaDataValidation.java index 3d919d62f..b9e8ff8b2 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/metadata/DatabaseMetaDataValidation.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/metadata/DatabaseMetaDataValidation.java @@ -11,6 +11,7 @@ import java.sql.SQLException; import java.util.function.Consumer; + import net.sf.jsqlparser.util.validation.UnexpectedValidationException; import net.sf.jsqlparser.util.validation.ValidationCapability; import net.sf.jsqlparser.util.validation.ValidationContext; @@ -37,7 +38,8 @@ default void validate(ValidationContext context, Consumer e } catch (ValidationException ve) { errorConsumer.accept(ve); } catch (UnsupportedOperationException uoe) { - errorConsumer.accept(new ValidationException("This Operation " + named.toString() + " is not supported yet.", uoe)); + errorConsumer.accept(new ValidationException( + "This Operation " + named.toString() + " is not supported yet.", uoe)); } catch (Exception e) { errorConsumer.accept(getUnexpectedErrorMessage(named, e)); } @@ -45,15 +47,11 @@ default void validate(ValidationContext context, Consumer e /** * @param named - * @return true, if the object exists, false - * otherwise. - * @throws ValidationException - on specific errors like - * {@link DatabaseException} on - * database-errors wrapping a - * {@link SQLException} or - * PersistenceException - * @throws UnsupportedOperationException - if testing of given - * {@link NamedObject} is not supported. + * @return true, if the object exists, false otherwise. + * @throws ValidationException - on specific errors like {@link DatabaseException} on + * database-errors wrapping a {@link SQLException} or PersistenceException + * @throws UnsupportedOperationException - if testing of given {@link NamedObject} is not + * supported. */ boolean exists(Named named); @@ -63,7 +61,8 @@ default void validate(ValidationContext context, Consumer e * @return a new {@link ValidationException} */ default ValidationException getErrorMessage(Named named, boolean checkForExists) { - return toError(String.format("%s does %sexist.", named.getFqn(), checkForExists ? "not " : "")); + return toError( + String.format("%s does %sexist.", named.getFqn(), checkForExists ? "not " : "")); } /** @@ -73,7 +72,9 @@ default ValidationException getErrorMessage(Named named, boolean checkForExists) */ default ValidationException getUnexpectedErrorMessage(Named named, Exception cause) { return new UnexpectedValidationException( - named.getFqn() + ": cannot validate " + named.getNamedObject() + "-name. detail: " + cause.getMessage(), cause); + named.getFqn() + ": cannot validate " + named.getNamedObject() + "-name. detail: " + + cause.getMessage(), + cause); } @Override diff --git a/src/main/java/net/sf/jsqlparser/util/validation/metadata/JdbcDatabaseMetaDataCapability.java b/src/main/java/net/sf/jsqlparser/util/validation/metadata/JdbcDatabaseMetaDataCapability.java index b40d2296c..a3d5102b8 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/metadata/JdbcDatabaseMetaDataCapability.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/metadata/JdbcDatabaseMetaDataCapability.java @@ -24,34 +24,36 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; + import net.sf.jsqlparser.util.validation.UnexpectedValidationException; import net.sf.jsqlparser.util.validation.ValidationException; /** - * Validates against schema by jdbc-metadata in a very basic way with simple - * caching and comparing names by {@link String#equalsIgnoreCase(String)} + * Validates against schema by jdbc-metadata in a very basic way with simple caching and comparing + * names by {@link String#equalsIgnoreCase(String)} * * @author gitmotte - * */ public class JdbcDatabaseMetaDataCapability extends AbstractDatabaseMetaDataCapability { private static final String VIEW = "VIEW"; private static final String TABLE = "TABLE"; private static final String COLUMN = "COLUMN"; - private static final Logger LOG = Logger.getLogger(JdbcDatabaseMetaDataCapability.class.getName()); + private static final Logger LOG = + Logger.getLogger(JdbcDatabaseMetaDataCapability.class.getName()); /** * @param connection * @param namesLookup - see {@link NamesLookup} */ - public JdbcDatabaseMetaDataCapability(Connection connection, UnaryOperator namesLookup) { + public JdbcDatabaseMetaDataCapability(Connection connection, + UnaryOperator namesLookup) { super(connection, namesLookup); } /** * @param connection - * @param namesLookup - see {@link NamesLookup} + * @param namesLookup - see {@link NamesLookup} * @param cacheResults - whether the results should be cached for later lookups */ public JdbcDatabaseMetaDataCapability(Connection connection, UnaryOperator namesLookup, @@ -61,7 +63,8 @@ public JdbcDatabaseMetaDataCapability(Connection connection, UnaryOperator results, Named named) throws ValidationException { + protected boolean columnExists(Map results, Named named) + throws ValidationException { String[] names = splitAndValidateMinMax(COLUMN, named.getFqnLookup(), 1, 4); String columnName = names[names.length - 1]; @@ -70,7 +73,8 @@ protected boolean columnExists(Map results, Named named) throws : named.getParents(); int lastIndexOf = named.getFqnLookup().lastIndexOf("."); - String fqnParent = lastIndexOf != -1 ? named.getFqnLookup().substring(0, lastIndexOf) : null; + String fqnParent = + lastIndexOf != -1 ? named.getFqnLookup().substring(0, lastIndexOf) : null; // try to match parents in results Predicate predicate = null; @@ -101,7 +105,8 @@ protected boolean columnExists(Map results, Named named) throws throw createDatabaseException(fqn, COLUMN, e); } } else if (LOG.isLoggable(Level.FINE)) { - LOG.fine(String.format("%s does not exists, cannot evaluate COLUMN from %s", fqn, named.getFqn())); + LOG.fine(String.format("%s does not exists, cannot evaluate COLUMN from %s", fqn, + named.getFqn())); } } return false; @@ -113,12 +118,14 @@ private boolean existsFromItem(Map results, String fqn) { } @Override - protected boolean viewExists(Map results, Named named) throws ValidationException { + protected boolean viewExists(Map results, Named named) + throws ValidationException { return jdbcMetadataTables(named, VIEW); } @Override - protected boolean tableExists(Map results, Named named) throws ValidationException { + protected boolean tableExists(Map results, Named named) + throws ValidationException { return jdbcMetadataTables(named, TABLE); } @@ -142,8 +149,9 @@ protected boolean jdbcMetadataTables(Named named, String type) throws Validation List tables = new ArrayList<>(); - try (ResultSet rs = connection.getMetaData().getTables(catalog, schemaPattern, tableNamePattern, - new String[] { type })) { + try (ResultSet rs = + connection.getMetaData().getTables(catalog, schemaPattern, tableNamePattern, + new String[] {type})) { while (rs.next()) { String tableCat = rs.getString("TABLE_CAT"); String tableSchem = rs.getString("TABLE_SCHEM"); @@ -156,10 +164,10 @@ protected boolean jdbcMetadataTables(Named named, String type) throws Validation tables.add(String.join(".", tableCat, tableSchem, tableName)); } } else { - tables.add(String.join(".", tableSchem, tableName)); + tables.add(String.join(".", tableSchem, tableName)); } } - } else { + } else { tables.add(tableName); } } @@ -184,7 +192,8 @@ private String[] splitAndValidateMinMax(String type, String fqn, int min, int ma String[] names = fqn.split("\\."); if (names.length < min || names.length > max) { throw new UnexpectedValidationException(String.format( - "%s path-elements count needs to be between %s and %s for %s", fqn, min, max, type)); + "%s path-elements count needs to be between %s and %s for %s", fqn, min, max, + type)); } return names; } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/metadata/MetadataContext.java b/src/main/java/net/sf/jsqlparser/util/validation/metadata/MetadataContext.java index 10c0d8047..38ea0b37d 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/metadata/MetadataContext.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/metadata/MetadataContext.java @@ -17,8 +17,7 @@ public enum MetadataContext implements ContextKey { */ named, /** - * true, check for existence, - * false, check for non-existence + * true, check for existence, false, check for non-existence */ exists } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/metadata/Named.java b/src/main/java/net/sf/jsqlparser/util/validation/metadata/Named.java index bd7597d53..2957df99d 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/metadata/Named.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/metadata/Named.java @@ -1,128 +1,127 @@ -/*- - * #%L - * JSQLParser library - * %% - * Copyright (C) 2004 - 2020 JSQLParser - * %% - * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 - * #L% - */ -package net.sf.jsqlparser.util.validation.metadata; - -import java.util.List; -import java.util.Objects; - -public class Named { - - private final NamedObject namedObject; - private final String fqn; - private String alias; - private List parents; - - private String fqnLookup; - private String aliasLookup; - - public Named(NamedObject namedObject, String fqn) { - Objects.requireNonNull(namedObject, "named object must not be null"); - Objects.requireNonNull(fqn, "fully qualified name must not be null"); - this.namedObject = namedObject; - this.fqn = fqn; - } - - public String getFqn() { - return fqn; - } - - public String getAlias() { - return alias; - } - - public Named setAlias(String alias) { - this.alias = alias; - return this; - } - - public NamedObject getNamedObject() { - return namedObject; - } - - public List getParents() { - return parents; - } - - public Named setParents(List parents) { - this.parents = parents; - return this; - } - - public Named setFqnLookup(String fqnLookup) { - this.fqnLookup = fqnLookup; - return this; - } - - public Named setAliasLookup(String aliasLookup) { - this.aliasLookup = aliasLookup; - return this; - } - - /** - * @return the fqn transformed for catalog-lookup (uppercase/lowercase/.. - * depends on database) - */ - public String getFqnLookup() { - return fqnLookup; - } - - /** - * @return the alias transformed for catalog-lookup (uppercase/lowercase/.. - * depends on database) - */ - public String getAliasLookup() { - return aliasLookup; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((alias == null) ? 0 : alias.hashCode()); - result = prime * result + fqn.hashCode(); - result = prime * result + namedObject.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Named other = (Named) obj; - if (alias == null) { - if (other.alias != null) { - return false; - } - } else if (!alias.equals(other.alias)) { - return false; - } - if (!fqn.equals(other.fqn)) { - return false; - } - if (namedObject != other.namedObject) { - return false; - } - return true; - } - - @Override - public String toString() { - return "Named [namedObject=" + namedObject + ", fqn=" + fqn + ", alias=" + alias + ", parents=" + parents + "]"; - } - - -} +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2020 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.util.validation.metadata; + +import java.util.List; +import java.util.Objects; + +public class Named { + + private final NamedObject namedObject; + private final String fqn; + private String alias; + private List parents; + + private String fqnLookup; + private String aliasLookup; + + public Named(NamedObject namedObject, String fqn) { + Objects.requireNonNull(namedObject, "named object must not be null"); + Objects.requireNonNull(fqn, "fully qualified name must not be null"); + this.namedObject = namedObject; + this.fqn = fqn; + } + + public String getFqn() { + return fqn; + } + + public String getAlias() { + return alias; + } + + public Named setAlias(String alias) { + this.alias = alias; + return this; + } + + public NamedObject getNamedObject() { + return namedObject; + } + + public List getParents() { + return parents; + } + + public Named setParents(List parents) { + this.parents = parents; + return this; + } + + /** + * @return the fqn transformed for catalog-lookup (uppercase/lowercase/.. depends on database) + */ + public String getFqnLookup() { + return fqnLookup; + } + + public Named setFqnLookup(String fqnLookup) { + this.fqnLookup = fqnLookup; + return this; + } + + /** + * @return the alias transformed for catalog-lookup (uppercase/lowercase/.. depends on database) + */ + public String getAliasLookup() { + return aliasLookup; + } + + public Named setAliasLookup(String aliasLookup) { + this.aliasLookup = aliasLookup; + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((alias == null) ? 0 : alias.hashCode()); + result = prime * result + fqn.hashCode(); + result = prime * result + namedObject.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Named other = (Named) obj; + if (alias == null) { + if (other.alias != null) { + return false; + } + } else if (!alias.equals(other.alias)) { + return false; + } + if (!fqn.equals(other.fqn)) { + return false; + } + if (namedObject != other.namedObject) { + return false; + } + return true; + } + + @Override + public String toString() { + return "Named [namedObject=" + namedObject + ", fqn=" + fqn + ", alias=" + alias + + ", parents=" + parents + "]"; + } + + +} diff --git a/src/main/java/net/sf/jsqlparser/util/validation/metadata/NamedObject.java b/src/main/java/net/sf/jsqlparser/util/validation/metadata/NamedObject.java index ee97a4573..742f183ff 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/metadata/NamedObject.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/metadata/NamedObject.java @@ -27,32 +27,18 @@ public enum NamedObject { */ view, /** - * a name constisting of min 2 (the table-reference) and max. 4 identifiers, - * i.e. [catalog].[schema].[table].[columnName] + * a name constisting of min 2 (the table-reference) and max. 4 identifiers, i.e. + * [catalog].[schema].[table].[columnName] */ - column, - index, - constraint, - uniqueConstraint, + column, index, constraint, uniqueConstraint, /** * a name constisting of max. 3 identifiers, i.e. [catalog].[schema].[sequence] */ - sequence, - synonym, - procedure, - user, - role, - trigger, - alias; - - public boolean equalsIgnoreCase(String name) { - return name().equalsIgnoreCase(name); - } + sequence, synonym, procedure, user, role, trigger, alias; /** * @param name - * @return null, if not found, otherwise the - * {@link NamedObject} + * @return null, if not found, otherwise the {@link NamedObject} */ public static NamedObject forName(String name) { for (NamedObject o : values()) { @@ -62,4 +48,8 @@ public static NamedObject forName(String name) { } return null; } + + public boolean equalsIgnoreCase(String name) { + return name().equalsIgnoreCase(name); + } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/metadata/NamesLookup.java b/src/main/java/net/sf/jsqlparser/util/validation/metadata/NamesLookup.java index 6ff98158e..46c2aae03 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/metadata/NamesLookup.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/metadata/NamesLookup.java @@ -13,11 +13,11 @@ import java.util.function.UnaryOperator; /** - * A strategy for transformation of database-names before lookup in - * database-catalog-metadata + * A strategy for transformation of database-names before lookup in database-catalog-metadata */ public enum NamesLookup implements UnaryOperator { - UPPERCASE(String::toUpperCase), LOWERCASE(String::toLowerCase), NO_TRANSFORMATION(UnaryOperator.identity()); + UPPERCASE(String::toUpperCase), LOWERCASE(String::toLowerCase), NO_TRANSFORMATION( + UnaryOperator.identity()); private Function strategy; @@ -29,4 +29,4 @@ public enum NamesLookup implements UnaryOperator { public String apply(String name) { return name == null ? null : strategy.apply(name); } -} \ No newline at end of file +} diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/AbstractValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/AbstractValidator.java index 5eefdd1e4..9e810ca82 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/AbstractValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/AbstractValidator.java @@ -45,12 +45,10 @@ */ public abstract class AbstractValidator implements Validator { - private ValidationContext context = new ValidationContext(); - - private Map> errors = new HashMap<>(); - - private Map>, AbstractValidator> validatorForwards = + private final Map> errors = new HashMap<>(); + private final Map>, AbstractValidator> validatorForwards = new HashMap<>(); + private ValidationContext context = new ValidationContext(); public > T getValidator(Class type) { return type.cast(validatorForwards.computeIfAbsent(type, this::newObject)); @@ -132,16 +130,16 @@ protected > void validateOptionalList(List elementL } protected void validateOptionalExpression(Expression expression) { - validateOptional(expression, e -> e.accept(getValidator(ExpressionValidator.class))); + validateOptional(expression, e -> e.accept(getValidator(ExpressionValidator.class), null)); } protected void validateOptionalExpression(Expression expression, ExpressionValidator v) { - validateOptional(expression, e -> e.accept(v)); + validateOptional(expression, e -> e.accept(v, null)); } protected void validateOptionalExpressions(List expressions) { validateOptionalList(expressions, () -> getValidator(ExpressionValidator.class), - (o, v) -> o.accept(v)); + (o, v) -> o.accept(v, null)); } protected void validateOptionalFromItems(FromItem... fromItems) { @@ -155,15 +153,15 @@ protected void validateOptionalFromItems(List fromItems) { protected void validateOptionalOrderByElements(List orderByElements) { validateOptionalList(orderByElements, () -> getValidator(OrderByValidator.class), - (o, v) -> o.accept(v)); + (o, v) -> o.accept(v, null)); } protected void validateOptionalFromItem(FromItem fromItem) { - validateOptional(fromItem, i -> i.accept(getValidator(SelectValidator.class))); + validateOptional(fromItem, i -> i.accept(getValidator(SelectValidator.class), null)); } protected void validateOptionalFromItem(FromItem fromItem, SelectValidator v) { - validateOptional(fromItem, i -> i.accept(v)); + validateOptional(fromItem, i -> i.accept(v, null)); } /** diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/AlterSessionValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/AlterSessionValidator.java index 35b7f7477..1f45828ae 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/AlterSessionValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/AlterSessionValidator.java @@ -17,6 +17,6 @@ public class AlterSessionValidator extends AbstractValidator { @Override public void validate(AlterSession statement) { - //@todo: implement this method + // @todo: implement this method } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/AlterValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/AlterValidator.java index abdfdb69c..e8dc84b72 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/AlterValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/AlterValidator.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.util.validation.validator; import java.util.EnumSet; + import net.sf.jsqlparser.parser.feature.Feature; import net.sf.jsqlparser.statement.alter.Alter; import net.sf.jsqlparser.statement.alter.AlterExpression; @@ -41,13 +42,16 @@ public void validate(Alter alter, AlterExpression e) { validateOptionalColumnName(c, e.getColumnName()); if (e.getColumnDropNotNullList() != null) { - validateOptionalColumnNames(c, ValidationUtil.map(e.getColumnDropNotNullList(), ColumnDropNotNull::getColumnName)); + validateOptionalColumnNames(c, ValidationUtil.map(e.getColumnDropNotNullList(), + ColumnDropNotNull::getColumnName)); } if (e.getColDataTypeList() != null) { - boolean validateForExist = !EnumSet.of(AlterOperation.ADD).contains(e.getOperation()); + boolean validateForExist = + !EnumSet.of(AlterOperation.ADD).contains(e.getOperation()); validateOptionalColumnNames(c, - ValidationUtil.map(e.getColDataTypeList(), ColumnDataType::getColumnName), validateForExist, + ValidationUtil.map(e.getColDataTypeList(), ColumnDataType::getColumnName), + validateForExist, NamedObject.table); } @@ -70,12 +74,12 @@ public void validate(Alter alter, AlterExpression e) { if (e.getIndex() != null) { validateName(c, NamedObject.index, e.getIndex().getName()); if (e.getIndex().getColumns() != null) { - validateOptionalColumnNames(c, e.getIndex().getColumnsNames(), NamedObject.index); + validateOptionalColumnNames(c, e.getIndex().getColumnsNames(), + NamedObject.index); } } } } - } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/AlterViewValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/AlterViewValidator.java index fe1868485..db390af83 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/AlterViewValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/AlterViewValidator.java @@ -27,7 +27,7 @@ public void validate(AlterView alterView) { validateName(c, NamedObject.view, alterView.getView().getFullyQualifiedName()); validateOptionalColumnNames(c, alterView.getColumnNames()); } - alterView.getSelect().accept(getValidator(SelectValidator.class)); + alterView.getSelect().accept(getValidator(SelectValidator.class), null); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/AnalyzeValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/AnalyzeValidator.java index 82864b7ff..ac5de0c19 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/AnalyzeValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/AnalyzeValidator.java @@ -14,7 +14,7 @@ import net.sf.jsqlparser.util.validation.ValidationCapability; import net.sf.jsqlparser.util.validation.metadata.NamedObject; -public class AnalyzeValidator extends AbstractValidator{ +public class AnalyzeValidator extends AbstractValidator { @Override public void validate(Analyze analyze) { for (ValidationCapability c : getCapabilities()) { diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSequenceValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSequenceValidator.java index 213549937..404c58ce2 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSequenceValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSequenceValidator.java @@ -1,30 +1,26 @@ -/* - * #%L - * JSQLParser library - * %% - * Copyright (C) 2004 - 2020 JSQLParser - * %% - * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 - * #L% - */ -package net.sf.jsqlparser.util.validation.validator; - -import net.sf.jsqlparser.parser.feature.Feature; -import net.sf.jsqlparser.statement.create.sequence.CreateSequence; -import net.sf.jsqlparser.util.validation.ValidationCapability; -import net.sf.jsqlparser.util.validation.metadata.NamedObject; - -/** - * @author gitmotte - */ -public class CreateSequenceValidator extends AbstractValidator { - - - @Override - public void validate(CreateSequence statement) { - for (ValidationCapability c : getCapabilities()) { - validateFeature(Feature.createSequence); - validateName(c, NamedObject.sequence, statement.getSequence().getFullyQualifiedName(), false); - } - } -} +/* + * #%L JSQLParser library %% Copyright (C) 2004 - 2020 JSQLParser %% Dual licensed under GNU LGPL + * 2.1 or Apache License 2.0 #L% + */ +package net.sf.jsqlparser.util.validation.validator; + +import net.sf.jsqlparser.parser.feature.Feature; +import net.sf.jsqlparser.statement.create.sequence.CreateSequence; +import net.sf.jsqlparser.util.validation.ValidationCapability; +import net.sf.jsqlparser.util.validation.metadata.NamedObject; + +/** + * @author gitmotte + */ +public class CreateSequenceValidator extends AbstractValidator { + + + @Override + public void validate(CreateSequence statement) { + for (ValidationCapability c : getCapabilities()) { + validateFeature(Feature.createSequence); + validateName(c, NamedObject.sequence, statement.getSequence().getFullyQualifiedName(), + false); + } + } +} diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSynonymValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSynonymValidator.java index f60226464..7ef2476ed 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSynonymValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSynonymValidator.java @@ -1,11 +1,6 @@ /* - * #%L - * JSQLParser library - * %% - * Copyright (C) 2004 - 2020 JSQLParser - * %% - * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 - * #L% + * #%L JSQLParser library %% Copyright (C) 2004 - 2020 JSQLParser %% Dual licensed under GNU LGPL + * 2.1 or Apache License 2.0 #L% */ package net.sf.jsqlparser.util.validation.validator; @@ -23,7 +18,8 @@ public class CreateSynonymValidator extends AbstractValidator { public void validate(CreateSynonym statement) { for (ValidationCapability c : getCapabilities()) { validateFeature(Feature.createSynonym); - validateName(c, NamedObject.synonym, statement.getSynonym().getFullyQualifiedName(), false); + validateName(c, NamedObject.synonym, statement.getSynonym().getFullyQualifiedName(), + false); } } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateTableValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateTableValidator.java index 57d85bd7d..e4b7a3c83 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateTableValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateTableValidator.java @@ -26,17 +26,21 @@ public void validate(CreateTable createTable) { for (ValidationCapability c : getCapabilities()) { validateFeature(c, Feature.createTable); validateFeature(c, createTable.isUnlogged(), Feature.createTableUnlogged); - validateOptionalFeature(c, createTable.getCreateOptionsStrings(), Feature.createTableCreateOptionStrings); - validateOptionalFeature(c, createTable.getTableOptionsStrings(), Feature.createTableTableOptionStrings); + validateOptionalFeature(c, createTable.getCreateOptionsStrings(), + Feature.createTableCreateOptionStrings); + validateOptionalFeature(c, createTable.getTableOptionsStrings(), + Feature.createTableTableOptionStrings); validateFeature(c, createTable.isIfNotExists(), Feature.createTableIfNotExists); - validateOptionalFeature(c, createTable.getRowMovement(), Feature.createTableRowMovement); + validateOptionalFeature(c, createTable.getRowMovement(), + Feature.createTableRowMovement); validateOptionalFeature(c, createTable.getSelect(), Feature.createTableFromSelect); - if (isNotEmpty(createTable.getIndexes()) ) { + if (isNotEmpty(createTable.getIndexes())) { for (Index i : createTable.getIndexes()) { validateName(c, NamedObject.index, i.getName()); } } - validateName(c, NamedObject.table, createTable.getTable().getFullyQualifiedName(), false); + validateName(c, NamedObject.table, createTable.getTable().getFullyQualifiedName(), + false); } if (createTable.getSelect() != null) { diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateViewValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateViewValidator.java index e2910ada3..262bb4e90 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateViewValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateViewValidator.java @@ -38,7 +38,7 @@ public void validate(CreateView createView) { } SelectValidator v = getValidator(SelectValidator.class); Select select = createView.getSelect(); - select.accept(v); + select.accept(v, null); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/DeleteValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/DeleteValidator.java index 3de5343c4..19588e3b7 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/DeleteValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/DeleteValidator.java @@ -33,10 +33,10 @@ public void validate(Delete delete) { } SelectValidator v = getValidator(SelectValidator.class); - delete.getTable().accept(v); + delete.getTable().accept(v, null); if (isNotEmpty(delete.getTables())) { - delete.getTables().forEach(t -> t.accept(v)); + delete.getTables().forEach(t -> t.accept(v, null)); } validateOptionalExpression(delete.getWhere()); @@ -49,7 +49,7 @@ public void validate(Delete delete) { } if (delete.getReturningClause() != null) { - delete.getReturningClause().forEach(c -> c.accept(v)); + delete.getReturningClause().forEach(c -> c.accept(v, null)); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/DropValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/DropValidator.java index 3a6a0b454..04ea1cf8f 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/DropValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/DropValidator.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.util.validation.validator; import java.util.Arrays; + import net.sf.jsqlparser.parser.feature.Feature; import net.sf.jsqlparser.statement.drop.Drop; import net.sf.jsqlparser.util.validation.ValidationCapability; @@ -36,7 +37,8 @@ public void validate(Drop drop) { Feature.dropTableIfExists); validateFeature(c, drop.isIfExists() && NamedObject.index.equalsIgnoreCase(type), Feature.dropIndexIfExists); - validateFeature(c, drop.isIfExists() && NamedObject.view.equalsIgnoreCase(type), Feature.dropViewIfExists); + validateFeature(c, drop.isIfExists() && NamedObject.view.equalsIgnoreCase(type), + Feature.dropViewIfExists); validateFeature(c, drop.isIfExists() && NamedObject.schema.equalsIgnoreCase(type), Feature.dropSchemaIfExists); validateFeature(c, drop.isIfExists() && NamedObject.sequence.equalsIgnoreCase(type), diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java index a0794b831..ae82e703a 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java @@ -34,6 +34,7 @@ import net.sf.jsqlparser.expression.JsonExpression; import net.sf.jsqlparser.expression.JsonFunction; import net.sf.jsqlparser.expression.KeepExpression; +import net.sf.jsqlparser.expression.LambdaExpression; import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.MySQLGroupConcat; import net.sf.jsqlparser.expression.NextValExpression; @@ -44,12 +45,12 @@ import net.sf.jsqlparser.expression.OracleHint; import net.sf.jsqlparser.expression.OracleNamedFunctionParameter; import net.sf.jsqlparser.expression.OverlapsCondition; -import net.sf.jsqlparser.expression.Parenthesis; import net.sf.jsqlparser.expression.RangeExpression; import net.sf.jsqlparser.expression.RowConstructor; import net.sf.jsqlparser.expression.RowGetExpression; import net.sf.jsqlparser.expression.SignedExpression; import net.sf.jsqlparser.expression.StringValue; +import net.sf.jsqlparser.expression.StructType; import net.sf.jsqlparser.expression.TimeKeyExpression; import net.sf.jsqlparser.expression.TimeValue; import net.sf.jsqlparser.expression.TimestampValue; @@ -83,6 +84,7 @@ import net.sf.jsqlparser.expression.operators.relational.Contains; import net.sf.jsqlparser.expression.operators.relational.DoubleAnd; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; +import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression; import net.sf.jsqlparser.expression.operators.relational.ExistsExpression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.FullTextSearch; @@ -90,6 +92,7 @@ import net.sf.jsqlparser.expression.operators.relational.GreaterThan; import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals; import net.sf.jsqlparser.expression.operators.relational.InExpression; +import net.sf.jsqlparser.expression.operators.relational.IncludesExpression; import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression; import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression; import net.sf.jsqlparser.expression.operators.relational.IsNullExpression; @@ -111,7 +114,9 @@ import net.sf.jsqlparser.statement.select.AllColumns; import net.sf.jsqlparser.statement.select.AllTableColumns; import net.sf.jsqlparser.statement.select.ParenthesedSelect; +import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.util.validation.ValidationCapability; import net.sf.jsqlparser.util.validation.metadata.NamedObject; @@ -120,73 +125,85 @@ */ @SuppressWarnings({"PMD.CyclomaticComplexity"}) public class ExpressionValidator extends AbstractValidator - implements ExpressionVisitor { + implements ExpressionVisitor { @Override - public void visit(Addition addition) { + public Void visit(Addition addition, S context) { visitBinaryExpression(addition, " + "); + return null; } @Override - public void visit(AndExpression andExpression) { + public Void visit(AndExpression andExpression, S context) { visitBinaryExpression(andExpression, andExpression.isUseOperator() ? " && " : " AND "); + return null; } @Override - public void visit(Between between) { - between.getLeftExpression().accept(this); - between.getBetweenExpressionStart().accept(this); - between.getBetweenExpressionEnd().accept(this); + public Void visit(Between between, S context) { + between.getLeftExpression().accept(this, context); + between.getBetweenExpressionStart().accept(this, context); + between.getBetweenExpressionEnd().accept(this, context); + return null; } @Override - public void visit(OverlapsCondition overlapsCondition) { + public Void visit(OverlapsCondition overlapsCondition, S context) { validateOptionalExpressionList(overlapsCondition.getLeft()); validateOptionalExpressionList(overlapsCondition.getRight()); + return null; } @Override - public void visit(EqualsTo equalsTo) { - visitOldOracleJoinBinaryExpression(equalsTo, " = "); + public Void visit(EqualsTo equalsTo, S context) { + validateOldOracleJoinBinaryExpression(equalsTo, " = ", context); + return null; } @Override - public void visit(Division division) { + public Void visit(Division division, S context) { visitBinaryExpression(division, " / "); + return null; } @Override - public void visit(IntegerDivision division) { + public Void visit(IntegerDivision division, S context) { visitBinaryExpression(division, " DIV "); + return null; } @Override - public void visit(DoubleValue doubleValue) { + public Void visit(DoubleValue doubleValue, S context) { // nothing to validate + return null; } @Override - public void visit(HexValue hexValue) { + public Void visit(HexValue hexValue, S context) { // nothing to validate + return null; } @Override - public void visit(NotExpression notExpr) { - notExpr.getExpression().accept(this); + public Void visit(NotExpression notExpr, S context) { + notExpr.getExpression().accept(this, context); + return null; } @Override - public void visit(BitwiseRightShift expr) { + public Void visit(BitwiseRightShift expr, S context) { visitBinaryExpression(expr, " >> "); + return null; } @Override - public void visit(BitwiseLeftShift expr) { + public Void visit(BitwiseLeftShift expr, S context) { visitBinaryExpression(expr, " << "); + return null; } - public void visitOldOracleJoinBinaryExpression(OldOracleJoinBinaryExpression expression, - String operator) { + public void validateOldOracleJoinBinaryExpression(OldOracleJoinBinaryExpression expression, + String operator, S context) { for (ValidationCapability c : getCapabilities()) { validateOptionalExpression(expression.getLeftExpression(), this); if (expression.getOldOracleJoinSyntax() != SupportsOldOracleJoinSyntax.NO_ORACLE_JOIN) { @@ -201,18 +218,20 @@ public void visitOldOracleJoinBinaryExpression(OldOracleJoinBinaryExpression exp } @Override - public void visit(GreaterThan greaterThan) { - visitOldOracleJoinBinaryExpression(greaterThan, " > "); + public Void visit(GreaterThan greaterThan, S context) { + validateOldOracleJoinBinaryExpression(greaterThan, " > ", context); + return null; } @Override - public void visit(GreaterThanEquals greaterThanEquals) { - visitOldOracleJoinBinaryExpression(greaterThanEquals, " >= "); + public Void visit(GreaterThanEquals greaterThanEquals, S context) { + validateOldOracleJoinBinaryExpression(greaterThanEquals, " >= ", context); + return null; } @Override - public void visit(InExpression inExpression) { + public Void visit(InExpression inExpression, S context) { for (ValidationCapability c : getCapabilities()) { validateOptionalExpression(inExpression.getLeftExpression(), this); if (inExpression @@ -221,144 +240,270 @@ public void visit(InExpression inExpression) { } } validateOptionalExpression(inExpression.getRightExpression(), this); + return null; } @Override - public void visit(FullTextSearch fullTextSearch) { + public Void visit(IncludesExpression includesExpression, S context) { + validateOptionalExpression(includesExpression.getLeftExpression(), this); + validateOptionalExpression(includesExpression.getRightExpression(), this); + return null; + } + + @Override + public Void visit(ExcludesExpression excludesExpression, S context) { + validateOptionalExpression(excludesExpression.getLeftExpression(), this); + validateOptionalExpression(excludesExpression.getRightExpression(), this); + return null; + } + + @Override + public Void visit(FullTextSearch fullTextSearch, S context) { validateOptionalExpressions(fullTextSearch.getMatchColumns()); + return null; } @Override - public void visit(SignedExpression signedExpression) { - signedExpression.getExpression().accept(this); + public Void visit(SignedExpression signedExpression, S context) { + signedExpression.getExpression().accept(this, context); + return null; } @Override - public void visit(IsNullExpression isNullExpression) { - isNullExpression.getLeftExpression().accept(this); + public Void visit(IsNullExpression isNullExpression, S context) { + isNullExpression.getLeftExpression().accept(this, context); + return null; } @Override - public void visit(IsBooleanExpression isBooleanExpression) { - isBooleanExpression.getLeftExpression().accept(this); + public Void visit(IsBooleanExpression isBooleanExpression, S context) { + isBooleanExpression.getLeftExpression().accept(this, context); + return null; } @Override - public void visit(JdbcParameter jdbcParameter) { + public Void visit(JdbcParameter jdbcParameter, S context) { validateFeature(Feature.jdbcParameter); + return null; + } + + public void visit(PlainSelect plainSelect) { + visit(plainSelect, null); // Call the parametrized visit method with null context + } + + public void visit(Addition addition) { + visit(addition, null); // Call the parametrized visit method with null context + } + + public void visit(AndExpression andExpression) { + visit(andExpression, null); // Call the parametrized visit method with null context + } + + public void visit(Between between) { + visit(between, null); // Call the parametrized visit method with null context + } + + public void visit(OverlapsCondition overlapsCondition) { + visit(overlapsCondition, null); // Call the parametrized visit method with null context + } + + public void visit(EqualsTo equalsTo) { + visit(equalsTo, null); // Call the parametrized visit method with null context + } + + public void visit(Division division) { + visit(division, null); // Call the parametrized visit method with null context + } + + public void visit(IntegerDivision division) { + visit(division, null); // Call the parametrized visit method with null context + } + + public void visit(DoubleValue doubleValue) { + visit(doubleValue, null); // Call the parametrized visit method with null context + } + + public void visit(HexValue hexValue) { + visit(hexValue, null); // Call the parametrized visit method with null context + } + + public void visit(NotExpression notExpr) { + visit(notExpr, null); // Call the parametrized visit method with null context + } + + public void visit(BitwiseRightShift expr) { + visit(expr, null); // Call the parametrized visit method with null context + } + + public void visit(BitwiseLeftShift expr) { + visit(expr, null); // Call the parametrized visit method with null context + } + + public void visit(GreaterThan greaterThan) { + visit(greaterThan, null); // Call the parametrized visit method with null context + } + + public void visit(GreaterThanEquals greaterThanEquals) { + visit(greaterThanEquals, null); // Call the parametrized visit method with null context + } + + public void visit(InExpression inExpression) { + visit(inExpression, null); // Call the parametrized visit method with null context + } + + public void visit(IncludesExpression includesExpression) { + visit(includesExpression, null); // Call the parametrized visit method with null context + } + + public void visit(ExcludesExpression excludesExpression) { + visit(excludesExpression, null); // Call the parametrized visit method with null context + } + + public void visit(FullTextSearch fullTextSearch) { + visit(fullTextSearch, null); // Call the parametrized visit method with null context + } + + public void visit(SignedExpression signedExpression) { + visit(signedExpression, null); // Call the parametrized visit method with null context + } + + public void visit(IsNullExpression isNullExpression) { + visit(isNullExpression, null); // Call the parametrized visit method with null context + } + + public void visit(IsBooleanExpression isBooleanExpression) { + visit(isBooleanExpression, null); // Call the parametrized visit method with null context + } + + public void visit(JdbcParameter jdbcParameter) { + visit(jdbcParameter, null); // Call the parametrized visit method with null context } + @Override - public void visit(LikeExpression likeExpression) { + public Void visit(LikeExpression likeExpression, S context) { validateFeature(Feature.exprLike); visitBinaryExpression(likeExpression, (likeExpression.isNot() ? " NOT" : "") + (likeExpression.isCaseInsensitive() ? " ILIKE " : " LIKE ")); + return null; } @Override - public void visit(ExistsExpression existsExpression) { - existsExpression.getRightExpression().accept(this); + public Void visit(ExistsExpression existsExpression, S context) { + existsExpression.getRightExpression().accept(this, context); + return null; } @Override - public void visit(MemberOfExpression memberOfExpression) { - memberOfExpression.getLeftExpression().accept(this); - memberOfExpression.getRightExpression().accept(this); + public Void visit(MemberOfExpression memberOfExpression, S context) { + memberOfExpression.getLeftExpression().accept(this, context); + memberOfExpression.getRightExpression().accept(this, context); + return null; } @Override - public void visit(LongValue longValue) { + public Void visit(LongValue longValue, S context) { // nothing to validate + return null; } @Override - public void visit(MinorThan minorThan) { - visitOldOracleJoinBinaryExpression(minorThan, " < "); + public Void visit(MinorThan minorThan, S context) { + validateOldOracleJoinBinaryExpression(minorThan, " < ", context); + return null; } @Override - public void visit(MinorThanEquals minorThanEquals) { - visitOldOracleJoinBinaryExpression(minorThanEquals, " <= "); + public Void visit(MinorThanEquals minorThanEquals, S context) { + validateOldOracleJoinBinaryExpression(minorThanEquals, " <= ", context); + return null; } @Override - public void visit(Multiplication multiplication) { + public Void visit(Multiplication multiplication, S context) { visitBinaryExpression(multiplication, " * "); + return null; } @Override - public void visit(NotEqualsTo notEqualsTo) { - visitOldOracleJoinBinaryExpression(notEqualsTo, - " " + notEqualsTo.getStringExpression() + " "); + public Void visit(NotEqualsTo notEqualsTo, S context) { + validateOldOracleJoinBinaryExpression(notEqualsTo, + " " + notEqualsTo.getStringExpression() + " ", context); + return null; } @Override - public void visit(DoubleAnd doubleAnd) { + public Void visit(DoubleAnd doubleAnd, S context) { + return null; } @Override - public void visit(Contains contains) { + public Void visit(Contains contains, S context) { + return null; } @Override - public void visit(ContainedBy containedBy) { + public Void visit(ContainedBy containedBy, S context) { + return null; } @Override - public void visit(NullValue nullValue) { + public Void visit(NullValue nullValue, S context) { // nothing to validate + return null; } @Override - public void visit(OrExpression orExpression) { + public Void visit(OrExpression orExpression, S context) { visitBinaryExpression(orExpression, " OR "); + return null; } @Override - public void visit(XorExpression xorExpression) { + public Void visit(XorExpression xorExpression, S context) { visitBinaryExpression(xorExpression, " XOR "); + return null; } @Override - public void visit(Parenthesis parenthesis) { - parenthesis.getExpression().accept(this); - } - - @Override - public void visit(StringValue stringValue) { + public Void visit(StringValue stringValue, S context) { // nothing to validate + return null; } @Override - public void visit(Subtraction subtraction) { + public Void visit(Subtraction subtraction, S context) { visitBinaryExpression(subtraction, " - "); + return null; } protected void visitBinaryExpression(BinaryExpression binaryExpression, String operator) { - binaryExpression.getLeftExpression().accept(this); - binaryExpression.getRightExpression().accept(this); + binaryExpression.getLeftExpression().accept(this, null); + binaryExpression.getRightExpression().accept(this, null); } @Override - public void visit(ParenthesedSelect selectBody) { + public Void visit(ParenthesedSelect selectBody, S context) { validateOptionalFromItem(selectBody); + return null; } @Override - public void visit(Column tableColumn) { + public Void visit(Column tableColumn, S context) { validateName(NamedObject.column, tableColumn.getFullyQualifiedName()); + return null; } @Override - public void visit(Function function) { + public Void visit(Function function, S context) { validateFeature(Feature.function); validateOptionalExpressionList(function.getNamedParameters()); @@ -371,86 +516,193 @@ public void visit(Function function) { validateOptionalExpression(function.getKeep(), this); validateOptionalOrderByElements(function.getOrderByElements()); + return null; } @Override - public void visit(DateValue dateValue) { + public Void visit(DateValue dateValue, S context) { // nothing to validate + return null; } @Override - public void visit(TimestampValue timestampValue) { + public Void visit(TimestampValue timestampValue, S context) { // nothing to validate + return null; } @Override - public void visit(TimeValue timeValue) { + public Void visit(TimeValue timeValue, S context) { // nothing to validate + return null; } @Override - public void visit(CaseExpression caseExpression) { + public Void visit(CaseExpression caseExpression, S context) { Expression switchExp = caseExpression.getSwitchExpression(); if (switchExp != null) { - switchExp.accept(this); + switchExp.accept(this, context); } - caseExpression.getWhenClauses().forEach(wc -> wc.accept(this)); + caseExpression.getWhenClauses().forEach(wc -> wc.accept(this, context)); Expression elseExp = caseExpression.getElseExpression(); if (elseExp != null) { - elseExp.accept(this); + elseExp.accept(this, context); } + return null; + } + + public void visit(LikeExpression likeExpression) { + visit(likeExpression, null); + } + + public void visit(ExistsExpression existsExpression) { + visit(existsExpression, null); + } + + public void visit(MemberOfExpression memberOfExpression) { + visit(memberOfExpression, null); + } + + public void visit(LongValue longValue) { + visit(longValue, null); + } + + public void visit(MinorThan minorThan) { + visit(minorThan, null); + } + + public void visit(MinorThanEquals minorThanEquals) { + visit(minorThanEquals, null); + } + + public void visit(Multiplication multiplication) { + visit(multiplication, null); + } + + public void visit(NotEqualsTo notEqualsTo) { + visit(notEqualsTo, null); + } + + public void visit(DoubleAnd doubleAnd) { + visit(doubleAnd, null); + } + + public void visit(Contains contains) { + visit(contains, null); + } + + public void visit(ContainedBy containedBy) { + visit(containedBy, null); + } + + public void visit(NullValue nullValue) { + visit(nullValue, null); + } + + public void visit(OrExpression orExpression) { + visit(orExpression, null); + } + + public void visit(XorExpression xorExpression) { + visit(xorExpression, null); + } + + public void visit(StringValue stringValue) { + visit(stringValue, null); + } + + public void visit(Subtraction subtraction) { + visit(subtraction, null); + } + + public void visit(ParenthesedSelect selectBody) { + visit(selectBody, null); + } + + public void visit(Column tableColumn) { + visit(tableColumn, null); + } + + public void visit(Function function) { + visit(function, null); + } + + public void visit(DateValue dateValue) { + visit(dateValue, null); + } + + public void visit(TimestampValue timestampValue) { + visit(timestampValue, null); + } + + public void visit(TimeValue timeValue) { + visit(timeValue, null); + } + + public void visit(CaseExpression caseExpression) { + visit(caseExpression, null); } + @Override - public void visit(WhenClause whenClause) { - whenClause.getWhenExpression().accept(this); - whenClause.getThenExpression().accept(this); + public Void visit(WhenClause whenClause, S context) { + whenClause.getWhenExpression().accept(this, context); + whenClause.getThenExpression().accept(this, context); + return null; } @Override - public void visit(AnyComparisonExpression anyComparisonExpression) { - anyComparisonExpression.getSelect().accept(this); + public Void visit(AnyComparisonExpression anyComparisonExpression, S context) { + anyComparisonExpression.getSelect().accept(this, context); + return null; } @Override - public void visit(Concat concat) { + public Void visit(Concat concat, S context) { visitBinaryExpression(concat, " || "); + return null; } @Override - public void visit(Matches matches) { - visitOldOracleJoinBinaryExpression(matches, " @@ "); + public Void visit(Matches matches, S context) { + validateOldOracleJoinBinaryExpression(matches, " @@ ", context); + return null; } @Override - public void visit(BitwiseAnd bitwiseAnd) { + public Void visit(BitwiseAnd bitwiseAnd, S context) { visitBinaryExpression(bitwiseAnd, " & "); + return null; } @Override - public void visit(BitwiseOr bitwiseOr) { + public Void visit(BitwiseOr bitwiseOr, S context) { visitBinaryExpression(bitwiseOr, " | "); + return null; } @Override - public void visit(BitwiseXor bitwiseXor) { + public Void visit(BitwiseXor bitwiseXor, S context) { visitBinaryExpression(bitwiseXor, " ^ "); + return null; } @Override - public void visit(CastExpression cast) { - cast.getLeftExpression().accept(this); + public Void visit(CastExpression cast, S context) { + cast.getLeftExpression().accept(this, context); + return null; } @Override - public void visit(Modulo modulo) { + public Void visit(Modulo modulo, S context) { visitBinaryExpression(modulo, " % "); + return null; } @Override - public void visit(AnalyticExpression aexpr) { + public Void visit(AnalyticExpression aexpr, S context) { validateOptionalExpression(aexpr.getExpression(), this); validateOptionalExpression(aexpr.getOffset(), this); validateOptionalExpression(aexpr.getDefaultValue(), this); @@ -467,6 +719,7 @@ public void visit(AnalyticExpression aexpr) { } } validateOptionalExpression(aexpr.getFilterExpression()); + return null; } private void validateOptionalWindowOffset(WindowOffset offset) { @@ -476,236 +729,485 @@ private void validateOptionalWindowOffset(WindowOffset offset) { } @Override - public void visit(ExtractExpression eexpr) { - eexpr.getExpression().accept(this); + public Void visit(ExtractExpression eexpr, S context) { + eexpr.getExpression().accept(this, context); + return null; } @Override - public void visit(IntervalExpression iexpr) { + public Void visit(IntervalExpression iexpr, S context) { validateOptionalExpression(iexpr.getExpression()); + return null; } @Override - public void visit(JdbcNamedParameter jdbcNamedParameter) { + public Void visit(JdbcNamedParameter jdbcNamedParameter, S context) { validateFeature(Feature.jdbcNamedParameter); + return null; } @Override - public void visit(OracleHierarchicalExpression oexpr) { + public Void visit(OracleHierarchicalExpression oexpr, S context) { validateFeature(Feature.oracleHierarchicalExpression); + return null; } @Override - public void visit(RegExpMatchOperator rexpr) { + public Void visit(RegExpMatchOperator rexpr, S context) { visitBinaryExpression(rexpr, " " + rexpr.getStringExpression() + " "); + return null; } @Override - public void visit(JsonExpression jsonExpr) { + public Void visit(JsonExpression jsonExpr, S context) { validateOptionalExpression(jsonExpr.getExpression()); + return null; } @Override - public void visit(JsonOperator jsonExpr) { + public Void visit(JsonOperator jsonExpr, S context) { visitBinaryExpression(jsonExpr, " " + jsonExpr.getStringExpression() + " "); + return null; } @Override - public void visit(UserVariable var) { + public Void visit(UserVariable var, S context) { // nothing to validate + return null; } @Override - public void visit(NumericBind bind) { + public Void visit(NumericBind bind, S context) { // nothing to validate + return null; } @Override - public void visit(KeepExpression aexpr) { + public Void visit(KeepExpression aexpr, S context) { validateOptionalOrderByElements(aexpr.getOrderByElements()); + return null; } @Override - public void visit(MySQLGroupConcat groupConcat) { + public Void visit(MySQLGroupConcat groupConcat, S context) { validateOptionalExpressionList(groupConcat.getExpressionList()); validateOptionalOrderByElements(groupConcat.getOrderByElements()); + return null; } private void validateOptionalExpressionList(ExpressionList expressionList) { if (expressionList != null) { for (Expression expression : expressionList) { - expression.accept(this); + expression.accept(this, null); } } } + public void visit(WhenClause whenClause) { + visit(whenClause, null); + } + + public void visit(AnyComparisonExpression anyComparisonExpression) { + visit(anyComparisonExpression, null); + } + + public void visit(Concat concat) { + visit(concat, null); + } + + public void visit(Matches matches) { + visit(matches, null); + } + + public void visit(BitwiseAnd bitwiseAnd) { + visit(bitwiseAnd, null); + } + + public void visit(BitwiseOr bitwiseOr) { + visit(bitwiseOr, null); + } + + public void visit(BitwiseXor bitwiseXor) { + visit(bitwiseXor, null); + } + + public void visit(CastExpression cast) { + visit(cast, null); + } + + public void visit(Modulo modulo) { + visit(modulo, null); + } + + public void visit(AnalyticExpression aexpr) { + visit(aexpr, null); + } + + public void visit(ExtractExpression eexpr) { + visit(eexpr, null); + } + + public void visit(IntervalExpression iexpr) { + visit(iexpr, null); + } + + public void visit(JdbcNamedParameter jdbcNamedParameter) { + visit(jdbcNamedParameter, null); + } + + public void visit(OracleHierarchicalExpression oexpr) { + visit(oexpr, null); + } + + public void visit(RegExpMatchOperator rexpr) { + visit(rexpr, null); + } + + public void visit(JsonExpression jsonExpr) { + visit(jsonExpr, null); + } + + public void visit(JsonOperator jsonExpr) { + visit(jsonExpr, null); + } + + public void visit(UserVariable var) { + visit(var, null); + } + + public void visit(NumericBind bind) { + visit(bind, null); + } + + public void visit(KeepExpression aexpr) { + visit(aexpr, null); + } + + public void visit(MySQLGroupConcat groupConcat) { + visit(groupConcat, null); + } + @Override - public void visit(ExpressionList expressionList) { + public Void visit(ExpressionList expressionList, S context) { validateOptionalExpressionList(expressionList); + return null; } @Override - public void visit(RowConstructor rowConstructor) { + public Void visit(RowConstructor rowConstructor, S context) { validateOptionalExpressionList(rowConstructor); + return null; } @Override - public void visit(RowGetExpression rowGetExpression) { - rowGetExpression.getExpression().accept(this); + public Void visit(RowGetExpression rowGetExpression, S context) { + rowGetExpression.getExpression().accept(this, context); + return null; } @Override - public void visit(OracleHint hint) { + public Void visit(OracleHint hint, S context) { // nothing to validate + return null; } @Override - public void visit(TimeKeyExpression timeKeyExpression) { + public Void visit(TimeKeyExpression timeKeyExpression, S context) { // nothing to validate + return null; } @Override - public void visit(DateTimeLiteralExpression literal) { + public Void visit(DateTimeLiteralExpression literal, S context) { // nothing to validate + return null; } @Override - public void visit(NextValExpression nextVal) { + public Void visit(NextValExpression nextVal, S context) { validateName(NamedObject.sequence, nextVal.getName()); + return null; } @Override - public void visit(CollateExpression col) { + public Void visit(CollateExpression col, S context) { validateOptionalExpression(col.getLeftExpression()); + return null; } @Override - public void visit(SimilarToExpression expr) { + public Void visit(SimilarToExpression expr, S context) { validateFeature(Feature.exprSimilarTo); visitBinaryExpression(expr, (expr.isNot() ? " NOT" : "") + " SIMILAR TO "); + return null; } @Override - public void visit(ArrayExpression array) { - array.getObjExpression().accept(this); + public Void visit(ArrayExpression array, S context) { + array.getObjExpression().accept(this, context); if (array.getIndexExpression() != null) { - array.getIndexExpression().accept(this); + array.getIndexExpression().accept(this, context); } if (array.getStartIndexExpression() != null) { - array.getStartIndexExpression().accept(this); + array.getStartIndexExpression().accept(this, context); } if (array.getStopIndexExpression() != null) { - array.getStopIndexExpression().accept(this); + array.getStopIndexExpression().accept(this, context); } + return null; } @Override - public void visit(ArrayConstructor aThis) { + public Void visit(ArrayConstructor aThis, S context) { for (Expression expression : aThis.getExpressions()) { - expression.accept(this); + expression.accept(this, context); } + return null; } @Override public void validate(Expression expression) { - expression.accept(this); + expression.accept(this, null); } @Override - public void visit(VariableAssignment a) { + public Void visit(VariableAssignment a, S context) { validateOptionalExpression(a.getExpression()); if (a.getVariable() != null) { - a.getVariable().accept(this); + a.getVariable().accept(this, context); } + return null; } @Override - public void visit(TimezoneExpression a) { + public Void visit(TimezoneExpression a, S context) { validateOptionalExpression(a.getLeftExpression()); + return null; } @Override - public void visit(XMLSerializeExpr xml) { - // TODO this feature seams very close to a jsqlparser-user usecase + public Void visit(XMLSerializeExpr xml, S context) { + return null; } @Override - public void visit(JsonAggregateFunction expression) { + public Void visit(JsonAggregateFunction expression, S context) { // no idea what this is good for + return null; } @Override - public void visit(JsonFunction expression) { + public Void visit(JsonFunction expression, S context) { // no idea what this is good for + return null; } @Override - public void visit(ConnectByRootOperator connectByRootOperator) { - connectByRootOperator.getColumn().accept(this); + public Void visit(ConnectByRootOperator connectByRootOperator, S context) { + connectByRootOperator.getColumn().accept(this, context); + return null; } @Override - public void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter) { - oracleNamedFunctionParameter.getExpression().accept(this); + public Void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, S context) { + oracleNamedFunctionParameter.getExpression().accept(this, context); + return null; } @Override - public void visit(AllColumns allColumns) {} + public Void visit(AllColumns allColumns, S context) { + return null; + } @Override - public void visit(AllTableColumns allTableColumns) {} + public Void visit(AllTableColumns allTableColumns, S context) { + return null; + } @Override - public void visit(AllValue allValue) { - + public Void visit(AllValue allValue, S context) { + return null; } @Override - public void visit(IsDistinctExpression isDistinctExpression) { - isDistinctExpression.getLeftExpression().accept(this); - isDistinctExpression.getRightExpression().accept(this); + public Void visit(IsDistinctExpression isDistinctExpression, S context) { + isDistinctExpression.getLeftExpression().accept(this, context); + isDistinctExpression.getRightExpression().accept(this, context); + return null; } @Override - public void visit(GeometryDistance geometryDistance) { - visitOldOracleJoinBinaryExpression(geometryDistance, " <-> "); + public Void visit(GeometryDistance geometryDistance, S context) { + validateOldOracleJoinBinaryExpression(geometryDistance, " <-> ", context); + return null; } @Override - public void visit(Select selectBody) { - + public Void visit(Select select, S context) { + return null; } @Override - public void visit(TranscodingFunction transcodingFunction) { - transcodingFunction.getExpression().accept(this); + public Void visit(TranscodingFunction transcodingFunction, S context) { + transcodingFunction.getExpression().accept(this, context); + return null; } @Override - public void visit(TrimFunction trimFunction) { + public Void visit(TrimFunction trimFunction, S context) { if (trimFunction.getExpression() != null) { - trimFunction.getExpression().accept(this); + trimFunction.getExpression().accept(this, context); } if (trimFunction.getFromExpression() != null) { - trimFunction.getFromExpression().accept(this); + trimFunction.getFromExpression().accept(this, context); } + return null; } @Override - public void visit(RangeExpression rangeExpression) { - rangeExpression.getStartExpression().accept(this); - rangeExpression.getEndExpression().accept(this); + public Void visit(RangeExpression rangeExpression, S context) { + rangeExpression.getStartExpression().accept(this, context); + rangeExpression.getEndExpression().accept(this, context); + return null; } @Override - public void visit(TSQLLeftJoin tsqlLeftJoin) { - tsqlLeftJoin.getLeftExpression().accept(this); - tsqlLeftJoin.getRightExpression().accept(this); + public Void visit(TSQLLeftJoin tsqlLeftJoin, S context) { + tsqlLeftJoin.getLeftExpression().accept(this, context); + tsqlLeftJoin.getRightExpression().accept(this, context); + return null; + } + + @Override + public Void visit(TSQLRightJoin tsqlRightJoin, S context) { + tsqlRightJoin.getLeftExpression().accept(this, context); + tsqlRightJoin.getRightExpression().accept(this, context); + return null; + } + + @Override + public Void visit(StructType structType, S context) { + if (structType.getArguments() != null) { + for (SelectItem selectItem : structType.getArguments()) { + selectItem.getExpression().accept(this, context); + } + } + return null; } @Override + public Void visit(LambdaExpression lambdaExpression, S context) { + lambdaExpression.getExpression().accept(this, context); + return null; + } + + public void visit(TimeKeyExpression timeKeyExpression) { + visit(timeKeyExpression, null); + } + + public void visit(DateTimeLiteralExpression literal) { + visit(literal, null); + } + + public void visit(NextValExpression nextVal) { + visit(nextVal, null); + } + + public void visit(CollateExpression col) { + visit(col, null); + } + + public void visit(SimilarToExpression expr) { + visit(expr, null); + } + + public void visit(ArrayExpression array) { + visit(array, null); + } + + public void visit(ArrayConstructor aThis) { + visit(aThis, null); + } + + + public void visit(VariableAssignment a) { + visit(a, null); + } + + public void visit(TimezoneExpression a) { + visit(a, null); + } + + public void visit(XMLSerializeExpr xml) { + visit(xml, null); + } + + public void visit(JsonAggregateFunction expression) { + visit(expression, null); + } + + public void visit(JsonFunction expression) { + visit(expression, null); + } + + public void visit(ConnectByRootOperator connectByRootOperator) { + visit(connectByRootOperator, null); + } + + public void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter) { + visit(oracleNamedFunctionParameter, null); + } + + public void visit(AllColumns allColumns) { + visit(allColumns, null); + } + + public void visit(AllTableColumns allTableColumns) { + visit(allTableColumns, null); + } + + public void visit(AllValue allValue) { + visit(allValue, null); + } + + public void visit(IsDistinctExpression isDistinctExpression) { + visit(isDistinctExpression, null); + } + + public void visit(GeometryDistance geometryDistance) { + visit(geometryDistance, null); + } + + public void visit(Select select) { + visit(select, null); + } + + public void visit(TranscodingFunction transcodingFunction) { + visit(transcodingFunction, null); + } + + public void visit(TrimFunction trimFunction) { + visit(trimFunction, null); + } + + public void visit(RangeExpression rangeExpression) { + visit(rangeExpression, null); + } + + public void visit(TSQLLeftJoin tsqlLeftJoin) { + visit(tsqlLeftJoin, null); + } + public void visit(TSQLRightJoin tsqlRightJoin) { - tsqlRightJoin.getLeftExpression().accept(this); - tsqlRightJoin.getRightExpression().accept(this); + visit(tsqlRightJoin, null); } + + public void visit(StructType structType) { + visit(structType, null); + } + + public void visit(LambdaExpression lambdaExpression) { + visit(lambdaExpression, null); + } + } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/GroupByValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/GroupByValidator.java index 215b5b514..ee2d7155f 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/GroupByValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/GroupByValidator.java @@ -19,15 +19,16 @@ /** * @author gitmotte */ -public class GroupByValidator extends AbstractValidator implements GroupByVisitor { +public class GroupByValidator extends AbstractValidator + implements GroupByVisitor { @Override public void validate(GroupByElement groupBy) { - groupBy.accept(this); + groupBy.accept(this, null); } @Override - public void visit(GroupByElement groupBy) { + public Void visit(GroupByElement groupBy, S context) { for (ValidationCapability c : getCapabilities()) { validateFeature(c, Feature.selectGroupBy); if (isNotEmpty(groupBy.getGroupingSets())) { @@ -46,6 +47,7 @@ public void visit(GroupByElement groupBy) { } } } + return null; } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/InsertValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/InsertValidator.java index be09f314c..c1186ba1a 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/InsertValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/InsertValidator.java @@ -45,7 +45,7 @@ public void validate(Insert insert) { validateOptionalExpressions(insert.getColumns()); if (insert.getSelect() instanceof Values) { - insert.getSelect().accept(getValidator(StatementValidator.class)); + insert.getSelect().accept(getValidator(StatementValidator.class), null); validateOptionalExpressions(insert.getValues().getExpressions()); } @@ -55,8 +55,8 @@ public void validate(Insert insert) { // validateModelCondition (insert.getSetColumns().size() != // insert.getSetExpressionList().size(), "model-error"); for (UpdateSet updateSet : insert.getSetUpdateSets()) { - updateSet.getColumns().forEach(c -> c.accept(v)); - updateSet.getValues().forEach(c -> c.accept(v)); + updateSet.getColumns().forEach(c -> c.accept(v, null)); + updateSet.getValues().forEach(c -> c.accept(v, null)); } } @@ -66,14 +66,14 @@ public void validate(Insert insert) { // validateModelCondition (insert.getSetColumns().size() != // insert.getSetExpressionList().size(), "model-error"); for (UpdateSet updateSet : insert.getDuplicateUpdateSets()) { - updateSet.getColumns().forEach(c -> c.accept(v)); - updateSet.getValues().forEach(c -> c.accept(v)); + updateSet.getColumns().forEach(c -> c.accept(v, null)); + updateSet.getValues().forEach(c -> c.accept(v, null)); } } if (insert.getReturningClause() != null) { SelectValidator v = getValidator(SelectValidator.class); - insert.getReturningClause().forEach(c -> c.accept(v)); + insert.getReturningClause().forEach(c -> c.accept(v, null)); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/MergeValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/MergeValidator.java index e9e0765cc..e82ebc91d 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/MergeValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/MergeValidator.java @@ -17,7 +17,8 @@ /** * @author gitmotte */ -public class MergeValidator extends AbstractValidator implements MergeOperationVisitor { +public class MergeValidator extends AbstractValidator + implements MergeOperationVisitor { @Override @@ -27,18 +28,23 @@ public void validate(Merge merge) { } validateOptionalExpression(merge.getOnCondition()); if (merge.getOperations() != null) { - merge.getOperations().forEach(operation -> operation.accept(this)); + merge.getOperations().forEach(operation -> operation.accept(this, null)); } validateOptionalFromItems(merge.getFromItem()); } @Override - public void visit(MergeDelete mergeDelete) { + public Void visit(MergeDelete mergeDelete, S context) { validateOptionalExpression(mergeDelete.getAndPredicate()); + return null; + } + + public void visit(MergeDelete mergeDelete) { + visit(mergeDelete, null); } @Override - public void visit(MergeUpdate mergeUpdate) { + public Void visit(MergeUpdate mergeUpdate, S context) { validateOptionalExpression(mergeUpdate.getAndPredicate()); for (UpdateSet updateSet : mergeUpdate.getUpdateSets()) { validateOptionalExpressions(updateSet.getColumns()); @@ -46,12 +52,23 @@ public void visit(MergeUpdate mergeUpdate) { } validateOptionalExpression(mergeUpdate.getDeleteWhereCondition()); validateOptionalExpression(mergeUpdate.getWhereCondition()); + return null; + } + + public void visit(MergeUpdate mergeUpdate) { + visit(mergeUpdate, null); } @Override - public void visit(MergeInsert mergeInsert) { + public Void visit(MergeInsert mergeInsert, S context) { validateOptionalExpression(mergeInsert.getAndPredicate()); validateOptionalExpressions(mergeInsert.getColumns()); validateOptionalExpressions(mergeInsert.getValues()); + + return null; + } + + public void visit(MergeInsert mergeInsert) { + visit(mergeInsert, null); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/OrderByValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/OrderByValidator.java index 20a5c780d..858702dda 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/OrderByValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/OrderByValidator.java @@ -1,36 +1,42 @@ -/*- - * #%L - * JSQLParser library - * %% - * Copyright (C) 2004 - 2020 JSQLParser - * %% - * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 - * #L% - */ -package net.sf.jsqlparser.util.validation.validator; - -import net.sf.jsqlparser.parser.feature.Feature; -import net.sf.jsqlparser.statement.select.OrderByElement; -import net.sf.jsqlparser.statement.select.OrderByVisitor; -import net.sf.jsqlparser.util.validation.ValidationCapability; - -/** - * @author gitmotte - */ -public class OrderByValidator extends AbstractValidator implements OrderByVisitor { - - @Override - public void validate(OrderByElement element) { - element.accept(this); - } - - @Override - public void visit(OrderByElement orderBy) { - for (ValidationCapability c : getCapabilities()) { - validateFeature(c, Feature.orderBy); - validateOptionalFeature(c, orderBy.getNullOrdering(), Feature.orderByNullOrdering); - } - getValidator(ExpressionValidator.class).validate(orderBy.getExpression()); - } +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2020 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.util.validation.validator; -} +import net.sf.jsqlparser.parser.feature.Feature; +import net.sf.jsqlparser.statement.select.OrderByElement; +import net.sf.jsqlparser.statement.select.OrderByVisitor; +import net.sf.jsqlparser.util.validation.ValidationCapability; + +/** + * @author gitmotte + */ +public class OrderByValidator extends AbstractValidator + implements OrderByVisitor { + + @Override + public void validate(OrderByElement element) { + element.accept(this, null); + } + + @Override + public Void visit(OrderByElement orderBy, S context) { + for (ValidationCapability c : getCapabilities()) { + validateFeature(c, Feature.orderBy); + validateOptionalFeature(c, orderBy.getNullOrdering(), Feature.orderByNullOrdering); + } + getValidator(ExpressionValidator.class).validate(orderBy.getExpression()); + return null; + } + + public void visit(OrderByElement orderBy) { + visit(orderBy, null); + } + +} diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/SelectValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/SelectValidator.java index 97fcd08a3..4ed464ddc 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/SelectValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/SelectValidator.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.util.validation.validator; import java.util.List; + import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.MySQLIndexHint; import net.sf.jsqlparser.expression.SQLServerHints; @@ -47,15 +48,16 @@ /** * @author gitmotte */ -public class SelectValidator extends AbstractValidator - implements SelectVisitor, SelectItemVisitor, FromItemVisitor, PivotVisitor { +public class SelectValidator extends AbstractValidator> + implements SelectVisitor, SelectItemVisitor, FromItemVisitor, + PivotVisitor { @SuppressWarnings({"PMD.CyclomaticComplexity"}) @Override - public void visit(PlainSelect plainSelect) { + public Void visit(PlainSelect plainSelect, S context) { if (isNotEmpty(plainSelect.getWithItemsList())) { plainSelect.getWithItemsList() - .forEach(withItem -> withItem.accept((SelectVisitor) this)); + .forEach(withItem -> withItem.accept((SelectVisitor) this, context)); } for (ValidationCapability c : getCapabilities()) { @@ -111,13 +113,15 @@ public void visit(PlainSelect plainSelect) { validateOptionalJoins(plainSelect.getJoins()); // to correctly recognize aliased tables - validateOptionalList(plainSelect.getSelectItems(), () -> this, (e, v) -> e.accept(v)); + // @todo: fix this properly, I don't understand functional syntax + // validateOptionalList(plainSelect.getSelectItems(), () -> this, SelectItem::accept, + // context); validateOptionalExpression(plainSelect.getWhere()); validateOptionalExpression(plainSelect.getOracleHierarchical()); if (plainSelect.getGroupBy() != null) { - plainSelect.getGroupBy().accept(getValidator(GroupByValidator.class)); + plainSelect.getGroupBy().accept(getValidator(GroupByValidator.class), context); } validateOptionalExpression(plainSelect.getHaving()); @@ -135,30 +139,34 @@ public void visit(PlainSelect plainSelect) { validateFetch(plainSelect.getFetch()); } + return null; } @Override - public void visit(SelectItem selectExpressionItem) { - selectExpressionItem.getExpression().accept(getValidator(ExpressionValidator.class)); + public Void visit(SelectItem selectExpressionItem, S context) { + selectExpressionItem.getExpression().accept(getValidator(ExpressionValidator.class), + context); + return null; } @Override - public void visit(ParenthesedSelect selectBody) { + public Void visit(ParenthesedSelect selectBody, S context) { if (isNotEmpty(selectBody.getWithItemsList())) { selectBody.getWithItemsList() - .forEach(withItem -> withItem.accept((SelectVisitor) this)); + .forEach(withItem -> withItem.accept((SelectVisitor) this, context)); } - selectBody.getSelect().accept(this); - validateOptional(selectBody.getPivot(), p -> p.accept(this)); + selectBody.getSelect().accept(this, context); + validateOptional(selectBody.getPivot(), p -> p.accept(this, context)); + return null; } @Override - public void visit(Table table) { + public Void visit(Table table, S context) { validateNameWithAlias(NamedObject.table, table.getFullyQualifiedName(), ValidationUtil.getAlias(table.getAlias())); - validateOptional(table.getPivot(), p -> p.accept(this)); - validateOptional(table.getUnPivot(), up -> up.accept(this)); + validateOptional(table.getPivot(), p -> p.accept(this, context)); + validateOptional(table.getUnPivot(), up -> up.accept(this, context)); MySQLIndexHint indexHint = table.getIndexHint(); if (indexHint != null && isNotEmpty(indexHint.getIndexNames())) { @@ -168,33 +176,37 @@ public void visit(Table table) { if (sqlServerHints != null) { validateName(NamedObject.index, sqlServerHints.getIndexName()); } + return null; } @Override - public void visit(Pivot pivot) { + public Void visit(Pivot pivot, S context) { validateFeature(Feature.pivot); validateOptionalExpressions(pivot.getForColumns()); + return null; } @Override - public void visit(UnPivot unpivot) { + public Void visit(UnPivot unpivot, S context) { validateFeature(Feature.unpivot); validateOptionalExpressions(unpivot.getUnPivotForClause()); validateOptionalExpressions(unpivot.getUnPivotClause()); + return null; } @Override - public void visit(PivotXml pivot) { + public Void visit(PivotXml pivot, S context) { validateFeature(Feature.pivotXml); validateOptionalExpressions(pivot.getForColumns()); if (isNotEmpty(pivot.getFunctionItems())) { ExpressionValidator v = getValidator(ExpressionValidator.class); - pivot.getFunctionItems().forEach(f -> f.getExpression().accept(v)); + pivot.getFunctionItems().forEach(f -> f.getExpression().accept(v, context)); } if (pivot.getInSelect() != null) { - pivot.getInSelect().accept(this); + pivot.getInSelect().accept(this, context); } + return null; } public void validateOffset(Offset offset) { @@ -249,10 +261,10 @@ public void validateOptionalJoin(Join join) { } @Override - public void visit(SetOperationList setOperation) { + public Void visit(SetOperationList setOperation, S context) { if (isNotEmpty(setOperation.getWithItemsList())) { setOperation.getWithItemsList() - .forEach(withItem -> withItem.accept((SelectVisitor) this)); + .forEach(withItem -> withItem.accept((SelectVisitor) this, context)); } for (ValidationCapability c : getCapabilities()) { validateFeature(c, Feature.setOperation); @@ -271,7 +283,7 @@ public void visit(SetOperationList setOperation) { } if (isNotEmpty(setOperation.getSelects())) { - setOperation.getSelects().forEach(s -> s.accept(this)); + setOperation.getSelects().forEach(s -> s.accept(this, context)); } validateOptionalOrderByElements(setOperation.getOrderByElements()); @@ -287,58 +299,121 @@ public void visit(SetOperationList setOperation) { if (setOperation.getFetch() != null) { validateFetch(setOperation.getFetch()); } + return null; } @Override - public void visit(WithItem withItem) { + public Void visit(WithItem withItem, S context) { for (ValidationCapability c : getCapabilities()) { validateFeature(c, Feature.withItem); validateFeature(c, withItem.isRecursive(), Feature.withItemRecursive); } if (isNotEmpty(withItem.getWithItemList())) { - withItem.getWithItemList().forEach(wi -> wi.accept(this)); + withItem.getWithItemList().forEach(wi -> wi.accept(this, context)); } - withItem.getSelect().accept(this); + withItem.getSelect().accept(this, context); + return null; } @Override - public void visit(LateralSubSelect lateralSubSelect) { + public Void visit(LateralSubSelect lateralSubSelect, S context) { if (isNotEmpty(lateralSubSelect.getWithItemsList())) { lateralSubSelect.getWithItemsList() - .forEach(withItem -> withItem.accept((SelectVisitor) this)); + .forEach(withItem -> withItem.accept((SelectVisitor) this, context)); } validateFeature(Feature.lateralSubSelect); - validateOptional(lateralSubSelect.getPivot(), p -> p.accept(this)); - validateOptional(lateralSubSelect.getUnPivot(), up -> up.accept(this)); - validateOptional(lateralSubSelect.getSelect(), e -> e.accept(this)); + validateOptional(lateralSubSelect.getPivot(), p -> p.accept(this, context)); + validateOptional(lateralSubSelect.getUnPivot(), up -> up.accept(this, context)); + validateOptional(lateralSubSelect.getSelect(), e -> e.accept(this, context)); + return null; } @Override - public void visit(TableStatement tableStatement) { + public Void visit(TableStatement tableStatement, S context) { getValidator(TableStatementValidator.class).validate(tableStatement); + return null; } @Override - public void visit(TableFunction tableFunction) { + public Void visit(TableFunction tableFunction, S context) { validateFeature(Feature.tableFunction); - validateOptional(tableFunction.getPivot(), p -> p.accept(this)); - validateOptional(tableFunction.getUnPivot(), up -> up.accept(this)); + validateOptional(tableFunction.getPivot(), p -> p.accept(this, context)); + validateOptional(tableFunction.getUnPivot(), up -> up.accept(this, context)); + return null; } @Override - public void visit(ParenthesedFromItem parenthesis) { - validateOptional(parenthesis.getFromItem(), e -> e.accept(this)); + public Void visit(ParenthesedFromItem parenthesis, S context) { + validateOptional(parenthesis.getFromItem(), e -> e.accept(this, context)); + return null; } @Override - public void visit(Values values) { + public Void visit(Values values, S context) { getValidator(ValuesStatementValidator.class).validate(values); + return null; } @Override - public void validate(SelectItem statement) { - statement.accept(this); + public void validate(SelectItem statement) { + statement.accept(this, null); + } + + public void visit(PlainSelect plainSelect) { + visit(plainSelect, null); + } + + public void visit(SelectItem selectExpressionItem) { + visit(selectExpressionItem, null); + } + + public void visit(ParenthesedSelect selectBody) { + visit(selectBody, null); + } + + public void visit(Table table) { + visit(table, null); + } + + public void visit(Pivot pivot) { + visit(pivot, null); + } + + public void visit(UnPivot unpivot) { + visit(unpivot, null); + } + + public void visit(PivotXml pivot) { + visit(pivot, null); + } + + public void visit(SetOperationList setOperation) { + visit(setOperation, null); + } + + public void visit(WithItem withItem) { + visit(withItem, null); + } + + public void visit(LateralSubSelect lateralSubSelect) { + visit(lateralSubSelect, null); + } + + public void visit(TableStatement tableStatement) { + visit(tableStatement, null); + } + + public void visit(TableFunction tableFunction) { + visit(tableFunction, null); + } + + public void visit(ParenthesedFromItem parenthesis) { + visit(parenthesis, null); + } + + public void visit(Values values) { + visit(values, null); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/ShowIndexStatementValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/ShowIndexStatementValidator.java index 624ee3828..8a35faffb 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/ShowIndexStatementValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/ShowIndexStatementValidator.java @@ -14,9 +14,8 @@ import net.sf.jsqlparser.util.validation.metadata.NamedObject; /** -* -* @author Jayant Kumar Yadav -*/ + * @author Jayant Kumar Yadav + */ public class ShowIndexStatementValidator extends AbstractValidator { @@ -24,4 +23,4 @@ public class ShowIndexStatementValidator extends AbstractValidator implements StatementVisitor { +public class StatementValidator extends AbstractValidator + implements StatementVisitor { @Override - public void visit(CreateIndex createIndex) { + public Void visit(CreateIndex createIndex, S context) { getValidator(CreateIndexValidator.class).validate(createIndex); + return null; } @Override - public void visit(CreateTable createTable) { + public Void visit(CreateTable createTable, S context) { getValidator(CreateTableValidator.class).validate(createTable); + return null; } @Override - public void visit(CreateView createView) { + public Void visit(CreateView createView, S context) { getValidator(CreateViewValidator.class).validate(createView); + return null; } @Override - public void visit(AlterView alterView) { + public Void visit(AlterView alterView, S context) { getValidator(AlterViewValidator.class).validate(alterView); + return null; } @Override - public void visit(RefreshMaterializedViewStatement materializedView) { + public Void visit(RefreshMaterializedViewStatement materializedView, S context) { getValidator(RefreshMaterializedViewStatementValidator.class).validate(materializedView); + return null; } @Override - public void visit(Delete delete) { + public Void visit(Delete delete, S context) { getValidator(DeleteValidator.class).validate(delete); + return null; } @Override - public void visit(Drop drop) { + public Void visit(Drop drop, S context) { getValidator(DropValidator.class).validate(drop); + return null; } @Override - public void visit(Insert insert) { + public Void visit(Insert insert, S context) { getValidator(InsertValidator.class).validate(insert); + return null; } @Override - public void visit(Select select) { + public Void visit(Select select, S context) { validateFeature(Feature.select); SelectValidator selectValidator = getValidator(SelectValidator.class); - select.accept(selectValidator); + select.accept(selectValidator, null); + return null; } @Override - public void visit(Truncate truncate) { + public Void visit(Truncate truncate, S context) { validateFeature(Feature.truncate); validateOptionalFromItem(truncate.getTable()); + return null; } @Override - public void visit(Update update) { + public Void visit(Update update, S context) { getValidator(UpdateValidator.class).validate(update); + return null; } @Override - public void visit(Alter alter) { + public Void visit(Alter alter, S context) { getValidator(AlterValidator.class).validate(alter); + return null; } @Override - public void visit(Statements stmts) { - stmts.getStatements().forEach(s -> s.accept(this)); + public Void visit(Statements statements, S context) { + statements.forEach(s -> s.accept(this, context)); + return null; } @Override - public void visit(Execute execute) { + public Void visit(Execute execute, S context) { getValidator(ExecuteValidator.class).validate(execute); + return null; } @Override - public void visit(SetStatement set) { + public Void visit(SetStatement set, S context) { getValidator(SetStatementValidator.class).validate(set); + return null; } @Override - public void visit(ResetStatement reset) { + public Void visit(ResetStatement reset, S context) { getValidator(ResetStatementValidator.class).validate(reset); + return null; } @Override - public void visit(Merge merge) { + public Void visit(Merge merge, S context) { getValidator(MergeValidator.class).validate(merge); + return null; } @Override - public void visit(Commit commit) { + public Void visit(Commit commit, S context) { validateFeature(Feature.commit); + return null; } @Override - public void visit(Upsert upsert) { + public Void visit(Upsert upsert, S context) { getValidator(UpsertValidator.class).validate(upsert); + return null; } @Override - public void visit(UseStatement use) { + public Void visit(UseStatement use, S context) { getValidator(UseStatementValidator.class).validate(use); + return null; } @Override - public void visit(ShowStatement show) { - getValidator(ShowStatementValidator.class).validate(show); + public Void visit(ShowStatement showStatement, S context) { + getValidator(ShowStatementValidator.class).validate(showStatement); + return null; } @Override - public void visit(ShowColumnsStatement show) { + public Void visit(ShowColumnsStatement show, S context) { getValidator(ShowColumnsStatementValidator.class).validate(show); + return null; } @Override - public void visit(ShowIndexStatement show) { + public Void visit(ShowIndexStatement show, S context) { getValidator(ShowIndexStatementValidator.class).validate(show); + return null; } @Override - public void visit(ShowTablesStatement showTables) { + public Void visit(ShowTablesStatement showTables, S context) { getValidator(ShowTablesStatementValidator.class).validate(showTables); + return null; } @Override - public void visit(Block block) { + public Void visit(Block block, S context) { validateFeature(Feature.block); - block.getStatements().accept(this); + block.getStatements().accept(this, context); + return null; } @Override - public void visit(Comment comment) { + public Void visit(Comment comment, S context) { for (ValidationCapability c : getCapabilities()) { validateFeature(c, Feature.comment); validateOptionalFeature(c, comment.getTable(), Feature.commentOnTable); validateOptionalFeature(c, comment.getColumn(), Feature.commentOnColumn); validateOptionalFeature(c, comment.getView(), Feature.commentOnView); } + return null; } @Override - public void visit(DescribeStatement describe) { + public Void visit(DescribeStatement describe, S context) { validateFeature(Feature.describe); validateFeature(Feature.desc); validateOptionalFromItem(describe.getTable()); + return null; } @Override - public void visit(ExplainStatement explain) { + public Void visit(ExplainStatement explainStatement, S context) { validateFeature(Feature.explain); - if (explain.getStatement() != null) { - explain.getStatement().accept(this); + if (explainStatement.getStatement() != null) { + explainStatement.getStatement().accept(this, context); } + return null; } @Override - public void visit(DeclareStatement declare) { - getValidator(DeclareStatementValidator.class).validate(declare); + public Void visit(DeclareStatement declareStatement, S context) { + getValidator(DeclareStatementValidator.class).validate(declareStatement); + return null; } @Override - public void visit(Grant grant) { + public Void visit(Grant grant, S context) { getValidator(GrantValidator.class).validate(grant); + return null; } @Override - public void visit(CreateSchema aThis) { + public Void visit(CreateSchema aThis, S context) { validateFeatureAndName(Feature.createSchema, NamedObject.schema, aThis.getSchemaName()); - aThis.getStatements().forEach(s -> s.accept(this)); + aThis.getStatements().forEach(s -> s.accept(this, context)); + return null; } @Override - public void visit(CreateSequence createSequence) { + public Void visit(CreateSequence createSequence, S context) { getValidator(CreateSequenceValidator.class).validate(createSequence); + return null; } @Override - public void visit(AlterSequence alterSequence) { + public Void visit(AlterSequence alterSequence, S context) { getValidator(AlterSequenceValidator.class).validate(alterSequence); + return null; } @Override - public void visit(CreateFunctionalStatement createFunctionalStatement) { + public Void visit(CreateFunctionalStatement createFunctionalStatement, S context) { validateFeature(Feature.functionalStatement); if (createFunctionalStatement instanceof CreateFunction) { validateFeature(Feature.createFunction); } else if (createFunctionalStatement instanceof CreateProcedure) { validateFeature(Feature.createProcedure); } + return null; } @Override public void validate(Statement statement) { - statement.accept(this); + statement.accept(this, null); } @Override - public void visit(CreateSynonym createSynonym) { + public Void visit(CreateSynonym createSynonym, S context) { getValidator(CreateSynonymValidator.class).validate(createSynonym); + return null; } @Override - public void visit(Analyze analyze) { + public Void visit(Analyze analyze, S context) { getValidator(AnalyzeValidator.class).validate(analyze); + return null; } @Override - public void visit(SavepointStatement savepointStatement) { + public Void visit(SavepointStatement savepointStatement, S context) { // TODO: not yet implemented + return null; } @Override - public void visit(RollbackStatement rollbackStatement) { + public Void visit(RollbackStatement rollbackStatement, S context) { // TODO: not yet implemented + return null; } @Override - public void visit(AlterSession alterSession) { + public Void visit(AlterSession alterSession, S context) { // TODO: not yet implemented + return null; } @Override - public void visit(IfElseStatement ifElseStatement) { - ifElseStatement.getIfStatement().accept(this); + public Void visit(IfElseStatement ifElseStatement, S context) { + ifElseStatement.getIfStatement().accept(this, context); if (ifElseStatement.getElseStatement() != null) { - ifElseStatement.getElseStatement().accept(this); + ifElseStatement.getElseStatement().accept(this, context); } + return null; } - public void visit(RenameTableStatement renameTableStatement) { + public Void visit(RenameTableStatement renameTableStatement, S context) { // TODO: not yet implemented + return null; } @Override - public void visit(PurgeStatement purgeStatement) { + public Void visit(PurgeStatement purgeStatement, S context) { // TODO: not yet implemented + return null; } @Override - public void visit(AlterSystemStatement alterSystemStatement) { + public Void visit(AlterSystemStatement alterSystemStatement, S context) { // TODO: not yet implemented + return null; } @Override - public void visit(UnsupportedStatement unsupportedStatement) { + public Void visit(UnsupportedStatement unsupportedStatement, S context) { + return null; + } + + public void visit(CreateIndex createIndex) { + visit(createIndex, null); } + + public void visit(CreateTable createTable) { + visit(createTable, null); + } + + public void visit(CreateView createView) { + visit(createView, null); + } + + public void visit(AlterView alterView) { + visit(alterView, null); + } + + public void visit(RefreshMaterializedViewStatement materializedView) { + visit(materializedView, null); + } + + public void visit(Delete delete) { + visit(delete, null); + } + + public void visit(Drop drop) { + visit(drop, null); + } + + public void visit(Insert insert) { + visit(insert, null); + } + + public void visit(Select select) { + visit(select, null); + } + + public void visit(Truncate truncate) { + visit(truncate, null); + } + + public void visit(Update update) { + visit(update, null); + } + + public void visit(Alter alter) { + visit(alter, null); + } + + public void visit(Statements statements) { + visit(statements, null); + } + + public void visit(Execute execute) { + visit(execute, null); + } + + public void visit(SetStatement set) { + visit(set, null); + } + + public void visit(ResetStatement reset) { + visit(reset, null); + } + + public void visit(Merge merge) { + visit(merge, null); + } + + public void visit(Commit commit) { + visit(commit, null); + } + + public void visit(Upsert upsert) { + visit(upsert, null); + } + + public void visit(UseStatement use) { + visit(use, null); + } + + public void visit(ShowStatement showStatement) { + visit(showStatement, null); + } + + public void visit(ShowColumnsStatement show) { + visit(show, null); + } + + public void visit(ShowIndexStatement show) { + visit(show, null); + } + + public void visit(ShowTablesStatement showTables) { + visit(showTables, null); + } + + public void visit(Block block) { + visit(block, null); + } + + public void visit(Comment comment) { + visit(comment, null); + } + + public void visit(DescribeStatement describe) { + visit(describe, null); + } + + public void visit(ExplainStatement explainStatement) { + visit(explainStatement, null); + } + + public void visit(DeclareStatement declareStatement) { + visit(declareStatement, null); + } + + public void visit(Grant grant) { + visit(grant, null); + } + + public void visit(CreateSchema aThis) { + visit(aThis, null); + } + + public void visit(CreateSequence createSequence) { + visit(createSequence, null); + } + + public void visit(AlterSequence alterSequence) { + visit(alterSequence, null); + } + + public void visit(CreateFunctionalStatement createFunctionalStatement) { + visit(createFunctionalStatement, null); + } + + public void visit(CreateSynonym createSynonym) { + visit(createSynonym, null); + } + + public void visit(Analyze analyze) { + visit(analyze, null); + } + + public void visit(SavepointStatement savepointStatement) { + visit(savepointStatement, null); + } + + public void visit(RollbackStatement rollbackStatement) { + visit(rollbackStatement, null); + } + + public void visit(AlterSession alterSession) { + visit(alterSession, null); + } + + public void visit(IfElseStatement ifElseStatement) { + visit(ifElseStatement, null); + } + + public void visit(RenameTableStatement renameTableStatement) { + visit(renameTableStatement, null); + } + + public void visit(PurgeStatement purgeStatement) { + visit(purgeStatement, null); + } + + public void visit(AlterSystemStatement alterSystemStatement) { + visit(alterSystemStatement, null); + } + + public void visit(UnsupportedStatement unsupportedStatement) { + visit(unsupportedStatement, null); + } + } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/UpdateValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/UpdateValidator.java index 735725126..aabfaf3fa 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/UpdateValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/UpdateValidator.java @@ -40,7 +40,7 @@ public void validate(Update update) { if (update.isUseSelect()) { validateOptionalExpressions(update.getColumns()); validateOptional(update.getSelect(), - e -> e.accept(getValidator(SelectValidator.class))); + e -> e.accept(getValidator(SelectValidator.class), null)); } else { validateOptionalExpressions(update.getColumns()); validateOptionalExpressions(update.getExpressions()); @@ -61,7 +61,7 @@ public void validate(Update update) { if (update.getReturningClause() != null) { SelectValidator v = getValidator(SelectValidator.class); - update.getReturningClause().forEach(c -> c.accept(v)); + update.getReturningClause().forEach(c -> c.accept(v, null)); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/UpsertValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/UpsertValidator.java index 21e9ebeeb..0d0fb9b1d 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/UpsertValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/UpsertValidator.java @@ -35,7 +35,7 @@ public void validate(Upsert upsert) { private void validateOptionalSelect(Select select) { if (select != null) { SelectValidator v = getValidator(SelectValidator.class); - select.accept(v); + select.accept(v, null); } } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 880804cd5..581999a38 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -67,11 +67,16 @@ import net.sf.jsqlparser.statement.upsert.*; import net.sf.jsqlparser.statement.merge.*; import net.sf.jsqlparser.statement.grant.*; import java.util.*; +import java.util.AbstractMap.SimpleEntry; + +import java.util.logging.Level; +import java.util.logging.Logger; /** * The parser generated by JavaCC */ public class CCJSqlParser extends AbstractJSqlParser { + public final static Logger LOGGER = Logger.getLogger(CCJSqlParser.class.getName()); public int bracketsCounter = 0; public int caseCounter = 0; public boolean interrupted = false; @@ -97,6 +102,25 @@ public class CCJSqlParser extends AbstractJSqlParser { public Node getASTRoot() { return jjtree.rootNode(); } + + private static class ObjectNames { + + private final List names; + private final List delimiters; + + public ObjectNames(List names, List delimiters) { + this.names = names; + this.delimiters = delimiters; + } + + public List getNames() { + return names; + } + + public List getDelimiters() { + return delimiters; + } + } } PARSER_END(CCJSqlParser) @@ -141,6 +165,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -194,8 +219,8 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | -| -| +| +| | | | @@ -211,7 +236,6 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | -| | | | @@ -223,6 +247,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| /* Salesforce SOQL */ | | | @@ -263,6 +288,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| /* Salesforce SOQL */ | | | @@ -302,9 +328,11 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | +| | | | @@ -349,7 +377,6 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | -| | | | @@ -367,6 +394,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -411,6 +439,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -459,7 +488,6 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | -| | | | @@ -485,6 +513,11 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | + +| +| +| +| (" ")+ ) > } TOKEN : /* Statement Separators */ @@ -509,6 +542,40 @@ TOKEN : /* Date/Time with time zones */ ()* ("(" ")")? ()* ( | ) (()+ )? ()+ "TIME" ()+ > } +TOKEN : /* Data Types */ +{ + | | | + | | | | | | + | | | | | + | | | | + | | | + ) > + + | <#TYPE_BIT: "BISTRING"> + | <#TYPE_BLOB: "BLOB" | "BYTEA" | | "VARBINARY" | > + | <#TYPE_BOOLEAN: "BOOLEAN" | "BOOL" > + | <#TYPE_ENUM: "ENUM" > + | <#TYPE_MAP: "MAP" > + | <#TYPE_DECIMAL: "DECIMAL" | "NUMBER" | "NUMERIC" > + | <#TYPE_TINYINT: "TINYINT" | "INT1" > + | <#TYPE_SMALLINT: "SMALLINT" | "INT2" | "SHORT" > + | <#TYPE_INTEGER: ( "INTEGER" | "INT" | "INT4" | | ) > + | <#TYPE_BIGINT: "BIGINT" | "INT8" | "LONG" > + | <#TYPE_HUGEINT: "HUGEINT" > + | <#TYPE_UTINYINT: "UTINYINT" > + | <#TYPE_USMALLINT: "USMALLINT" > + | <#TYPE_UINTEGER: "UINTEGER" > + | <#TYPE_UBIGINT: "UBIGINT" > + | <#TYPE_UHUGEINT: "UHUGEINT" > + | <#TYPE_REAL: "REAL" | "FLOAT4" | "FLOAT"> + | <#TYPE_DOUBLE: "DOUBLE" | "PRECISION" | "FLOAT8" | "FLOAT64"> + | <#TYPE_VARCHAR: "NVARCHAR" | "VARCHAR" | "NCHAR" | | "BPCHAR" | "STRING" | "TEXT" | | "VARYING"> + | <#TYPE_TIME: "TIMETZ" > + | <#TYPE_TIMESTAMP: "TIMESTAMP_NS" | "TIMESTAMP_MS" | "TIMESTAMP_S" > + + | <#TYPE_UUID: "UUID"> +} + TOKEN : /* Numeric Constants */ { < S_DOUBLE: (()? "." ( ["e","E"] (["+", "-"])? )? @@ -625,33 +692,47 @@ Statement Statement() #Statement: Expression condition; } { - try { - ( - condition=Condition() - ( stm = SingleStatement() | stm = Block() ) { ifElseStatement = new IfElseStatement(condition, stm); } - [ { ifElseStatement.setUsingSemicolonForIfStatement(true); } ] - [ LOOKAHEAD(2) - ( stm2 = SingleStatement() | stm2 = Block() ) { ifElseStatement.setElseStatement(stm2); } - [ { ifElseStatement.setUsingSemicolonForElseStatement(true); }] - ] - - ) - | - ( - ( stm = SingleStatement() | stm = Block() ) - [ ] - - ) - | - LOOKAHEAD( { getAsBoolean(Feature.allowUnsupportedStatements) } ) stm = UnsupportedStatement() - } catch (ParseException e) { - if (errorRecovery) { - parseErrors.add(e); - error_skipto(ST_SEMICOLON); - } - else - throw e; - } + ( + try { + ( + condition=Condition() + ( stm = SingleStatement() | stm = Block() ) { ifElseStatement = new IfElseStatement(condition, stm); } + [ LOOKAHEAD(2) + [ { ifElseStatement.setUsingSemicolonForIfStatement(true); } ] + ( stm2 = SingleStatement() | stm2 = Block() ) { ifElseStatement.setElseStatement(stm2); } + ] + + [ + LOOKAHEAD(2) + { if (stm2!=null) + ifElseStatement.setUsingSemicolonForElseStatement(true); + else if (ifElseStatement!=null) + ifElseStatement.setUsingSemicolonForIfStatement(true); + } + ] + ) + | + ( + (stm = SingleStatement() + | stm = Block()) + + ( | ) + ) + | + LOOKAHEAD( { stm==null && getAsBoolean(Feature.allowUnsupportedStatements) } ) stm = UnsupportedStatement() + } catch (ParseException ex) { + if ( getAsBoolean(Feature.allowUnsupportedStatements) ) { + stm = new UnsupportedStatement( stm.toString(), error_skipto(ST_SEMICOLON) ); + } else if ( errorRecovery ) { + parseErrors.add(ex); + error_skipto(ST_SEMICOLON); + stm = null; + } else { + throw ex; + } + } + + ) { return ifElseStatement!=null ? ifElseStatement : stm; @@ -664,7 +745,6 @@ Statement SingleStatement() : List with = null; } { - try { ( LOOKAHEAD(3) ( [ LOOKAHEAD(2) with=WithList() ] @@ -731,14 +811,6 @@ Statement SingleStatement() : stm = PurgeStatement() ) { return stm; } - } catch (ParseException e) { - if (errorRecovery) { - parseErrors.add(e); - error_skipto(ST_SEMICOLON); - return null; - } else - throw e; - } } Block Block() #Block : { @@ -750,7 +822,6 @@ Block Block() #Block : { { ()* - try { ( stm = SingleStatement() | stm = Block() @@ -768,14 +839,6 @@ Block Block() #Block : { { list.add(stm); } ) )* - } catch (ParseException e) { - if (errorRecovery) { - parseErrors.add(e); - error_skipto(ST_SEMICOLON); - } else { - throw e; - } - } { stmts.setStatements(list); @@ -796,37 +859,62 @@ Statements Statements() #Statements: { Expression condition; } { - ()* - try { + ( ( - ( - condition=Condition() - ( stm = SingleStatement() | stm = Block() ) { ifElseStatement = new IfElseStatement(condition, stm); } - [ LOOKAHEAD(2) - [ { ifElseStatement.setUsingSemicolonForIfStatement(true); } ] - ( stm2 = SingleStatement() | stm2 = Block() ) { ifElseStatement.setElseStatement(stm2); } - ] + ( )* - { stmts.add( ifElseStatement ); } - ) - | - ( - stm = SingleStatement() - | stm = Block() + // todo: allow also first statement to be an `UnsupportedStatement` + try { + ( + condition=Condition() + ( stm = SingleStatement() | stm = Block() ) { ifElseStatement = new IfElseStatement(condition, stm); } + [ LOOKAHEAD(2) + [ { ifElseStatement.setUsingSemicolonForIfStatement(true); } ] + ( stm2 = SingleStatement() | stm2 = Block() ) { ifElseStatement.setElseStatement(stm2); } + ] + + { stmts.add( ifElseStatement ); } + + [ + LOOKAHEAD(2) + { if (stm2!=null) + ifElseStatement.setUsingSemicolonForElseStatement(true); + else if (ifElseStatement!=null) + ifElseStatement.setUsingSemicolonForIfStatement(true); + } + ] + ) + | + ( + (stm = SingleStatement() + | stm = Block()) + + ( | ) + ) + { + stmts.add(stm); stm=null; + } + + } catch (ParseException ex) { + if ( getAsBoolean(Feature.allowUnsupportedStatements) ) { + UnsupportedStatement unsupportedStatement = new UnsupportedStatement( stm!=null ? stm.toString() : "", error_skipto(ST_SEMICOLON) ); + if (!unsupportedStatement.isEmpty()) { + stmts.add( unsupportedStatement ); + } + } else if ( errorRecovery ) { + parseErrors.add(ex); + error_skipto(ST_SEMICOLON); + stmts.add( null ); + } else { + throw ex; + } + } - [ LOOKAHEAD(2) ] - ) { stmts.add(stm); } - | - LOOKAHEAD( { getAsBoolean(Feature.allowUnsupportedStatements) } ) stm = UnsupportedStatement() - { if ( !((UnsupportedStatement) stm).isEmpty() ) stmts.add(stm); } ) ( - { if (stm2!=null) - ifElseStatement.setUsingSemicolonForElseStatement(true); - else if (ifElseStatement!=null) - ifElseStatement.setUsingSemicolonForIfStatement(true); } - [ + ( )* + try { ( condition=Condition() ( stm = SingleStatement() | stm = Block() ) { ifElseStatement = new IfElseStatement(condition, stm); } @@ -838,40 +926,63 @@ Statements Statements() #Statements: { { stmts.add( ifElseStatement ); } ) | - ( + ( stm = SingleStatement() | stm = Block() + ) { stmts.add(stm); stm=null; } + } catch (ParseException ex) { + if ( getAsBoolean(Feature.allowUnsupportedStatements) ) { + UnsupportedStatement unsupportedStatement = new UnsupportedStatement( stm!=null ? stm.toString() : "" , error_skipto(ST_SEMICOLON) ); + if (!unsupportedStatement.isEmpty()) { + stmts.add( unsupportedStatement ); + } + } else if ( errorRecovery ) { + parseErrors.add(ex); + error_skipto(ST_SEMICOLON); + stmts.add( null ); + } else { + throw ex; + } + } + + ( LOOKAHEAD(2) { if (stm2!=null) + ifElseStatement.setUsingSemicolonForElseStatement(true); + else if (ifElseStatement!=null) + ifElseStatement.setUsingSemicolonForIfStatement(true); + } )* - [ LOOKAHEAD(2) ] - ) { stmts.add(stm); } - | - // For any reason, we can't LOOKAHEAD( { getAsBoolean(Feature.allowUnsupportedStatements) } ) here - // As it will result in a Stack Overflow - stm = UnsupportedStatement() - { if ( !((UnsupportedStatement) stm).isEmpty() ) stmts.add(stm); } - ] )* - - } catch (ParseException e) { - if (errorRecovery) { - parseErrors.add(e); - error_skipto(ST_SEMICOLON); - } else { - throw e; - } - } + + [ + LOOKAHEAD( { getAsBoolean(Feature.allowUnsupportedStatements) } ) + stm = UnsupportedStatement() + { + if (!( (UnsupportedStatement) stm).isEmpty()) { + stmts.add( stm ); + } + } + ] + + )* + + { return stmts; } } JAVACODE -void error_skipto(int kind) { +List error_skipto(int kind) { + ArrayList tokenImages = new ArrayList(); ParseException e = generateParseException(); Token t; do { t = getNextToken(); + if (t.kind != kind && t.kind != EOF) { + tokenImages.add(t.image); + } } while (t.kind != kind && t.kind != EOF); + return tokenImages; } DeclareStatement Declare(): { @@ -1374,7 +1485,7 @@ Update Update( List with ): [ fromItem=FromItem() - [ joins=JoinsList() ] ] + [ LOOKAHEAD(2) joins=JoinsList() ] ] [ where=WhereClause() { update.setWhere(where); } ] @@ -1678,7 +1789,7 @@ Delete Delete( List with ): [ outputClause = OutputClause() {delete.setOutputClause(outputClause); } ] | ) { hasFrom = true; }] - [ LOOKAHEAD(3) table=TableWithAlias() [ joins=JoinsList() ] ] + [ LOOKAHEAD(3) table=TableWithAlias() [ LOOKAHEAD(2) joins=JoinsList() ] ] [ usingTable=TableWithAlias() { usingList.add(usingTable); } ("," usingTable=TableWithAlias() { usingList.add(usingTable); } )*] [where=WhereClause() { delete.setWhere(where); } ] @@ -1763,7 +1874,7 @@ MergeOperation MergeUpdateClause(Expression predicate) : { { updateSets = UpdateSets() { mu.setUpdateSets(updateSets); } [ condition = Expression() { mu.setWhereCondition(condition); }] - [ condition = Expression() { mu.setDeleteWhereCondition(condition); } ] + [ LOOKAHEAD(2) condition = Expression() { mu.setDeleteWhereCondition(condition); } ] { return mu; } } @@ -1794,33 +1905,38 @@ MergeOperation MergeWhenNotMatched() : { { return mi; } } -List RelObjectNameList() : { +ObjectNames RelObjectNames() : { String token = null; + Token delimiter = null; List data = new ArrayList(); + List delimiters = new ArrayList(); } { token = RelObjectNameExt() { data.add(token); } - ( LOOKAHEAD (2) ("." | ":") ("." { data.add(null); })* token = RelObjectNameExt2() { data.add(token); } ) * + ( + LOOKAHEAD (2) ( delimiter = "." | delimiter = ":" ) { delimiters.add(delimiter.image); } (( delimiter = "." | delimiter = ":" ) { data.add(null); delimiters.add(delimiter.image); })* + token = RelObjectNameExt2() { data.add(token); } + ) * - { return data; } + { return new ObjectNames(data, delimiters); } } // See: http://technet.microsoft.com/en-us/library/ms187879%28v=sql.105%29.aspx Column Column() #Column : { - List data = new ArrayList(); + ObjectNames data = null; ArrayConstructor arrayConstructor = null; Token tk = null; } { - data = RelObjectNameList() + data = RelObjectNames() [ LOOKAHEAD(2) tk= ] // @todo: we better should return a SEQUENCE instead of a COLUMN - [ "." { data.add("nextval"); } ] + [ "." { data.getNames().add("nextval"); } ] [ LOOKAHEAD(2) arrayConstructor = ArrayConstructor(false) ] { - Column col = new Column(data); + Column col = new Column(data.getNames(), data.getDelimiters()); if (tk != null) { col.withCommentText(tk.image); } if (arrayConstructor!=null) { col.setArrayConstructor(arrayConstructor); @@ -1841,8 +1957,8 @@ The following tokens are allowed as Names for Schema, Table, Column and Aliases String RelObjectNameWithoutValue() : { Token tk = null; } { - ( tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DDL" | tk="DECLARE" | tk="DEFAULT" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GUARD" | tk="HASH" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LOOP" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAXVALUE" | tk="MEMBER" | tk="MERGE" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRECISION" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) + ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DDL" | tk="DECLARE" | tk="DEFAULT" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GUARD" | tk="HASH" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LOOP" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRECISION" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -1884,7 +2000,7 @@ String RelObjectNameExt(): } { ( result=RelObjectName() | tk= | tk= | tk= | tk= | tk= | tk= - | tk= | tk= | tk= | tk= | tk= + | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= @@ -1912,13 +2028,13 @@ String RelObjectNameExt2(): Table Table() #TableName : { //String serverName = null, databaseName = null, schemaName = null, tableName = null; - List data = new ArrayList(); + ObjectNames data = null; } { - data = RelObjectNameList() + data = RelObjectNames() { - Table table = new Table(data); + Table table = new Table(data.getNames()); linkAST(table,jjtThis); return table; } @@ -2255,6 +2371,11 @@ PlainSelect PlainSelect() #PlainSelect: [ LOOKAHEAD(2) first = First() { plainSelect.setFirst(first); } ] + // Redshift allows TOP before DISTINCT + // https://docs.aws.amazon.com/redshift/latest/dg/r_SELECT_list.html + // @Todo: reflect the order when de-parsing + [ LOOKAHEAD(2) top = Top() { plainSelect.setTop(top); } ] + [ LOOKAHEAD(2) ( @@ -2274,6 +2395,15 @@ PlainSelect PlainSelect() #PlainSelect: ) ] + [ + + ( + { plainSelect.setBigQuerySelectQualifier( PlainSelect.BigQuerySelectQualifier.AS_STRUCT ); } + | + { plainSelect.setBigQuerySelectQualifier( PlainSelect.BigQuerySelectQualifier.AS_VALUE ); } + ) + ] + [ LOOKAHEAD(2) top = Top() { plainSelect.setTop(top); } ] selectItems=SelectItemsList() @@ -2436,7 +2566,7 @@ WithItem WithItem() #WithItem: Select select; } { - [ { withItem.setRecursive(true); } ] + [ LOOKAHEAD(2) { withItem.setRecursive(true); } ] name=RelObjectName() { withItem.setAlias( new Alias( name, false)); } [ "(" selectItems=SelectItemsList() ")" { withItem.setWithItemList(selectItems); } ] select = ParenthesedSelect() { withItem.setSelect(select); } @@ -2445,13 +2575,30 @@ WithItem WithItem() #WithItem: } } +List> ColumnSelectItemsList(): +{ + List> selectItemsList = null; + SelectItem selectItem = null; +} +{ + selectItem=SelectItem() { selectItemsList = new ArrayList>(); selectItemsList.add(selectItem); } + ( + LOOKAHEAD(2) "," selectItem=SelectItem() + { + selectItemsList.add(selectItem); + } + )* + + { return selectItemsList; } +} + List> SelectItemsList(): { - List> selectItemsList = new ArrayList>(); + List> selectItemsList = null; SelectItem selectItem = null; } { - selectItem=SelectItem() { selectItemsList.add(selectItem); } + selectItem=SelectItem() { selectItemsList = new ArrayList>(); selectItemsList.add(selectItem); } ( LOOKAHEAD(2) "," selectItem=SelectItem() { @@ -2463,7 +2610,7 @@ List> SelectItemsList(): } -SelectItem SelectItem() #SelectItem: +SelectItem SelectItem() #SelectItem: { Expression expression; Alias alias = null; @@ -2476,7 +2623,7 @@ SelectItem SelectItem() #SelectItem: | LOOKAHEAD(AllTableColumns()) expression = AllTableColumns() | - LOOKAHEAD( Condition() ) expression = Condition() + LOOKAHEAD( 3 ) expression = XorExpression() | LOOKAHEAD( 3 ) expression = ConcatExpression() | @@ -2484,7 +2631,7 @@ SelectItem SelectItem() #SelectItem: ) [ LOOKAHEAD(2) alias=Alias() ] { - SelectItem selectItem = new SelectItem(expression, alias); + SelectItem selectItem = new SelectItem(expression, alias); linkAST(selectItem,jjtThis); return selectItem; } @@ -2493,15 +2640,17 @@ SelectItem SelectItem() #SelectItem: AllColumns AllColumns(): { ParenthesedExpressionList exceptColumns = null; - List> replaceExpressions = null; + List> replaceExpressions = null; + String exceptKeyword=null; + Token tk; } { "*" - [ LOOKAHEAD(2) exceptColumns = ParenthesedColumnList() ] - [ LOOKAHEAD(2) "(" replaceExpressions = SelectItemsList() ")" ] + [ LOOKAHEAD(2) ( tk= | tk= ) exceptColumns = ParenthesedColumnList() { exceptKeyword=tk.image; } ] + [ LOOKAHEAD(2) "(" replaceExpressions = ColumnSelectItemsList() ")" ] { - return new AllColumns(exceptColumns, replaceExpressions); + return new AllColumns(exceptColumns, replaceExpressions, exceptKeyword); } } @@ -2519,7 +2668,7 @@ AllTableColumns AllTableColumns(): } Alias Alias(): -{ String name = null; +{ String name = ""; Token token = null; boolean useAs = false; Alias alias; @@ -2527,15 +2676,41 @@ Alias Alias(): ColDataType colDataType = null; } { - [ { useAs = true; } ] - ( name=RelObjectNameWithoutStart() | token= { name=token.image; } ) - { alias = new Alias(name,useAs); } + ( + LOOKAHEAD(3) ( + // Aliases with AS and Columns, but optional identifier: + // SELECT fun(x) AS (a,b,c) + // SELECT fun(x) AS T(a,b,c) + + [ LOOKAHEAD(2) name=RelObjectNameWithoutStart() ] + { alias = new Alias(name, true ); } + + "(" { List list = new ArrayList(); } + colname = RelObjectName() [ colDataType = ColDataType() ] { list.add(new Alias.AliasColumn(colname, colDataType)); } + ( + "," { colDataType=null; } colname = RelObjectName() [ colDataType = ColDataType()] { list.add(new Alias.AliasColumn(colname, colDataType)); } + )* + ")" { alias.setAliasColumns(list); } + + ) + | + ( + // Aliases with identifier but optional AS and Columns: + // SELECT fun(x) AS T + // SELECT fun(x) T + // SELECT fun(x) T(a,b,c) - [ LOOKAHEAD(2) "(" { List list = new ArrayList(); } - colname = RelObjectName() [ colDataType = ColDataType() ] { list.add(new Alias.AliasColumn(colname, colDataType)); } - ("," { colDataType=null; } colname = RelObjectName() [ colDataType = ColDataType()] { list.add(new Alias.AliasColumn(colname, colDataType)); } )* - ")" { alias.setAliasColumns(list); } ] + [ { useAs = true; } ] + ( name=RelObjectNameWithoutStart() | token= { name=token.image; } ) + { alias = new Alias(name,useAs); } + [ LOOKAHEAD(2) "(" { List list = new ArrayList(); } + colname = RelObjectName() [ colDataType = ColDataType() ] { list.add(new Alias.AliasColumn(colname, colDataType)); } + ("," { colDataType=null; } colname = RelObjectName() [ colDataType = ColDataType()] { list.add(new Alias.AliasColumn(colname, colDataType)); } )* + ")" { alias.setAliasColumns(list); } ] + + ) + ) { return alias; } } @@ -2623,7 +2798,7 @@ List> PivotFunctionItems(): { return functionItems; } } -SelectItem ExpressionListItem(): +SelectItem> ExpressionListItem(): { ExpressionList expressionList; Alias alias = null; @@ -2631,13 +2806,13 @@ SelectItem ExpressionListItem(): { expressionList=ParenthesedExpressionList() [ alias=Alias() ] - { return new SelectItem(expressionList, alias); } + { return new SelectItem>(expressionList, alias); } } -List> PivotMultiInItems(): +List>> PivotMultiInItems(): { - List> retval = new ArrayList>(); - SelectItem item; + List>> retval = new ArrayList>>(); + SelectItem> item; } { item = ExpressionListItem() {retval.add(item);} @@ -2651,7 +2826,7 @@ Pivot Pivot(): List> functionItems; ExpressionList forColumns; List> singleInItems = null; - List> multiInItems = null; + List>> multiInItems = null; Alias alias = null; } { @@ -2679,7 +2854,7 @@ PivotXml PivotXml(): List> functionItems; ExpressionList forColumns; List> singleInItems = null; - List> multiInItems = null; + List>> multiInItems = null; Select inSelect = null; } { @@ -2761,7 +2936,7 @@ FromItem ParenthesedFromItem(): } } -FromItem FromItem(): +FromItem FromItem() #FromItem: { FromItem fromItem = null; FromItem fromItem2 = null; @@ -2775,6 +2950,8 @@ FromItem FromItem(): } { ( + LOOKAHEAD(3) fromItem = Values() + | LOOKAHEAD( TableFunction() ) fromItem=TableFunction() | LOOKAHEAD(3) fromItem=Table() @@ -2809,6 +2986,7 @@ FromItem FromItem(): ) ] { + linkAST(fromItem,jjtThis); return fromItem; } } @@ -2902,11 +3080,11 @@ Join JoinerExpression() #JoinerExpression: ) ) ] - { - linkAST(join,jjtThis); - join.setFromItem(right); - return join; -} + { + linkAST(join,jjtThis); + join.setFromItem(right); + return join; + } } @@ -3175,14 +3353,13 @@ Limit PlainLimit() #PlainLimit: { // mysql-postgresql-> LIMIT (row_count | ALL | NULL) - ( - ( + ( LOOKAHEAD(3) rowCountExpression = ParenthesedSelect() | rowCountExpression = Expression() - ) { limit.setRowCount(rowCountExpression); } - ) + ) { + limit.setRowCount(rowCountExpression); linkAST(limit,jjtThis); return limit; } @@ -3307,7 +3484,7 @@ OptimizeFor OptimizeFor(): } // according to http://technet.microsoft.com/en-us/library/ms189463.aspx -Top Top(): +Top Top() #Top: { Top top = new Top(); Token token = null; @@ -3317,23 +3494,25 @@ Top Top(): { ( - token= { top.setExpression(new LongValue(token.image)); } - | - jdbc = JdbcParameter() { top.setExpression(jdbc); } - /*"?" { top.setExpression(new JdbcParameter(++jdbcParameterIndex, false)); } [ LOOKAHEAD(2) token = { ((JdbcParameter)(top.getExpression())).setUseFixedIndex(true); ((JdbcParameter)(top.getExpression())).setIndex(Integer.valueOf(token.image)); } ]*/ - | - ":" { top.setExpression(new JdbcNamedParameter()); } [ LOOKAHEAD(2) token = { ((JdbcNamedParameter)top.getExpression()).setName(token.image); } ] - | - "(" + token= { top.setExpression(new LongValue(token.image)); } + | + jdbc = JdbcParameter() { top.setExpression(jdbc); } + | + ":" { top.setExpression(new JdbcNamedParameter()); } + [ LOOKAHEAD(2) token = { ((JdbcNamedParameter)top.getExpression()).setName(token.image); } ] + | + "(" expr=AdditiveExpression() { top.setExpression(expr); top.setParenthesis(true); } ")" - ) [ LOOKAHEAD(2) { top.setPercentage(true); } ] - [ LOOKAHEAD(2) { top.setWithTies(true); }] + ) + [ LOOKAHEAD(2) { top.setPercentage(true); } ] + [ LOOKAHEAD(2) { top.setWithTies(true); } ] { + linkAST(top,jjtThis); return top; } } @@ -3461,7 +3640,7 @@ Expression AndExpression() : left=Condition() | [ { not=true; } | "!" { not=true; exclamationMarkNot=true; } ] - "(" left=XorExpression() ")" {left = new Parenthesis(left); if (not) { left = new NotExpression(left, exclamationMarkNot); not = false; } } + "(" left=XorExpression() ")" {left = new ParenthesedExpressionList(left); if (not) { left = new NotExpression(left, exclamationMarkNot); not = false; } } ) { result = left; } @@ -3473,7 +3652,7 @@ Expression AndExpression() : right=Condition() | [ { not=true; } | "!" { not=true; exclamationMarkNot=true; } ] - "(" right=XorExpression() ")" {right = new Parenthesis(right); if (not) { right = new NotExpression(right, exclamationMarkNot); not = false; } } + "(" right=XorExpression() ")" {right = new ParenthesedExpressionList(right); if (not) { right = new NotExpression(right, exclamationMarkNot); not = false; } } ) { result = new AndExpression(left, right); @@ -3566,7 +3745,7 @@ Expression RegularCondition() #RegularCondition: ) ( LOOKAHEAD(2) rightExpression=ComparisonItem() { oraclePrior = EqualsTo.ORACLE_PRIOR_END; } - | rightExpression=ComparisonItem() ) + | rightExpression=ComparisonItem() ) [ LOOKAHEAD(2) "(" "+" ")" { oracleJoin=EqualsTo.ORACLE_JOIN_LEFT; } ] @@ -3602,6 +3781,10 @@ Expression SQLCondition(): [ LOOKAHEAD(2) ( ( + LOOKAHEAD(ExcludesExpression()) result=ExcludesExpression(left) + | + LOOKAHEAD(IncludesExpression()) result=IncludesExpression(left) + | LOOKAHEAD(2) result=Between(left) | result = MemberOfExpression(left) @@ -3655,6 +3838,36 @@ Expression InExpression() #InExpression : } } +Expression IncludesExpression(Expression leftExpression) #IncludesExpression : +{ + Token token; + Expression rightExpression; +} +{ + (rightExpression = ParenthesedExpressionList()) + { + IncludesExpression includesExpression = new IncludesExpression(leftExpression, rightExpression); + + linkAST(includesExpression,jjtThis); + return includesExpression; + } +} + +Expression ExcludesExpression(Expression leftExpression) #ExcludesExpression : +{ + Token token; + Expression rightExpression; +} +{ + (rightExpression = ParenthesedExpressionList()) + { + ExcludesExpression excludesExpression = new ExcludesExpression(leftExpression, rightExpression); + + linkAST(excludesExpression,jjtThis); + return excludesExpression; + } +} + Expression Between(Expression leftExpression) : { Between result = new Between(); @@ -3703,6 +3916,7 @@ Expression LikeExpression(Expression leftExpression) #LikeExpression: | token = | token = | token = + | token = ) { result.setLikeKeyWord( LikeExpression.KeyWord.from(token.image)); } [ LOOKAHEAD(2) {result.setUseBinary(true); } ] rightExpression=SimpleExpression() @@ -3872,7 +4086,7 @@ ExpressionList SimpleExpressionList(): } { expr=SimpleExpression() { expressions.add(expr); } - ( LOOKAHEAD(2, {!interrupted} ) "," expr=SimpleExpression() { expressions.add(expr); } )* + ( LOOKAHEAD(2, {!interrupted} ) "," ( LOOKAHEAD(2) expr=LambdaExpression() | expr=SimpleExpression()) { expressions.add(expr); } )* { return expressions; } @@ -3921,6 +4135,7 @@ ExpressionList ComplexExpressionList(): LOOKAHEAD(2, {!interrupted}) "," ( LOOKAHEAD(2) expr=OracleNamedFunctionParameter() + | LOOKAHEAD(2) expr=LambdaExpression() | expr=Expression() ) { expressions.add(expr); } )* @@ -3984,7 +4199,7 @@ Expression ComparisonItem() : } { ( - LOOKAHEAD(3) retval=AnyComparisonExpression() + LOOKAHEAD( AnyComparisonExpression() ) retval=AnyComparisonExpression() | LOOKAHEAD(3) retval=SimpleExpression() | LOOKAHEAD(3) retval=ParenthesedExpressionList() | LOOKAHEAD(3) retval=RowConstructor() @@ -4003,11 +4218,14 @@ Expression AnyComparisonExpression() : } { ( - { anyType = AnyType.ANY; } - | { anyType = AnyType.SOME; } - | { anyType = AnyType.ALL; } + ( + { anyType = AnyType.ANY; } + | { anyType = AnyType.SOME; } + | { anyType = AnyType.ALL; } + ) + + select = ParenthesedSelect() ) - select = Select() { return new AnyComparisonExpression(anyType, select); } @@ -4190,7 +4408,7 @@ Expression ArrayExpression(Expression obj): { "]" { expr = new ArrayExpression(obj, idxExpr, startExpr, stopExpr); } ( - "[" + LOOKAHEAD(2) "[" [LOOKAHEAD(3) idxExpr = SimpleExpression()] [ (":" { startExpr=idxExpr; idxExpr=null; }) @@ -4227,6 +4445,10 @@ Expression PrimaryExpression() #PrimaryExpression: | LOOKAHEAD(3, {!interrupted}) retval=CaseWhenExpression() + | LOOKAHEAD(2, {!interrupted}) retval=CharacterPrimary() + + | LOOKAHEAD( ImplicitCast(), {!interrupted}) retval=ImplicitCast() + | retval = JdbcParameter() | LOOKAHEAD(2) retval =JdbcNamedParameter() @@ -4235,7 +4457,7 @@ Expression PrimaryExpression() #PrimaryExpression: | LOOKAHEAD(2, {!interrupted}) retval=NumericBind() - | LOOKAHEAD(3, {!interrupted}) retval=ExtractExpression() + | LOOKAHEAD( ExtractExpression() , {!interrupted}) retval=ExtractExpression() | LOOKAHEAD(3) retval=MySQLGroupConcat() @@ -4247,7 +4469,7 @@ Expression PrimaryExpression() #PrimaryExpression: | LOOKAHEAD(3, { !interrupted}) retval = FullTextSearch() - | LOOKAHEAD(Function(), { !interrupted}) retval=Function() [ LOOKAHEAD(2) retval = AnalyticExpression( (Function) retval ) ] + | LOOKAHEAD( Function(), { !interrupted}) retval=Function() [ LOOKAHEAD(2) retval = AnalyticExpression( (Function) retval ) ] | LOOKAHEAD(2, {!interrupted}) retval = IntervalExpression() { dateExpressionAllowed = false; } @@ -4259,14 +4481,17 @@ Expression PrimaryExpression() #PrimaryExpression: | LOOKAHEAD(2, {!interrupted}) retval=CastExpression() - | LOOKAHEAD(2, {!interrupted}) retval=CharacterPrimary() // support timestamp expressions | LOOKAHEAD(2, {!interrupted}) (token= | token=) { retval = new TimeKeyExpression(token.image); } | LOOKAHEAD(2, {!interrupted}) retval=DateTimeLiteralExpression() - | LOOKAHEAD(2, {!interrupted}) retval=ArrayConstructor(true) + | LOOKAHEAD( 3 , {!interrupted}) retval=StructType() + + | LOOKAHEAD(3, {!interrupted}) retval=ArrayConstructor(true) + + | LOOKAHEAD(3, {!interrupted}) retval=ArrayConstructor(false) | LOOKAHEAD(2, {!interrupted}) retval = NextValExpression() @@ -4291,7 +4516,7 @@ Expression PrimaryExpression() #PrimaryExpression: list=ParenthesedExpressionList() { if (list.size() == 1) { - retval = new Parenthesis( (Expression) list.getExpressions().get(0)); + retval = new ParenthesedExpressionList( (Expression) list.getExpressions().get(0)); } else { retval = list; } @@ -4308,7 +4533,7 @@ Expression PrimaryExpression() #PrimaryExpression: LOOKAHEAD(2, { dateExpressionAllowed } ) retval = IntervalExpressionWithoutInterval(retval) ] - [ retval = ArrayExpression(retval) ] + [ LOOKAHEAD(2) retval = ArrayExpression(retval) ] ( "::" type=ColDataType() { castExpr = new CastExpression(); @@ -4369,13 +4594,13 @@ ConnectByRootOperator ConnectByRootOperator() #ConnectByRootOperator: { } NextValExpression NextValExpression() : { - List data = new ArrayList(); + ObjectNames data = null; Token token; } { - token= data = RelObjectNameList() + token= data = RelObjectNames() { - return new NextValExpression(data, token.image); + return new NextValExpression(data.getNames(), token.image); } } @@ -4394,15 +4619,16 @@ JdbcNamedParameter JdbcNamedParameter() : { } OracleNamedFunctionParameter OracleNamedFunctionParameter() : { - String name; + Token token = null; + String name = null; Expression expression; } { - name=RelObjectNameExt2() + ( name=RelObjectNameExt2() | token= ) expression=Expression() { - return new OracleNamedFunctionParameter(name, expression); + return new OracleNamedFunctionParameter(name != null ? name : token.image, expression); } } @@ -4438,7 +4664,7 @@ DateTimeLiteralExpression DateTimeLiteralExpression() : { } { t= { expr.setType(DateTimeLiteralExpression.DateTime.from(t.image)); } - t= { expr.setValue(t.image); return expr; } + ( t= | t= ) { expr.setValue(t.image); return expr; } } RangeExpression RangeExpression(Expression startExpression): @@ -4478,6 +4704,86 @@ ArrayConstructor ArrayConstructor(boolean arrayKeyword) : { { return array; } } +List> StructParameters(): +{ + String parameterName = ""; + ColDataType parameterType = null; + AbstractMap.SimpleEntry parameter = null; + List> parameters = new ArrayList>(); +} +{ + [ LOOKAHEAD(2) parameterName = RelObjectName() ] + parameterType = ColDataType() + { + parameters.add( new AbstractMap.SimpleEntry(parameterName, parameterType) ); + } + + ( + "," { parameterName=""; } + + [ LOOKAHEAD(2) parameterName = RelObjectName() ] + parameterType = ColDataType() + { + parameters.add( new AbstractMap.SimpleEntry(parameterName, parameterType) ); + } + )* + + { + return parameters; + } +} + +StructType StructType() #StruckType: +{ + StructType.Dialect dialect = StructType.Dialect.BIG_QUERY; + Token tk1; + String keyword = ""; + List> parameters = null; + List> arguments = null; + String id = null; + Expression expression = null; + StructType type; +} +{ + ( + LOOKAHEAD(4) ( + tk1= { keyword = tk1.image; } + "<" parameters = StructParameters() ">" + "(" { System.out.println("found arguments!"); } arguments = SelectItemsList() ")" + ) + | + ( + tk1= { keyword = tk1.image; } + "(" arguments = SelectItemsList() ")" + ) + | + ( + { arguments= new ArrayList>(); dialect = StructType.Dialect.DUCKDB;} + + id = RelObjectName() expression = Expression() { arguments.add( new SelectItem( expression, id) ); } + + ( + "," + id = RelObjectName() expression = Expression() { arguments.add( new SelectItem( expression, id) ); } + )* + + + ( + LOOKAHEAD(2) "::" "(" parameters = StructParameters() ")" + )* + ) + + // don't parse this as an Struct, but rather use an Expressionlist + // | + // arguments = StructArguments() + ) + { + type = new StructType(dialect, keyword, parameters, arguments); + linkAST(type,jjtThis); + return type; + } +} + Expression ParenthesedExpression(): { Expression expression; @@ -4485,7 +4791,7 @@ Expression ParenthesedExpression(): { "(" expression = PrimaryExpression() ")" { - return new Parenthesis(expression); + return new ParenthesedExpressionList(expression); } } @@ -4806,7 +5112,6 @@ void windowFun(AnalyticExpression retval):{ WindowDefinition winDef; } { ( - [ { retval.setIgnoreNullsOutside(true); } ] {retval.setType(AnalyticType.OVER);} | {retval.setType(AnalyticType.WITHIN_GROUP);} @@ -4857,8 +5162,13 @@ AnalyticExpression AnalyticExpression(Function function) : Expression filter = null; } { - (( "(" {retval.setType(AnalyticType.FILTER_ONLY);} filter = Expression() ")" [ LOOKAHEAD(2) windowFun(retval) ] ) - | windowFun(retval)) + ( + ( + "(" {retval.setType(AnalyticType.FILTER_ONLY);} filter = Expression() ")" + [ LOOKAHEAD(2) windowFun(retval) ] + ) + | windowFun(retval) + ) { retval.setFilterExpression(filter); return retval; @@ -4933,6 +5243,30 @@ ExtractExpression ExtractExpression() : } } +CastExpression ImplicitCast() #ImplicitCast: +{ + ColDataType colDataType; + Token tk1; + Token tk2; + + int precision = -1; + int scale = -1; +} +{ + colDataType = DataType() + ( + tk2 = + | + tk2 = + | + tk2 = + ) + { + CastExpression castExpression = new CastExpression(colDataType, tk2.image); + return castExpression; + } +} + CastExpression CastExpression(): { Token keyword; @@ -4941,6 +5275,7 @@ CastExpression CastExpression(): ColDataType type; Expression expression = null; boolean useCastKeyword; + Token formatCharLiteral; } { ( @@ -4969,6 +5304,11 @@ CastExpression CastExpression(): | type=ColDataType() { retval.setColDataType(type); } ) + + // BigQuery FORMAT clause + // https://cloud.google.com/bigquery/docs/reference/standard-sql/conversion_functions#cast_as_date + [ formatCharLiteral= { retval.setFormat(formatCharLiteral.image); } ] + ")" { @@ -5055,7 +5395,7 @@ EqualsTo VariableExpression(): { Execute Execute(): { Token token; - List funcName; + ObjectNames funcName; ExpressionList expressionList = null; Execute execute = new Execute(); List namedExprList; @@ -5066,10 +5406,10 @@ Execute Execute(): { | { execute.setExecType(Execute.ExecType.EXECUTE); } | { execute.setExecType(Execute.ExecType.CALL); } ) - funcName=RelObjectNameList() { execute.setName(funcName); } + funcName=RelObjectNames() { execute.setName(funcName.getNames()); } ( - expressionList=ExpressionList() { execute.setExprList(expressionList); } + LOOKAHEAD(2) expressionList=ExpressionList() { execute.setExprList(expressionList); } )? { @@ -5111,6 +5451,35 @@ FullTextSearch FullTextSearch() : { } } +LambdaExpression LambdaExpression() #LambdaExpression: +{ + String s; + ArrayList identifiers = new ArrayList(); + Expression expression; + LambdaExpression lambdaExpression; +} +{ +// wip, right now the Grammar works but collides with Multi Value Lists +// ( +// LOOKAHEAD(3) "(" +// s = RelObjectName() { identifiers.add(s); } +// ( "," s = RelObjectName() { identifiers.add(s); } )* +// ")" +// ) +// | + ( + s = RelObjectName() { identifiers.add(s); } + ) + + "->" + expression = Expression() + { + lambdaExpression = new LambdaExpression(identifiers, expression); + linkAST(lambdaExpression,jjtThis); + return lambdaExpression; + } +} + Function Function() #Function: { Function function; @@ -5159,13 +5528,13 @@ Function SpecialStringFunctionWithNamedParameters() : Function SimpleFunction(): { Function function = new Function(); - List name; + ObjectNames name; Expression expr=null; Expression attributeExpression = null; Column attributeColumn = null; } { - name = RelObjectNameList() + name = RelObjectNames() "(" [ ( @@ -5184,7 +5553,7 @@ Function SimpleFunction(): ] ")" { - function.setName(name); + function.setName(name.getNames()); if (expr!=null) { function.setParameters(expr); } @@ -5207,18 +5576,20 @@ Function SimpleFunction(): Function InternalFunction(boolean escaped): { + Token prefixToken = null; Function retval = new Function(); - List funcName; + ObjectNames funcName; ExpressionList expressionList = null; KeepExpression keep = null; Expression expr = null; Expression attributeExpression = null; Column attributeColumn = null; List orderByList; - boolean ignoreNulls = false; + Limit limit; } { - funcName = RelObjectNameList() + [ LOOKAHEAD(2) prefixToken = ] + funcName = RelObjectNames() { if (prefixToken!=null) funcName.getNames().add(0, prefixToken.image ); } "(" [ @@ -5235,9 +5606,32 @@ Function InternalFunction(boolean escaped): expr = Select() { expressionList = new ExpressionList(expr); } ) ] - [ {retval.setIgnoreNulls(true); }] + + [ + ( + expr = Expression() { retval.setHavingClause( "MIN", expr ); } + | + expr = Expression() { retval.setHavingClause( "MAX", expr ); } + ) + ] + + [ + ( + { retval.setNullHandling(Function.NullHandling.IGNORE_NULLS); } + ) + | + ( + { retval.setNullHandling(Function.NullHandling.RESPECT_NULLS); } + ) + ] + + [ + limit = PlainLimit() { retval.setLimit(limit); } + ] + ")" + [ "." ( // tricky lookahead since we do need to support the following constructs // schema.f1().f2() - Function with Function Column @@ -5248,12 +5642,30 @@ Function InternalFunction(boolean escaped): ) ] + [ + ( + + { + retval.setNullHandling(Function.NullHandling.IGNORE_NULLS); + retval.setIgnoreNullsOutside(true); + } + ) + | + ( + + { + retval.setNullHandling(Function.NullHandling.RESPECT_NULLS); + retval.setIgnoreNullsOutside(true); + } + ) + ] + [ LOOKAHEAD(2) keep = KeepExpression() ] { retval.setEscaped(escaped); retval.setParameters(expressionList); - retval.setName(funcName); + retval.setName(funcName.getNames()); retval.setKeep(keep); return retval; } @@ -5350,10 +5762,10 @@ List ColumnNamesWithParamsList() : { } Index Index(): { - List name; + ObjectNames name; } { - name= RelObjectNameList() { return new Index().withName(name).withType(""); } + name= RelObjectNames() { return new Index().withName(name.getNames()).withType(""); } } CreateIndex CreateIndex(): @@ -5389,7 +5801,7 @@ CreateIndex CreateIndex(): ) ) colNames = ColumnNamesWithParamsList() - ( parameter=CreateParameter() { tailParameters.addAll(parameter); } )* + ( LOOKAHEAD(2) parameter=CreateParameter() { tailParameters.addAll(parameter); } )* { index.setColumns(colNames); createIndex.setIndex(index); @@ -5707,17 +6119,22 @@ SpannerInterleaveIn SpannerInterleaveIn(): } } -ColDataType ColDataType(): + +ColDataType DataType(): { ColDataType colDataType = new ColDataType(); + Token prefix = null; Token tk = null; Token tk2 = null; String schema; - String type; + String type=""; List argumentsStringList = new ArrayList(); List array = new ArrayList(); List name; ColDataType arrayType; + + int precision = -1; + int scale = -1; } { ( @@ -5727,16 +6144,54 @@ ColDataType ColDataType(): } ) | - LOOKAHEAD(2) ( - tk= "(" (tk2= | tk2=) ")" - | tk= "(" (tk2= | tk2=) ")" - | tk= "(" (tk2= | tk2=) ")" - ) { colDataType.setDataType(tk.image + " (" + tk2.image + ")"); } - | - LOOKAHEAD(2) (tk= | tk=) [tk2=] { colDataType.setDataType(tk.image + (tk2!=null?" " + tk2.image:"")); } + ( + ( tk= | tk= | tk = | tk = | tk = + | tk= | tk= | tk= | tk= + | tk= | tk= | tk= ) { type = tk.image; } + [ + // MySQL seems to allow: INT UNSIGNED + LOOKAHEAD(2) ( LOOKAHEAD(2) ( tk = | tk = | tk = + | tk= | tk= | tk= | tk= + | tk= | tk= | tk= ) { type += " " + tk.image; } )+ + ] + [ + LOOKAHEAD(2) "(" ( tk= { precision = Integer.valueOf(tk.image); } | tk= { precision = Integer.MAX_VALUE; } ) + [ "," tk = { scale = Integer.valueOf(tk.image); } ] + ")" + ] + { + colDataType = new ColDataType(type, precision, scale); + } + ) + ) + + { + return colDataType; + } +} + +ColDataType ColDataType(): +{ + ColDataType colDataType = new ColDataType(); + Token prefix = null; + Token tk = null; + Token tk2 = null; + String schema; + String type=""; + List argumentsStringList = new ArrayList(); + List array = new ArrayList(); + List name; + ColDataType arrayType; + + int precision = -1; + int scale = -1; +} +{ + ( + LOOKAHEAD(2) ( + colDataType = DataType() + ) | - tk= [LOOKAHEAD(2) tk2=] { colDataType.setDataType(tk.image + (tk2!=null?" " + tk2.image:"")); } - | ( tk= | tk= @@ -5753,21 +6208,35 @@ ColDataType ColDataType(): | tk= | tk= ) { schema = tk.image; } - [ "." type = RelObjectName() { schema += "." + type; } ] + + [ "." arrayType = ColDataType() { schema += "." + arrayType.toString(); } ] { colDataType.setDataType(schema); } - | - tk= [LOOKAHEAD(2) tk2=] - { if (tk2!=null) colDataType.setDataType(tk.image + " " + tk2.image); else colDataType.setDataType(tk.image); } - | - LOOKAHEAD(2) tk= tk2= {colDataType.setDataType(tk.image + " " + tk2.image);} - | - tk= { colDataType.setDataType(tk.image);} ) - [LOOKAHEAD(2) "(" {tk2 =null;} ( ( ( tk= [ LOOKAHEAD(2) (tk2= | tk2=) ] ) | tk= | tk= | tk= ) - { argumentsStringList.add(tk.image + (tk2!=null?" " + tk2.image:"")); } ["," {/*argumentsStringList.add(",");*/}] )* ")"] + [ + LOOKAHEAD(2) "(" {tk2 =null;} + ( + ( + ( + ( tk= | tk= ) [ LOOKAHEAD(2) (tk2= | tk2=) ] + ) + | + tk= + | + tk= + | + tk= + ) + { + argumentsStringList.add(tk.image + (tk2!=null?" " + tk2.image:"")); + } + + [ "," ] + )* + ")" + ] [ LOOKAHEAD(2) ( LOOKAHEAD(2) "[" {tk=null;} [ tk= ] { array.add(tk!=null?Integer.valueOf(tk.image):null); } "]" )+ { colDataType.setArrayData(array); } ] - [LOOKAHEAD(2) (tk= | tk=) { colDataType.setCharacterSet(tk.image); } ] + [ LOOKAHEAD(2) (tk= | tk=) { colDataType.setCharacterSet(tk.image); } ] { if (argumentsStringList.size() > 0) @@ -5836,7 +6305,7 @@ CreateView CreateView(boolean isUsingOrReplace): [ commentTokens=CreateViewTailComment( ) { createView.setViewCommentOptions(commentTokens); } ] select=Select( ) { createView.setSelect(select); } - [ { createView.setWithReadOnly(true); } ] + [ LOOKAHEAD(2) { createView.setWithReadOnly(true); } ] { return createView; } } @@ -5935,11 +6404,11 @@ List CreateParameter(): tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk= | tk= | tk= | tk= | tk= + | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk= | tk= | tk= | tk= | tk= + | tk= | tk= | tk= | tk= | tk= | tk = | tk = | tk="=" ) { param.add(tk.image); } @@ -6011,7 +6480,7 @@ String ColumnsNamesListItem(): } { ( item = RelObjectName() ) - [ "(" tk = ")" { item = item + "(" + tk.image + ")"; } ] + [ LOOKAHEAD(2) "(" tk = ")" { item = item + "(" + tk.image + ")"; } ] { return item; } @@ -6109,7 +6578,7 @@ Drop Drop(): [ LOOKAHEAD(2) {drop.setIfExists(true);} ] name = Table() { drop.setName(name); } - [ funcArgs = FuncArgsList() ] + [ LOOKAHEAD(2) funcArgs = FuncArgsList() ] ((tk= | tk= | tk= | tk=) { dropArgs.add(tk.image); })* { @@ -6160,7 +6629,7 @@ AlterExpression.ColumnDataType AlterExpressionColumnDataType(): columnName = RelObjectName() { columnSpecs = new ArrayList(); } ( LOOKAHEAD(2) { withType = true; } )? ( LOOKAHEAD(2) dataType = ColDataType() )? - ( parameter = CreateParameter() { columnSpecs.addAll(parameter); } )* + ( LOOKAHEAD(2) parameter = CreateParameter() { columnSpecs.addAll(parameter); } )* { return new AlterExpression.ColumnDataType(columnName, withType, dataType, columnSpecs); } @@ -6300,8 +6769,8 @@ AlterExpression AlterExpression(): alterExp.setIndex(index); } constraints=AlterExpressionConstraintState() { alterExp.setConstraints(constraints); } - [ sk4=RelObjectName() { alterExp.addParameters("USING", sk4); }] - [ index = IndexWithComment(index) { alterExp.setIndex(index); } ] + [ sk4=RelObjectName() { alterExp.addParameters("USING", sk4); }] + [ LOOKAHEAD(2) index = IndexWithComment(index) { alterExp.setIndex(index); } ] ) | LOOKAHEAD(2) ( @@ -6348,8 +6817,8 @@ AlterExpression AlterExpression(): | ( (( { alterExp.setUk(true); } | ) (tk= | tk=) { alterExp.setUkName(tk.image); } )? columnNames=ColumnsNamesList() { alterExp.setUkColumns(columnNames); } - [ sk4=RelObjectName() { alterExp.addParameters("USING", sk4); }] - [ index = IndexWithComment(index) { alterExp.setIndex(index); } ] + [ sk4=RelObjectName() { alterExp.addParameters("USING", sk4); }] + [ LOOKAHEAD(2) index = IndexWithComment(index) { alterExp.setIndex(index); } ] ) | //following two choices regarding foreign keys should be merged @@ -6358,7 +6827,7 @@ AlterExpression AlterExpression(): tk= [ columnNames=ColumnsNamesList() ] { alterExp.setFkSourceTable(tk.image); alterExp.setFkSourceColumns(columnNames); } */ - fkTable=Table() [ columnNames=ColumnsNamesList() ] + fkTable=Table() [ LOOKAHEAD(2) columnNames=ColumnsNamesList() ] { alterExp.setFkSourceSchema(fkTable.getSchemaName()); alterExp.setFkSourceTable(fkTable.getName()); @@ -6385,7 +6854,7 @@ AlterExpression AlterExpression(): .withColumnsNames(columnNames); columnNames = null; } - fkTable=Table() [ columnNames=ColumnsNamesList() ] + fkTable=Table() [ LOOKAHEAD(2) columnNames=ColumnsNamesList() ] { fkIndex.withTable(fkTable).withReferencedColumnNames(columnNames); alterExp.setIndex(fkIndex); @@ -6410,12 +6879,12 @@ AlterExpression AlterExpression(): alterExp.setIndex(index); } constraints=AlterExpressionConstraintState() { alterExp.setConstraints(constraints); } - [ sk4=RelObjectName() { alterExp.addParameters("USING", sk4); }] - [ index = IndexWithComment(index) { alterExp.setIndex(index); } ] + [ sk4=RelObjectName() { alterExp.addParameters("USING", sk4); }] + [ LOOKAHEAD(2) index = IndexWithComment(index) { alterExp.setIndex(index); } ] ) | ( - {Expression exp = null;} ("(" exp = Expression() ")")* { + {Expression exp = null;} (LOOKAHEAD(2) "(" exp = Expression() ")")* { CheckConstraint checkCs = new CheckConstraint().withName(sk3).withExpression(exp); alterExp.setIndex(checkCs); } @@ -6432,8 +6901,8 @@ AlterExpression AlterExpression(): alterExp.setIndex(index); } constraints=AlterExpressionConstraintState() { alterExp.setConstraints(constraints); } - [ sk4=RelObjectName() { alterExp.addParameters("USING", sk4); }] - [ index = IndexWithComment(index) { alterExp.setIndex(index); } ] + [ sk4=RelObjectName() { alterExp.addParameters("USING", sk4); }] + [ LOOKAHEAD(2) index = IndexWithComment(index) { alterExp.setIndex(index); } ] ) | ( @@ -6906,7 +7375,7 @@ Grant Grant(): ArrayList privileges = new ArrayList(); List users; Token tk = null; - List objName; + ObjectNames objName; } { @@ -6915,7 +7384,7 @@ Grant Grant(): [readGrantTypes(privileges) ( readGrantTypes(privileges))*] ( - objName=RelObjectNameList() { grant.setObjectName(objName); } + objName=RelObjectNames() { grant.setObjectName(objName.getNames()); } ) ) | @@ -6960,13 +7429,13 @@ void readGrantTypes(ArrayList privileges): Sequence Sequence() #Sequence : { - List data = new ArrayList(); + ObjectNames data = null; String serverName = null, databaseName = null, schemaName = null, sequenceName = null; } { - data = RelObjectNameList() + data = RelObjectNames() { - Sequence sequence = new Sequence(data); + Sequence sequence = new Sequence(data.getNames()); linkAST(sequence,jjtThis); return sequence; } @@ -6996,7 +7465,7 @@ List SequenceParameters(): } ) | - ( [ token=] + ( [ LOOKAHEAD(2) token=] { parameter = new Sequence.Parameter(Sequence.ParameterType.RESTART_WITH); if(token != null){ @@ -7170,29 +7639,29 @@ CreateSynonym CreateSynonym(boolean isUsingOrReplace): CreateSynonym createSynonym = new CreateSynonym(); Synonym synonym; boolean publicSynonym = false; - List data = new ArrayList(); + ObjectNames data = null; } { [ { publicSynonym = true; } ] synonym=Synonym() { createSynonym.setSynonym(synonym); } - data = RelObjectNameList() + data = RelObjectNames() { createSynonym.setOrReplace(isUsingOrReplace); createSynonym.setPublicSynonym(publicSynonym); - createSynonym.setForList(data); + createSynonym.setForList(data.getNames()); return createSynonym; } } Synonym Synonym() #Synonym : { - List data = new ArrayList(); + ObjectNames data = null; String serverName = null, databaseName = null, schemaName = null, sequenceName = null; } { - data = RelObjectNameList() + data = RelObjectNames() { - Synonym synonym = new Synonym(data); + Synonym synonym = new Synonym(data.getNames()); linkAST(synonym,jjtThis); return synonym; } @@ -7216,7 +7685,7 @@ List captureRest() { while(true) { tok = getToken(1); int l = tokens.size(); - if( tok.kind == EOF ) { + if( tok.kind == EOF || tok.kind == ST_SEMICOLON ) { break; } else if ( l>0 && ( tok.image.equals(".") || tokens.get(l-1).endsWith(".")) ) { tokens.set(l-1, tokens.get(l-1) + tok.image); @@ -7318,16 +7787,39 @@ Expression CharacterPrimary(): } } -TranscodingFunction TranscodingFunction(): +TranscodingFunction TranscodingFunction() #TranscodingFunction : { + TranscodingFunction transcodingFunction; + ColDataType colDataType; Expression expression; - String transcodingName; + String transcodingName=null; + Token style; } { - "(" expression = Expression() transcodingName=IdentifierChain() ")" + "(" + ( + LOOKAHEAD(ColDataType() ",") ( + colDataType = ColDataType() + "," expression = Expression() + [ "," style = { transcodingName = style.image; } ] + { + transcodingFunction = new TranscodingFunction(colDataType, expression, transcodingName); + } + ) + | + ( + expression = Expression() + transcodingName=IdentifierChain() + + { + transcodingFunction = new TranscodingFunction(expression, transcodingName); + } + ) + ) + ")" { - return new TranscodingFunction(expression, transcodingName); + return transcodingFunction; } } diff --git a/src/main/resources/rr/xhtml2rst.xsl b/src/main/resources/rr/xhtml2rst.xsl index b29b03413..1f4687517 100644 --- a/src/main/resources/rr/xhtml2rst.xsl +++ b/src/main/resources/rr/xhtml2rst.xsl @@ -9,37 +9,37 @@ #L% --> - + indent="no"/> - - + + -.. raw:: html + .. raw:: html - <div id="floating-toc"> - <div class="search-container"> - <input type="button" id="toc-hide-show-btn"></input> - <input type="text" id="toc-search" placeholder="Search" /> - </div> - <ul id="toc-list"></ul> - </div> + <div id="floating-toc"> + <div class="search-container"> + <input type="button" id="toc-hide-show-btn"></input> + <input type="text" id="toc-search" placeholder="Search" /> + </div> + <ul id="toc-list"></ul> + </div> - + @@ -47,33 +47,49 @@ - -********************************************************************* -SQL Syntax - |JSQLPARSER_SNAPSHOT_VERSION| - |JSQLPARSER_VERSION| - -********************************************************************* - -The EBNF and Railroad Diagrams for - |JSQLPARSER_SNAPSHOT_VERSION| - |JSQLPARSER_VERSION| - . - - + + ********************************************************************* + SQL Syntax + + + + |JSQLPARSER_SNAPSHOT_VERSION| + + + |JSQLPARSER_VERSION| + + + + ********************************************************************* + + The EBNF and Railroad Diagrams for + + + + |JSQLPARSER_SNAPSHOT_VERSION| + + + |JSQLPARSER_VERSION| + + + . + + - -====================================================================================================================== - -====================================================================================================================== + + ====================================================================================================================== + + + + ====================================================================================================================== - + - -.. raw:: html + + .. raw:: html @@ -94,7 +110,8 @@ The EBNF and Railroad Diagrams for Referenced by:
    - +
@@ -108,7 +125,7 @@ The EBNF and Railroad Diagrams for
- + @@ -117,10 +134,10 @@ The EBNF and Railroad Diagrams for
  • - + - + diff --git a/src/site/sphinx/index.rst b/src/site/sphinx/index.rst index 916e4c07b..e28a57192 100644 --- a/src/site/sphinx/index.rst +++ b/src/site/sphinx/index.rst @@ -12,7 +12,8 @@ Java SQL Parser Library usage contribution - migration + migration47 + migration50 SQL Grammar Stable SQL Grammar Snapshot Unsupported Grammar @@ -51,6 +52,7 @@ Java SQL Parser Library **JSQLParser** is a SQL statement parser built from JavaCC. It translates SQLs in a traversable hierarchy of Java classes. +The upcoming 5.0 release will depend on Java 11 and introduces new Visitors. Please see the :ref:`Migration to 5.0` guide. Latest stable release: |JSQLPARSER_STABLE_VERSION_LINK| diff --git a/src/site/sphinx/keywords.rst b/src/site/sphinx/keywords.rst index af0dd839f..91437ece5 100644 --- a/src/site/sphinx/keywords.rst +++ b/src/site/sphinx/keywords.rst @@ -45,6 +45,8 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | EXCEPT | Yes | Yes | +----------------------+-------------+-----------+ +| EXCLUDES | Yes | Yes | ++----------------------+-------------+-----------+ | EXISTS | Yes | Yes | +----------------------+-------------+-----------+ | FETCH | Yes | Yes | @@ -81,6 +83,8 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | IN | Yes | Yes | +----------------------+-------------+-----------+ +| INCLUDES | Yes | Yes | ++----------------------+-------------+-----------+ | INNER | Yes | Yes | +----------------------+-------------+-----------+ | INTERSECT | Yes | Yes | @@ -135,10 +139,6 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | PUBLIC | Yes | | +----------------------+-------------+-----------+ -| RECURSIVE | Yes | Yes | -+----------------------+-------------+-----------+ -| REGEXP | Yes | Yes | -+----------------------+-------------+-----------+ | RETURNING | Yes | Yes | +----------------------+-------------+-----------+ | RIGHT | Yes | Yes | diff --git a/src/site/sphinx/migration.rst b/src/site/sphinx/migration47.rst similarity index 100% rename from src/site/sphinx/migration.rst rename to src/site/sphinx/migration47.rst diff --git a/src/site/sphinx/migration50.rst b/src/site/sphinx/migration50.rst new file mode 100644 index 000000000..eb0a9926a --- /dev/null +++ b/src/site/sphinx/migration50.rst @@ -0,0 +1,96 @@ +********************************* +Migration to 5.0 +********************************* + +The new JSQLParser 5 introduces API-breaking changes: + +1. **Dependency on Java 11 or newer** + +2. **Reworked AST Visitors** + + The AST Visitors have been reworked to pass a Generic Context from the Root Node down to the Leaves. + + .. code-block:: java + :caption: Generic Interface + + public interface SelectVisitor { + + T visit(PlainSelect plainSelect, S context); + + default void visit(PlainSelect plainSelect) { + this.visit(plainSelect, null); + } + + } + + .. code-block:: java + :caption: Sample Implementation + + public class JSQLColumnResolver + implements SelectVisitor, FromItemVisitor { + + @Override + public JdbcResultSetMetaData visit(PlainSelect select, S context) { + if (context instanceof JdbcMetaData) { + return visit(select, (JdbcMetaData) context); + } + return null; + } + + public JdbcResultSetMetaData visit(PlainSelect select, JdbcMetaData metaData) { + JdbcResultSetMetaData resultSetMetaData = new JdbcResultSetMetaData(); + + // Logic to retrieve the column information + resultSetMetaData = getColumn(metaData, select.getFromItem(), select.getJoins()); + + return resultSetMetaData; + } + } + +3. **Generic Result from Leaves to Root** + + Node objects now return a Generic Result from the Leaves up to the Root. + + .. code-block:: java + :caption: AST Node + + public class PlainSelect extends Select { + @Override + public T accept(SelectVisitor selectVisitor, S context) { + return selectVisitor.visit(this, context); + } + } + +How is this useful? Consider resolving the `AllColumns` ``*`` or `AllTableColumns` ``t.*`` expressions to retrieve the actual column names. This process depends on the database's physical metadata and the context of the current scope, including virtual data frames (like sub-selects and with-clauses). + +Therefore, every branch of the AST must receive scoped metadata from its parent node. Each AST node must receive the resolved columns from its child nodes. A global result object (like the `StringBuilder` in the `DepParser` implementations) is inadequate. + +Alternatively, consider substituting `TimeValueKey` (``CURRENT_DATE``, ``CURRENT_TIME``, etc.) with actual date or time values. You can push a simple `Map` of key/value pairs down to the Expression Visitor: + + .. code-block:: java + :caption: Expression Visitor + + @Override + public StringBuilder visit(TimeKeyExpression expression, S context) { + if (context instanceof Map) { + return visit(expression, (Map) substitutions); + } else { + return expression.toString(); + } + } + + public StringBuilder visit(TimeKeyExpression expression, Map substitutions) { + // Remove possible trailing brackets "()" + String value = expression.getStringValue().toUpperCase().replaceAll("[()]", ""); + + if (substitutions.containsKey(value)) { + // @todo: Cast Date/Time types + return castDateTime(substitutions.get(value).toString()).accept(this, null); + } else { + return super.visit(expression, null); + } + } + +Another advantage is parallel processing: Without relying on a global result object, the AST can be traversed in parallel (whereas it currently must be traversed strictly in serial). + +Finally, any child node can now know its parent and identify who called it. diff --git a/src/site/sphinx/usage.rst b/src/site/sphinx/usage.rst index fbacd437c..378166dcd 100644 --- a/src/site/sphinx/usage.rst +++ b/src/site/sphinx/usage.rst @@ -18,7 +18,7 @@ How to use it Compile from Source Code ============================== -You will need to have ``JDK 8`` or ``JDK 11`` installed. +You will need to have ``JDK 8`` or ``JDK 11`` installed. Please note that JSQLParser-4.9 is the last ``JDK 8`` compatible release and all development after will depend on ``JDK 11``. .. tab:: Maven @@ -145,6 +145,43 @@ For guidance with the API, use `JSQLFormatter +Error Handling +============================== + +There are two features for handling errors + +- ``parser.withErrorRecovery(true)`` will continue to the next statement separator and return an empty statement. +- ``parser.withUnsupportedStatements(true)`` will return an instance of the `UnsupportedStatement` class, although the first statement **must** be a regular statement + +.. code-block:: java + :caption: Error Recovery + + CCJSqlParser parser = new CCJSqlParser( + "select * from mytable; select from; select * from mytable2" ); + Statements statements = parser.withErrorRecovery().Statements(); + + // 3 statements, the failing one set to NULL + assertEquals(3, statements.size()); + assertNull(statements.get(1)); + + // errors are recorded + assertEquals(1, parser.getParseErrors().size()); + +.. code-block:: java + :caption: Unsupported Statement + + Statements statements = CCJSqlParserUtil.parseStatements( + "select * from mytable; select from; select * from mytable2; select 4;" + , parser -> parser.withUnsupportedStatements() ); + + // 4 statements with one Unsupported Statement holding the content + assertEquals(4, statements.size()); + assertInstanceOf(UnsupportedStatement.class, statements.get(1)); + assertEquals("select from", statements.get(1).toString()); + + // no errors records, because a statement has been returned + assertEquals(0, parser.getParseErrors().size()); + Use the Visitor Patterns ============================== @@ -155,36 +192,38 @@ Traverse the Java Object Tree using the Visitor Patterns: // Define an Expression Visitor reacting on any Expression // Overwrite the visit() methods for each Expression Class - ExpressionVisitorAdapter expressionVisitorAdapter = new ExpressionVisitorAdapter() { - public void visit(EqualsTo equalsTo) { - equalsTo.getLeftExpression().accept(this); - equalsTo.getRightExpression().accept(this); + ExpressionVisitorAdapter expressionVisitorAdapter = new ExpressionVisitorAdapter<>() { + public Void visit(EqualsTo equalsTo, S context) { + equalsTo.getLeftExpression().accept(this, context); + equalsTo.getRightExpression().accept(this, context); + return null; } - public void visit(Column column) { + public Void visit(Column column, S context) { System.out.println("Found a Column " + column.getColumnName()); + return null; } }; // Define a Select Visitor reacting on a Plain Select invoking the Expression Visitor on the Where Clause - SelectVisitorAdapter selectVisitorAdapter = new SelectVisitorAdapter() { + SelectVisitorAdapter selectVisitorAdapter = new SelectVisitorAdapter<>() { @Override - public void visit(PlainSelect plainSelect) { - plainSelect.getWhere().accept(expressionVisitorAdapter); + public Void visit(PlainSelect plainSelect, S context) { + return plainSelect.getWhere().accept(expressionVisitorAdapter, context); } }; // Define a Statement Visitor for dispatching the Statements - StatementVisitorAdapter statementVisitor = new StatementVisitorAdapter() { - public void visit(Select select) { - select.getSelectBody().accept(selectVisitorAdapter); + StatementVisitorAdapter statementVisitor = new StatementVisitorAdapter<>() { + public Void visit(Select select, S context) { + return select.getSelectBody().accept(selectVisitorAdapter, context); } }; String sqlStr="select 1 from dual where a=b"; Statement stmt = CCJSqlParserUtil.parse(sqlStr); - // Invoke the Statement Visitor - stmt.accept(statementVisitor); + // Invoke the Statement Visitor without a context + stmt.accept(statementVisitor, null); Find Table Names ============================== diff --git a/src/test/java/net/sf/jsqlparser/expression/AliasTest.java b/src/test/java/net/sf/jsqlparser/expression/AliasTest.java new file mode 100644 index 000000000..809aed3dd --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/AliasTest.java @@ -0,0 +1,23 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +class AliasTest { + + @Test + void testUDTF() throws JSQLParserException { + String sqlStr = "select udtf_1(words) as (a1, a2) from tab"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } +} diff --git a/src/test/java/net/sf/jsqlparser/expression/AnalyticExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/AnalyticExpressionTest.java new file mode 100644 index 000000000..df4ef1eba --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/AnalyticExpressionTest.java @@ -0,0 +1,46 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +class AnalyticExpressionTest { + + @Test + void testRedshiftApproximate() throws JSQLParserException { + String sqlStr = "select top 10 date.caldate,\n" + + "count(totalprice), sum(totalprice),\n" + + "approximate percentile_disc(0.5) \n" + + "within group (order by totalprice)\n" + + "from listing\n" + + "join date on listing.dateid = date.dateid\n" + + "group by date.caldate\n" + + "order by 3 desc;"; + + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "select approximate count(distinct pricepaid) from sales;"; + + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testDatabricks() throws JSQLParserException { + String sqlStr = "SELECT any_value(col) IGNORE NULLS FROM test;"; + + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT any_value(col) IGNORE NULLS FROM VALUES (NULL), (5), (20) AS tab(col);"; + + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } +} diff --git a/src/test/java/net/sf/jsqlparser/expression/ArrayExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/ArrayExpressionTest.java new file mode 100644 index 000000000..dd9644100 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/ArrayExpressionTest.java @@ -0,0 +1,33 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.SelectItem; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class ArrayExpressionTest { + + @Test + void testColumnArrayExpression() throws JSQLParserException { + String sqlStr = "SELECT a[2+1] AS a"; + PlainSelect select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + SelectItem selectItem = select.getSelectItem(0); + + Column column = selectItem.getExpression(Column.class); + assertInstanceOf(ArrayConstructor.class, column.getArrayConstructor()); + } + +} diff --git a/src/test/java/net/sf/jsqlparser/expression/BinaryExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/BinaryExpressionTest.java new file mode 100644 index 000000000..2f282ddbc --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/BinaryExpressionTest.java @@ -0,0 +1,22 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class BinaryExpressionTest { + + @Test + void testAddition() { + Expression addition = BinaryExpression.add(new LongValue(1), new LongValue(1)); + Assertions.assertEquals("1 + 1", addition.toString()); + } +} diff --git a/src/test/java/net/sf/jsqlparser/expression/CaseExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/CaseExpressionTest.java index e86f92a2b..6c0cbb50c 100644 --- a/src/test/java/net/sf/jsqlparser/expression/CaseExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/CaseExpressionTest.java @@ -160,4 +160,10 @@ void testPerformanceIssue1889() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + void testFormatClause() throws JSQLParserException { + String sqlStr = "SELECT CAST('18-12-03' AS DATE FORMAT 'YY-MM-DD') AS string_to_date"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/expression/CastExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/CastExpressionTest.java index da049cdad..806b6764a 100644 --- a/src/test/java/net/sf/jsqlparser/expression/CastExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/CastExpressionTest.java @@ -10,9 +10,13 @@ package net.sf.jsqlparser.expression; import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; + /** * * @author Andreas Reichel @@ -21,8 +25,11 @@ public class CastExpressionTest { @Test public void testCastToRowConstructorIssue1267() throws JSQLParserException { - TestUtils.assertExpressionCanBeParsedAndDeparsed("CAST(ROW(dataid, value, calcMark) AS ROW(datapointid CHAR, value CHAR, calcMark CHAR))", true); - TestUtils.assertExpressionCanBeParsedAndDeparsed("CAST(ROW(dataid, value, calcMark) AS testcol)", true); + TestUtils.assertExpressionCanBeParsedAndDeparsed( + "CAST(ROW(dataid, value, calcMark) AS ROW(datapointid CHAR, value CHAR, calcMark CHAR))", + true); + TestUtils.assertExpressionCanBeParsedAndDeparsed( + "CAST(ROW(dataid, value, calcMark) AS testcol)", true); } @Test @@ -30,4 +37,71 @@ void testDataKeywordIssue1969() throws Exception { String sqlStr = "SELECT * FROM myschema.myfunction('test'::data.text_not_null)"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + void testImplicitCast() throws JSQLParserException { + String sqlStr = "SELECT UUID '4ac7a9e9-607c-4c8a-84f3-843f0191e3fd'"; + PlainSelect select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + Assertions.assertTrue(select.getSelectItem(0).getExpression() instanceof CastExpression); + + sqlStr = "SELECT DECIMAL(5,3) '3.2'"; + select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + Assertions.assertTrue(select.getSelectItem(0).getExpression() instanceof CastExpression); + } + + @Test + void testImplicitCastTimestampIssue1364() throws JSQLParserException { + String sqlStr = "SELECT TIMESTAMP WITH TIME ZONE '2004-10-19 10:23:54+02'"; + PlainSelect select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + Assertions.assertTrue(select.getSelectItem(0).getExpression() instanceof CastExpression); + } + + @Test + void testImplicitCastDoublePrecisionIssue1344() throws JSQLParserException { + String sqlStr = "SELECT double precision '1'"; + PlainSelect select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + Assertions.assertTrue(select.getSelectItem(0).getExpression() instanceof CastExpression); + } + + + @Test + public void testCastToSigned() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "SELECT CAST(contact_id AS SIGNED) A"); + + assertSqlCanBeParsedAndDeparsed( + "SELECT CAST(contact_id AS SIGNED INTEGER) A"); + + assertSqlCanBeParsedAndDeparsed( + "SELECT CAST(contact_id AS UNSIGNED) A"); + + assertSqlCanBeParsedAndDeparsed( + "SELECT CAST(contact_id AS UNSIGNED INTEGER) A"); + + assertSqlCanBeParsedAndDeparsed( + "SELECT CAST(contact_id AS TIME WITHOUT TIME ZONE) A"); + } + + + @Test + void testDataTypeFrom() { + CastExpression.DataType float64 = CastExpression.DataType.from("FLOAT64"); + Assertions.assertEquals(CastExpression.DataType.FLOAT64, float64); + + CastExpression.DataType float128 = CastExpression.DataType.from("FLOAT128"); + Assertions.assertEquals(CastExpression.DataType.UNKNOWN, float128); + } + + @Test + void testParenthesisCastIssue1997() throws JSQLParserException { + String sqlStr = "SELECT ((foo)::text = ANY((ARRAY['bar'])::text[]))"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT ((foo)::text = ANY((((ARRAY['bar'])))::text[]))"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/expression/DateTimeLiteralTest.java b/src/test/java/net/sf/jsqlparser/expression/DateTimeLiteralTest.java new file mode 100644 index 000000000..f599eb6a9 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/DateTimeLiteralTest.java @@ -0,0 +1,30 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +public class DateTimeLiteralTest { + + @Test + void testDateTimeWithAlias() throws JSQLParserException { + String sqlStr = "SELECT DATETIME '2005-01-03 12:34:56' as datetime"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testDateTimeWithDoubleQuotes() throws JSQLParserException { + String sqlStr = "SELECT DATETIME \"2005-01-03 12:34:56\" as datetime"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + +} diff --git a/src/test/java/net/sf/jsqlparser/expression/DoubleValueTest.java b/src/test/java/net/sf/jsqlparser/expression/DoubleValueTest.java index 1ef676c6d..43150d261 100644 --- a/src/test/java/net/sf/jsqlparser/expression/DoubleValueTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/DoubleValueTest.java @@ -11,6 +11,7 @@ import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; public class DoubleValueTest { @@ -28,4 +29,14 @@ public void testEmptyValue() { new DoubleValue(""); }); } + + @Test + public void shouldSetStringValue() { + final DoubleValue doubleValue = new DoubleValue("42"); + + doubleValue.setValue(43D); + + assertEquals(43D, doubleValue.getValue()); + assertEquals("43.0", doubleValue.toString()); + } } diff --git a/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java b/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java index 14ae67fed..d9f45c2ca 100644 --- a/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java @@ -11,8 +11,11 @@ import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.operators.conditional.XorExpression; +import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.InExpression; +import net.sf.jsqlparser.expression.operators.relational.IncludesExpression; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.statement.select.AllTableColumns; @@ -25,8 +28,8 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; /** @@ -40,18 +43,19 @@ public void testInExpressionProblem() throws JSQLParserException { PlainSelect plainSelect = (PlainSelect) CCJSqlParserUtil.parse("select * from foo where x in (?,?,?)"); Expression where = plainSelect.getWhere(); - where.accept(new ExpressionVisitorAdapter() { + where.accept(new ExpressionVisitorAdapter() { @Override - public void visit(InExpression expr) { - super.visit(expr); + public Void visit(InExpression expr, S parameters) { + super.visit(expr, parameters); exprList.add(expr.getLeftExpression()); exprList.add(expr.getRightExpression()); + return null; } - }); + }, null); - assertTrue(exprList.get(0) instanceof Column); - assertTrue(exprList.get(1) instanceof ExpressionList); + assertInstanceOf(Column.class, exprList.get(0)); + assertInstanceOf(ExpressionList.class, exprList.get(1)); } @Test @@ -60,18 +64,19 @@ public void testInExpression() throws JSQLParserException { PlainSelect plainSelect = (PlainSelect) CCJSqlParserUtil .parse("select * from foo where (a,b) in (select a,b from foo2)"); Expression where = plainSelect.getWhere(); - where.accept(new ExpressionVisitorAdapter() { + where.accept(new ExpressionVisitorAdapter() { @Override - public void visit(InExpression expr) { - super.visit(expr); + public Void visit(InExpression expr, S parameters) { + super.visit(expr, parameters); exprList.add(expr.getLeftExpression()); exprList.add(expr.getRightExpression()); + return null; } - }); + }, null); - assertTrue(exprList.get(0) instanceof ExpressionList); - assertTrue(exprList.get(1) instanceof Select); + assertInstanceOf(ExpressionList.class, exprList.get(0)); + assertInstanceOf(Select.class, exprList.get(1)); } @Test @@ -80,20 +85,21 @@ public void testXorExpression() throws JSQLParserException { PlainSelect plainSelect = (PlainSelect) CCJSqlParserUtil.parse("SELECT * FROM table WHERE foo XOR bar"); Expression where = plainSelect.getWhere(); - where.accept(new ExpressionVisitorAdapter() { + where.accept(new ExpressionVisitorAdapter() { @Override - public void visit(XorExpression expr) { - super.visit(expr); + public Void visit(XorExpression expr, S parameters) { + super.visit(expr, parameters); exprList.add(expr.getLeftExpression()); exprList.add(expr.getRightExpression()); + return null; } - }); + }, null); assertEquals(2, exprList.size()); - assertTrue(exprList.get(0) instanceof Column); + assertInstanceOf(Column.class, exprList.get(0)); assertEquals("foo", ((Column) exprList.get(0)).getColumnName()); - assertTrue(exprList.get(1) instanceof Column); + assertInstanceOf(Column.class, exprList.get(1)); assertEquals("bar", ((Column) exprList.get(1)).getColumnName()); } @@ -108,14 +114,15 @@ public static void testOracleHintExpression(String sql, String hint, boolean sin PlainSelect plainSelect = (PlainSelect) CCJSqlParserUtil.parse(sql); final OracleHint[] holder = new OracleHint[1]; assertNotNull(plainSelect.getOracleHint()); - plainSelect.getOracleHint().accept(new ExpressionVisitorAdapter() { + plainSelect.getOracleHint().accept(new ExpressionVisitorAdapter() { @Override - public void visit(OracleHint hint) { - super.visit(hint); + public Void visit(OracleHint hint, S parameters) { + super.visit(hint, parameters); holder[0] = hint; + return null; } - }); + }, null); assertNotNull(holder[0]); assertEquals(singleLine, holder[0].isSingleLine()); @@ -128,14 +135,15 @@ public void testCurrentTimestampExpression() throws JSQLParserException { PlainSelect plainSelect = (PlainSelect) CCJSqlParserUtil .parse("select * from foo where bar < CURRENT_TIMESTAMP"); Expression where = plainSelect.getWhere(); - where.accept(new ExpressionVisitorAdapter() { + where.accept(new ExpressionVisitorAdapter() { @Override - public void visit(Column column) { - super.visit(column); + public Void visit(Column column, S parameters) { + super.visit(column, parameters); columnList.add(column.getColumnName()); + return null; } - }); + }, null); assertEquals(1, columnList.size()); assertEquals("bar", columnList.get(0)); @@ -147,14 +155,15 @@ public void testCurrentDateExpression() throws JSQLParserException { PlainSelect plainSelect = (PlainSelect) CCJSqlParserUtil.parse("select * from foo where bar < CURRENT_DATE"); Expression where = plainSelect.getWhere(); - where.accept(new ExpressionVisitorAdapter() { + where.accept(new ExpressionVisitorAdapter() { @Override - public void visit(Column column) { - super.visit(column); + public Void visit(Column column, S parameters) { + super.visit(column, parameters); columnList.add(column.getColumnName()); + return null; } - }); + }, null); assertEquals(1, columnList.size()); assertEquals("bar", columnList.get(0)); @@ -165,10 +174,10 @@ public void testSubSelectExpressionProblem() throws JSQLParserException { PlainSelect plainSelect = (PlainSelect) CCJSqlParserUtil .parse("SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t2.col2 = t1.col1)"); Expression where = plainSelect.getWhere(); - ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter(); - adapter.setSelectVisitor(new SelectVisitorAdapter()); + ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter<>(); + adapter.setSelectVisitor(new SelectVisitorAdapter<>()); try { - where.accept(adapter); + where.accept(adapter, null); } catch (NullPointerException npe) { fail(); } @@ -177,70 +186,71 @@ public void testSubSelectExpressionProblem() throws JSQLParserException { @Test public void testCaseWithoutElse() throws JSQLParserException { Expression expr = CCJSqlParserUtil.parseExpression("CASE WHEN 1 then 0 END"); - ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter(); - expr.accept(adapter); + ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter<>(); + expr.accept(adapter, null); } @Test public void testCaseWithoutElse2() throws JSQLParserException { Expression expr = CCJSqlParserUtil.parseExpression("CASE WHEN 1 then 0 ELSE -1 END"); - ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter(); - expr.accept(adapter); + ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter<>(); + expr.accept(adapter, null); } @Test public void testCaseWithoutElse3() throws JSQLParserException { Expression expr = CCJSqlParserUtil.parseExpression("CASE 3+4 WHEN 1 then 0 END"); - ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter(); - expr.accept(adapter); + ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter<>(); + expr.accept(adapter, null); } @Test public void testAnalyticFunctionWithoutExpression502() throws JSQLParserException { Expression expr = CCJSqlParserUtil.parseExpression("row_number() over (order by c)"); - ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter(); - expr.accept(adapter); + ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter<>(); + expr.accept(adapter, null); } @Test public void testAtTimeZoneExpression() throws JSQLParserException { Expression expr = CCJSqlParserUtil .parseExpression("DATE(date1 AT TIME ZONE 'UTC' AT TIME ZONE 'australia/sydney')"); - ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter(); - expr.accept(adapter); + ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter<>(); + expr.accept(adapter, null); } @Test public void testJsonFunction() throws JSQLParserException { - ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter(); + ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter<>(); CCJSqlParserUtil.parseExpression("JSON_OBJECT( KEY 'foo' VALUE bar, KEY 'foo' VALUE bar)") - .accept(adapter); - CCJSqlParserUtil.parseExpression("JSON_ARRAY( (SELECT * from dual) )").accept(adapter); + .accept(adapter, null); + CCJSqlParserUtil.parseExpression("JSON_ARRAY( (SELECT * from dual) )").accept(adapter, + null); } @Test public void testJsonAggregateFunction() throws JSQLParserException { - ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter(); + ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter<>(); CCJSqlParserUtil.parseExpression( "JSON_OBJECTAGG( KEY foo VALUE bar NULL ON NULL WITH UNIQUE KEYS ) FILTER( WHERE name = 'Raj' ) OVER( PARTITION BY name )") - .accept(adapter); + .accept(adapter, null); CCJSqlParserUtil.parseExpression( "JSON_ARRAYAGG( a FORMAT JSON ABSENT ON NULL ) FILTER( WHERE name = 'Raj' ) OVER( PARTITION BY name )") - .accept(adapter); + .accept(adapter, null); } @Test public void testConnectedByRootExpression() throws JSQLParserException { - ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter(); - CCJSqlParserUtil.parseExpression("CONNECT_BY_ROOT last_name as name").accept(adapter); + ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter<>(); + CCJSqlParserUtil.parseExpression("CONNECT_BY_ROOT last_name as name").accept(adapter, null); } @Test public void testRowConstructor() throws JSQLParserException { - ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter(); + ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter<>(); CCJSqlParserUtil.parseExpression( "CAST(ROW(dataid, value, calcMark) AS ROW(datapointid CHAR, value CHAR, calcMark CHAR))") - .accept(adapter); + .accept(adapter, null); } @Test @@ -248,13 +258,14 @@ public void testAllTableColumns() throws JSQLParserException { PlainSelect plainSelect = (PlainSelect) CCJSqlParserUtil.parse("select a.* from foo a"); final AllTableColumns[] holder = new AllTableColumns[1]; Expression from = plainSelect.getSelectItems().get(0).getExpression(); - from.accept(new ExpressionVisitorAdapter() { + from.accept(new ExpressionVisitorAdapter() { @Override - public void visit(AllTableColumns all) { + public Void visit(AllTableColumns all, S parameters) { holder[0] = all; + return null; } - }); + }, null); assertNotNull(holder[0]); assertEquals("a.*", holder[0].toString()); @@ -262,10 +273,52 @@ public void visit(AllTableColumns all) { @Test public void testAnalyticExpressionWithPartialWindowElement() throws JSQLParserException { - ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter(); + ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter<>(); Expression expression = CCJSqlParserUtil.parseExpression( "SUM(\"Spent\") OVER (PARTITION BY \"ID\" ORDER BY \"Name\" ASC ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)"); - expression.accept(adapter); + expression.accept(adapter, null); + } + + @Test + public void testIncludesExpression() throws JSQLParserException { + final List exprList = new ArrayList<>(); + PlainSelect plainSelect = (PlainSelect) CCJSqlParserUtil + .parse("select id from foo where b includes ('A', 'B')"); + Expression where = plainSelect.getWhere(); + where.accept(new ExpressionVisitorAdapter() { + + @Override + public Void visit(IncludesExpression expr, S parameters) { + super.visit(expr, parameters); + exprList.add(expr.getLeftExpression()); + exprList.add(expr.getRightExpression()); + return null; + } + }, null); + + assertInstanceOf(Column.class, exprList.get(0)); + assertInstanceOf(ParenthesedExpressionList.class, exprList.get(1)); + } + + @Test + public void testExcludesExpression() throws JSQLParserException { + final List exprList = new ArrayList<>(); + PlainSelect plainSelect = (PlainSelect) CCJSqlParserUtil + .parse("select id from foo where b Excludes ('A', 'B')"); + Expression where = plainSelect.getWhere(); + where.accept(new ExpressionVisitorAdapter() { + + @Override + public Void visit(ExcludesExpression expr, S parameters) { + super.visit(expr, parameters); + exprList.add(expr.getLeftExpression()); + exprList.add(expr.getRightExpression()); + return null; + } + }, null); + + assertInstanceOf(Column.class, exprList.get(0)); + assertInstanceOf(ParenthesedExpressionList.class, exprList.get(1)); } } diff --git a/src/test/java/net/sf/jsqlparser/expression/ExtractExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/ExtractExpressionTest.java new file mode 100644 index 000000000..9137349f3 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/ExtractExpressionTest.java @@ -0,0 +1,24 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +class ExtractExpressionTest { + + @Test + void testRegularFunctionCall() throws JSQLParserException { + String sqlStr = "select extract(engine_full, '''(.*?)''')"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + } +} diff --git a/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java b/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java index d5e132282..cd0f17278 100644 --- a/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java @@ -49,4 +49,30 @@ void testChainedFunctions() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + void testDatetimeParameter() throws JSQLParserException { + String sqlStr = "SELECT DATE(DATETIME '2016-12-25 23:59:59')"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testFunctionArrayParameter() throws JSQLParserException { + String sqlStr = "select unnest(ARRAY[1,2,3], nested >= true) as a"; + + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testSubSelectArrayWithoutKeywordParameter() throws JSQLParserException { + String sqlStr = "SELECT\n" + + " email,\n" + + " REGEXP_CONTAINS(email, r'@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+') AS is_valid\n" + + "FROM\n" + + " (SELECT\n" + + " ['foo@example.com', 'bar@example.org', 'www.example.net']\n" + + " AS addresses),\n" + + " UNNEST(addresses) AS email"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/expression/FunctionWithBooleanParameterTest.java b/src/test/java/net/sf/jsqlparser/expression/FunctionWithBooleanParameterTest.java index 87b9982b9..3c726619c 100644 --- a/src/test/java/net/sf/jsqlparser/expression/FunctionWithBooleanParameterTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/FunctionWithBooleanParameterTest.java @@ -21,8 +21,7 @@ */ public class FunctionWithBooleanParameterTest { - public FunctionWithBooleanParameterTest() { - } + public FunctionWithBooleanParameterTest() {} @Test public void testParseOpLowerTotally() throws Exception { diff --git a/src/test/java/net/sf/jsqlparser/expression/HexValueTest.java b/src/test/java/net/sf/jsqlparser/expression/HexValueTest.java new file mode 100644 index 000000000..736c82cca --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/HexValueTest.java @@ -0,0 +1,42 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.statement.select.PlainSelect; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class HexValueTest { + + @Test + void testHexCode() throws JSQLParserException { + String sqlString = "SELECT 0xF001, X'00A1', X'C3BC'"; + PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlString); + + HexValue hex1 = (HexValue) select.getSelectItem(0).getExpression(); + Assertions.assertEquals("F001", hex1.getDigits()); + Assertions.assertEquals(61441, hex1.getLong()); + Assertions.assertEquals(61441, hex1.getLongValue().getValue()); + + HexValue hex2 = (HexValue) select.getSelectItem(1).getExpression(); + Assertions.assertEquals("00A1", hex2.getDigits()); + Assertions.assertEquals(161, hex2.getLong()); + Assertions.assertEquals(161, hex2.getLongValue().getValue()); + + HexValue hex3 = (HexValue) select.getSelectItem(2).getExpression(); + Assertions.assertEquals("C3BC", hex3.getDigits()); + Assertions.assertEquals("'ü'", hex3.getStringValue().toString()); + Assertions.assertEquals("ü", hex3.getStringValue().getValue()); + + Assertions.assertEquals("'\\xC3\\xBC'", hex3.getBlob().toString()); + } +} diff --git a/src/test/java/net/sf/jsqlparser/expression/JsonFunctionTest.java b/src/test/java/net/sf/jsqlparser/expression/JsonFunctionTest.java index d27378658..1ce33d52e 100644 --- a/src/test/java/net/sf/jsqlparser/expression/JsonFunctionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/JsonFunctionTest.java @@ -25,7 +25,8 @@ public class JsonFunctionTest { public void testObjectAgg() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed( "SELECT JSON_OBJECTAGG( KEY foo VALUE bar) FROM dual ", true); - TestUtils.assertSqlCanBeParsedAndDeparsed("SELECT JSON_OBJECTAGG( foo:bar) FROM dual ", true); + TestUtils.assertSqlCanBeParsedAndDeparsed("SELECT JSON_OBJECTAGG( foo:bar) FROM dual ", + true); TestUtils.assertSqlCanBeParsedAndDeparsed( "SELECT JSON_OBJECTAGG( foo:bar FORMAT JSON) FROM dual ", true); TestUtils.assertSqlCanBeParsedAndDeparsed( @@ -61,7 +62,8 @@ public void testObjectBuilder() throws JSQLParserException { keyValuePair1.setUsingValueKeyword(true); f.add(keyValuePair1.withUsingFormatJson(true)); - JsonKeyValuePair keyValuePair2 = new JsonKeyValuePair("foo", "bar", false, false).withUsingKeyKeyword(true).withUsingValueKeyword(true).withUsingFormatJson(false); + JsonKeyValuePair keyValuePair2 = new JsonKeyValuePair("foo", "bar", false, false) + .withUsingKeyKeyword(true).withUsingValueKeyword(true).withUsingFormatJson(false); // this should work because we compare based on KEY only Assertions.assertEquals(keyValuePair1, keyValuePair2); @@ -69,7 +71,8 @@ public void testObjectBuilder() throws JSQLParserException { // this must fail because all the properties are considered Assertions.assertNotEquals(keyValuePair1.toString(), keyValuePair2.toString()); - JsonKeyValuePair keyValuePair3 = new JsonKeyValuePair("foo", "bar", false, false).withUsingKeyKeyword(false).withUsingValueKeyword(false).withUsingFormatJson(false); + JsonKeyValuePair keyValuePair3 = new JsonKeyValuePair("foo", "bar", false, false) + .withUsingKeyKeyword(false).withUsingValueKeyword(false).withUsingFormatJson(false); Assertions.assertNotNull(keyValuePair3); Assertions.assertEquals(keyValuePair3, keyValuePair3); Assertions.assertNotEquals(keyValuePair3, f); @@ -87,8 +90,9 @@ public void testArrayBuilder() throws JSQLParserException { JsonFunctionExpression expression1 = new JsonFunctionExpression(new NullValue()); expression1.setUsingFormatJson(true); - JsonFunctionExpression expression2 = new JsonFunctionExpression(new NullValue()).withUsingFormatJson( - true); + JsonFunctionExpression expression2 = + new JsonFunctionExpression(new NullValue()).withUsingFormatJson( + true); Assertions.assertEquals(expression1.toString(), expression2.toString()); @@ -101,9 +105,11 @@ public void testArrayAgg() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed("SELECT JSON_ARRAYAGG( a ) FROM dual ", true); TestUtils.assertSqlCanBeParsedAndDeparsed("SELECT JSON_ARRAYAGG( a ORDER BY a ) FROM dual ", true); - TestUtils.assertSqlCanBeParsedAndDeparsed("SELECT JSON_ARRAYAGG( a NULL ON NULL ) FROM dual ", + TestUtils.assertSqlCanBeParsedAndDeparsed( + "SELECT JSON_ARRAYAGG( a NULL ON NULL ) FROM dual ", true); - TestUtils.assertSqlCanBeParsedAndDeparsed("SELECT JSON_ARRAYAGG( a FORMAT JSON ) FROM dual ", + TestUtils.assertSqlCanBeParsedAndDeparsed( + "SELECT JSON_ARRAYAGG( a FORMAT JSON ) FROM dual ", true); TestUtils.assertSqlCanBeParsedAndDeparsed( "SELECT JSON_ARRAYAGG( a FORMAT JSON NULL ON NULL ) FROM dual ", true); @@ -127,7 +133,8 @@ public void testArrayAgg() throws JSQLParserException { public void testObject() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed( "SELECT JSON_OBJECT( KEY 'foo' VALUE bar, KEY 'foo' VALUE bar) FROM dual ", true); - TestUtils.assertSqlCanBeParsedAndDeparsed("SELECT JSON_OBJECT( 'foo' : bar, 'foo' : bar) FROM dual ", + TestUtils.assertSqlCanBeParsedAndDeparsed( + "SELECT JSON_OBJECT( 'foo' : bar, 'foo' : bar) FROM dual ", true); TestUtils.assertSqlCanBeParsedAndDeparsed( "SELECT JSON_OBJECT( 'foo':bar, 'foo':bar FORMAT JSON) FROM dual ", true); @@ -156,10 +163,12 @@ public void testObject() throws JSQLParserException { @Test public void testObjectWithExpression() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed( - "SELECT JSON_OBJECT( KEY 'foo' VALUE cast( bar AS VARCHAR(40)), KEY 'foo' VALUE bar) FROM dual ", true); + "SELECT JSON_OBJECT( KEY 'foo' VALUE cast( bar AS VARCHAR(40)), KEY 'foo' VALUE bar) FROM dual ", + true); TestUtils.assertSqlCanBeParsedAndDeparsed( - "SELECT JSON_ARRAYAGG(obj) FROM (SELECT trt.relevance_id,JSON_OBJECT('id',CAST(trt.id AS CHAR),'taskName',trt.task_name,'openStatus',trt.open_status,'taskSort',trt.task_sort) as obj FROM tb_review_task trt ORDER BY trt.task_sort ASC)", true); + "SELECT JSON_ARRAYAGG(obj) FROM (SELECT trt.relevance_id,JSON_OBJECT('id',CAST(trt.id AS CHAR),'taskName',trt.task_name,'openStatus',trt.open_status,'taskSort',trt.task_sort) as obj FROM tb_review_task trt ORDER BY trt.task_sort ASC)", + true); } @Test @@ -168,7 +177,8 @@ public void testObjectIssue1504() throws JSQLParserException { "SELECT JSON_OBJECT(key 'person' value tp.account) obj", true); TestUtils.assertSqlCanBeParsedAndDeparsed( - "SELECT JSON_OBJECT(key 'person' value tp.account, key 'person' value tp.account) obj", true); + "SELECT JSON_OBJECT(key 'person' value tp.account, key 'person' value tp.account) obj", + true); TestUtils.assertSqlCanBeParsedAndDeparsed( "SELECT JSON_OBJECT( 'person' : tp.account) obj", true); @@ -180,7 +190,8 @@ public void testObjectIssue1504() throws JSQLParserException { "SELECT JSON_OBJECT( 'person' : '1', 'person' : '2') obj", true); TestUtils.assertSqlCanBeParsedAndDeparsed( - "SELECT JSON_OBJECT( 'person' VALUE tp.person, 'account' VALUE tp.account) obj", true); + "SELECT JSON_OBJECT( 'person' VALUE tp.person, 'account' VALUE tp.account) obj", + true); } @Test @@ -202,19 +213,24 @@ public void testArrayWithNullExpressions() throws JSQLParserException { TestUtils.assertExpressionCanBeParsedAndDeparsed("JSON_ARRAY( 1, 2, 3 )", true); TestUtils.assertExpressionCanBeParsedAndDeparsed("json_array(null on null)", true); TestUtils.assertExpressionCanBeParsedAndDeparsed("json_array(null null on null)", true); - TestUtils.assertExpressionCanBeParsedAndDeparsed("json_array(null, null null on null)", true); + TestUtils.assertExpressionCanBeParsedAndDeparsed("json_array(null, null null on null)", + true); TestUtils.assertExpressionCanBeParsedAndDeparsed("json_array()", true); } @Test public void testIssue1260() throws JSQLParserException { - TestUtils.assertSqlCanBeParsedAndDeparsed("select \n" + " cast((\n" + " select coalesce(\n" - + " json_arrayagg(json_array(\"v0\") order by \"t\".\"v0\"),\n" - + " json_array(null on null)\n" + " )\n" + " from (\n" - + " select 2 \"v0\"\n" + " union\n" + " select 4 \"ID\"\n" + " ) \"t\"\n" - + " ) as text)", true); + TestUtils.assertSqlCanBeParsedAndDeparsed( + "select \n" + " cast((\n" + " select coalesce(\n" + + " json_arrayagg(json_array(\"v0\") order by \"t\".\"v0\"),\n" + + " json_array(null on null)\n" + " )\n" + " from (\n" + + " select 2 \"v0\"\n" + " union\n" + " select 4 \"ID\"\n" + + " ) \"t\"\n" + + " ) as text)", + true); - TestUtils.assertExpressionCanBeParsedAndDeparsed("listagg( json_object(key 'v0' value \"v0\"), ',' )", true); + TestUtils.assertExpressionCanBeParsedAndDeparsed( + "listagg( json_object(key 'v0' value \"v0\"), ',' )", true); TestUtils.assertSqlCanBeParsedAndDeparsed("select (\n" + " select coalesce(\n" @@ -244,19 +260,24 @@ public void testIssue1371() throws JSQLParserException { @Test public void testJavaMethods() throws JSQLParserException { - String expressionStr = "JSON_OBJECT( KEY 'foo' VALUE bar FORMAT JSON, 'foo':bar, 'foo':bar ABSENT ON NULL WITHOUT UNIQUE KEYS)"; + String expressionStr = + "JSON_OBJECT( KEY 'foo' VALUE bar FORMAT JSON, 'foo':bar, 'foo':bar ABSENT ON NULL WITHOUT UNIQUE KEYS)"; JsonFunction jsonFunction = (JsonFunction) CCJSqlParserUtil.parseExpression(expressionStr); Assertions.assertEquals(JsonFunctionType.OBJECT, jsonFunction.getType()); - Assertions.assertNotEquals(jsonFunction.withType(JsonFunctionType.POSTGRES_OBJECT), jsonFunction.getType()); + Assertions.assertNotEquals(jsonFunction.withType(JsonFunctionType.POSTGRES_OBJECT), + jsonFunction.getType()); Assertions.assertEquals(3, jsonFunction.getKeyValuePairs().size()); - Assertions.assertEquals(new JsonKeyValuePair("'foo'", "bar", true, true), jsonFunction.getKeyValuePair(0)); + Assertions.assertEquals(new JsonKeyValuePair("'foo'", "bar", true, true), + jsonFunction.getKeyValuePair(0)); jsonFunction.setOnNullType(JsonAggregateOnNullType.NULL); - Assertions.assertEquals(JsonAggregateOnNullType.ABSENT, jsonFunction.withOnNullType(JsonAggregateOnNullType.ABSENT).getOnNullType()); + Assertions.assertEquals(JsonAggregateOnNullType.ABSENT, + jsonFunction.withOnNullType(JsonAggregateOnNullType.ABSENT).getOnNullType()); jsonFunction.setUniqueKeysType(JsonAggregateUniqueKeysType.WITH); - Assertions.assertEquals(JsonAggregateUniqueKeysType.WITH, jsonFunction.withUniqueKeysType(JsonAggregateUniqueKeysType.WITH).getUniqueKeysType()); + Assertions.assertEquals(JsonAggregateUniqueKeysType.WITH, jsonFunction + .withUniqueKeysType(JsonAggregateUniqueKeysType.WITH).getUniqueKeysType()); } } diff --git a/src/test/java/net/sf/jsqlparser/expression/LambdaExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/LambdaExpressionTest.java new file mode 100644 index 000000000..1d51dbe99 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/LambdaExpressionTest.java @@ -0,0 +1,38 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class LambdaExpressionTest { + + @Test + void testLambdaFunctionSingleParameter() throws JSQLParserException { + String sqlStr = "select list_transform( split('test', ''), x -> unicode(x) )"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Disabled + @Test + // wip, right now the Grammar works but collides with Multi Value Lists + void testLambdaFunctionMultipleParameter() throws JSQLParserException { + String sqlStr = "SELECT list_transform(\n" + + " [1, 2, 3],\n" + + " x -> list_reduce([4, 5, 6], (a, b) -> a + b) + x\n" + + " )"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + +} diff --git a/src/test/java/net/sf/jsqlparser/expression/LikeExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/LikeExpressionTest.java index 3840d0935..d87614566 100644 --- a/src/test/java/net/sf/jsqlparser/expression/LikeExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/LikeExpressionTest.java @@ -26,119 +26,96 @@ public class LikeExpressionTest { public void testLikeWithEscapeExpressionIssue420() throws JSQLParserException { TestUtils.assertExpressionCanBeParsedAndDeparsed("a LIKE ?1 ESCAPE ?2", true); - TestUtils.assertSqlCanBeParsedAndDeparsed("select * from dual where a LIKE ?1 ESCAPE ?2", true); + TestUtils.assertSqlCanBeParsedAndDeparsed("select * from dual where a LIKE ?1 ESCAPE ?2", + true); } @Test public void testEscapeExpressionIssue1638() throws JSQLParserException { String sqlStr = "select case \n" - + " when id_portfolio like '%\\_1' escape '\\' then '1'\n" - + " end"; + + " when id_portfolio like '%\\_1' escape '\\' then '1'\n" + + " end"; TestUtils.assertSqlCanBeParsedAndDeparsed( - sqlStr - , true - , parser -> parser.withBackslashEscapeCharacter(false) - ); + sqlStr, true, parser -> parser.withBackslashEscapeCharacter(false)); Assertions.assertThrows(JSQLParserException.class, new Executable() { @Override public void execute() throws Throwable { CCJSqlParserUtil.parse( - sqlStr - , parser -> parser.withBackslashEscapeCharacter(true) - ); + sqlStr, parser -> parser.withBackslashEscapeCharacter(true)); } }); } @Test public void testEscapingIssue1209() throws JSQLParserException { - String sqlStr="INSERT INTO \"a\".\"b\"(\"c\", \"d\", \"e\") VALUES ('c c\\', 'dd', 'ee\\')"; + String sqlStr = + "INSERT INTO \"a\".\"b\"(\"c\", \"d\", \"e\") VALUES ('c c\\', 'dd', 'ee\\')"; TestUtils.assertSqlCanBeParsedAndDeparsed( - sqlStr - , true - , parser -> parser.withBackslashEscapeCharacter(false) - ); + sqlStr, true, parser -> parser.withBackslashEscapeCharacter(false)); } @Test public void testEscapingIssue1173() throws JSQLParserException { - String sqlStr="update PARAM_TBL set PARA_DESC = null where PARA_DESC = '\\' and DEFAULT_VALUE = '\\'"; + String sqlStr = + "update PARAM_TBL set PARA_DESC = null where PARA_DESC = '\\' and DEFAULT_VALUE = '\\'"; TestUtils.assertSqlCanBeParsedAndDeparsed( - sqlStr - , true - , parser -> parser.withBackslashEscapeCharacter(false) - ); + sqlStr, true, parser -> parser.withBackslashEscapeCharacter(false)); } @Test public void testEscapingIssue1172() throws JSQLParserException { - String sqlStr="SELECT A ALIA1, CASE WHEN B LIKE 'ABC\\_%' ESCAPE '\\' THEN 'DEF' ELSE 'CCCC' END AS OBJ_SUB_TYPE FROM TABLE2"; + String sqlStr = + "SELECT A ALIA1, CASE WHEN B LIKE 'ABC\\_%' ESCAPE '\\' THEN 'DEF' ELSE 'CCCC' END AS OBJ_SUB_TYPE FROM TABLE2"; TestUtils.assertSqlCanBeParsedAndDeparsed( - sqlStr - , true - , parser -> parser.withBackslashEscapeCharacter(false) - ); + sqlStr, true, parser -> parser.withBackslashEscapeCharacter(false)); } @Test public void testEscapingIssue832() throws JSQLParserException { - String sqlStr="SELECT * FROM T1 WHERE (name LIKE ? ESCAPE '\\') AND (description LIKE ? ESCAPE '\\')"; + String sqlStr = + "SELECT * FROM T1 WHERE (name LIKE ? ESCAPE '\\') AND (description LIKE ? ESCAPE '\\')"; TestUtils.assertSqlCanBeParsedAndDeparsed( - sqlStr - , true - , parser -> parser.withBackslashEscapeCharacter(false) - ); + sqlStr, true, parser -> parser.withBackslashEscapeCharacter(false)); } @Test public void testEscapingIssue827() throws JSQLParserException { - String sqlStr="INSERT INTO my_table (my_column_1, my_column_2) VALUES ('my_value_1\\', 'my_value_2')"; + String sqlStr = + "INSERT INTO my_table (my_column_1, my_column_2) VALUES ('my_value_1\\', 'my_value_2')"; TestUtils.assertSqlCanBeParsedAndDeparsed( - sqlStr - , true - , parser -> parser.withBackslashEscapeCharacter(false) - ); + sqlStr, true, parser -> parser.withBackslashEscapeCharacter(false)); } @Test public void testEscapingIssue578() throws JSQLParserException { - String sqlStr="SELECT * FROM t1 WHERE UPPER(t1.TIPCOR_A8) like ? ESCAPE '' ORDER BY PERFILB2||TRANSLATE(UPPER(AP1SOL10 || ' ' || AP2SOL10 || ',' || NOMSOL10), '?', 'A') asc"; + String sqlStr = + "SELECT * FROM t1 WHERE UPPER(t1.TIPCOR_A8) like ? ESCAPE '' ORDER BY PERFILB2||TRANSLATE(UPPER(AP1SOL10 || ' ' || AP2SOL10 || ',' || NOMSOL10), '?', 'A') asc"; TestUtils.assertSqlCanBeParsedAndDeparsed( - sqlStr - , true - , parser -> parser.withBackslashEscapeCharacter(false) - ); + sqlStr, true, parser -> parser.withBackslashEscapeCharacter(false)); } @Test public void testEscapingIssue875() throws JSQLParserException { - String sqlStr="insert into standard_table(gmt_create, gmt_modified, config_name, standard_code) values (now(), now(), null, 'if \n" - + "@fac.sql_type in \n" - + "[ ''UPDATE'', ''DELETE'', ''INSERT'', ''INSERT_SELECT''] \n" - + "then \n" - + "@act.allow_submit \n" - + "end \n" - + "')" - ; + String sqlStr = + "insert into standard_table(gmt_create, gmt_modified, config_name, standard_code) values (now(), now(), null, 'if \n" + + "@fac.sql_type in \n" + + "[ ''UPDATE'', ''DELETE'', ''INSERT'', ''INSERT_SELECT''] \n" + + "then \n" + + "@act.allow_submit \n" + + "end \n" + + "')"; TestUtils.assertSqlCanBeParsedAndDeparsed( - sqlStr - , true - , parser -> parser.withBackslashEscapeCharacter(false) - ); + sqlStr, true, parser -> parser.withBackslashEscapeCharacter(false)); - sqlStr="insert into standard_table(gmt_create, gmt_modified, config_name, standard_code) values (now(), now(), null, 'if \n" - + "@fac.sql_type in \n" - + "[ \\'UPDATE\\', \\'DELETE\\', \\'INSERT\\', \\'INSERT_SELECT\\'] \n" - + "then \n" - + "@act.allow_submit \n" - + "end \n" - + "')" - ; + sqlStr = "insert into standard_table(gmt_create, gmt_modified, config_name, standard_code) values (now(), now(), null, 'if \n" + + "@fac.sql_type in \n" + + "[ \\'UPDATE\\', \\'DELETE\\', \\'INSERT\\', \\'INSERT_SELECT\\'] \n" + + "then \n" + + "@act.allow_submit \n" + + "end \n" + + "')"; TestUtils.assertSqlCanBeParsedAndDeparsed( - sqlStr - , true - , parser -> parser.withBackslashEscapeCharacter(true) - ); + sqlStr, true, parser -> parser.withBackslashEscapeCharacter(true)); } } diff --git a/src/test/java/net/sf/jsqlparser/expression/LimitExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/LimitExpressionTest.java index 59151487f..70dbd2103 100644 --- a/src/test/java/net/sf/jsqlparser/expression/LimitExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/LimitExpressionTest.java @@ -61,6 +61,6 @@ public void testMethods() throws JSQLParserException { plainSelect = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); AllValue allValue = plainSelect.getLimit().getRowCount(AllValue.class); - allValue.accept(new ExpressionVisitorAdapter()); + allValue.accept(new ExpressionVisitorAdapter(), null); } } diff --git a/src/test/java/net/sf/jsqlparser/expression/OracleNamedFunctionParameterTest.java b/src/test/java/net/sf/jsqlparser/expression/OracleNamedFunctionParameterTest.java index f662c5a0b..98c2028a1 100644 --- a/src/test/java/net/sf/jsqlparser/expression/OracleNamedFunctionParameterTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/OracleNamedFunctionParameterTest.java @@ -30,19 +30,19 @@ public class OracleNamedFunctionParameterTest { /** - * This test will parse and deparse the statement and assures the functional coverage by JSQLParser. + * This test will parse and deparse the statement and assures the functional coverage by + * JSQLParser. * * @throws net.sf.jsqlparser.JSQLParserException */ @Test public void testExpression() throws JSQLParserException { - String sqlStr - = "select r.*, test.numeric_function ( p_1 => r.param1, p_2 => r.param2 ) as resultaat2"; + String sqlStr = + "select r.*, test.numeric_function ( p_1 => r.param1, p_2 => r.param2 ) as resultaat2"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); - sqlStr - = "exec dbms_stats.gather_schema_stats(\n" + sqlStr = "exec dbms_stats.gather_schema_stats(\n" + " ownname => 'COMMON', \n" + " estimate_percent => dbms_stats.auto_sample_size, \n" + " method_opt => 'for all columns size auto', \n" @@ -54,49 +54,50 @@ public void testExpression() throws JSQLParserException { } /** - * This test will trigger the method {@link ExpressionVisitorAdaptor#visit() Visit Method} in the - * ExpressionVisitorAdaptor needed for the Code Coverage. + * This test will trigger the method {@link ExpressionVisitorAdaptor#visit() Visit Method} in + * the ExpressionVisitorAdaptor needed for the Code Coverage. * * @throws net.sf.jsqlparser.JSQLParserException */ @Test public void testExpressionVisitorAdaptor() throws JSQLParserException { - String sqlStr - = "select r.*, test.numeric_function ( p_1 => r.param1, p_2 => r.param2 ) as resultaat2"; + String sqlStr = + "select r.*, test.numeric_function ( p_1 => r.param1, p_2 => r.param2 ) as resultaat2"; CCJSqlParserUtil.parse(sqlStr).accept(new StatementVisitorAdapter()); // alternatively, for the Expression only - CCJSqlParserUtil.parseExpression("p_1 => r.param1").accept(new ExpressionVisitorAdapter()); + CCJSqlParserUtil.parseExpression("p_1 => r.param1").accept(new ExpressionVisitorAdapter(), + null); } /** - * This test will trigger the method {@link TableNamesFinder#visit() Visit Method} in the TableNamesFinder needed - * for the Code Coverage. + * This test will trigger the method {@link TableNamesFinder#visit() Visit Method} in the + * TableNamesFinder needed for the Code Coverage. * * @throws net.sf.jsqlparser.JSQLParserException */ @Test public void testTableNamesFinder() throws JSQLParserException { - String sqlStr - = "select r.*, test.numeric_function ( p_1 => r.param1, p_2 => r.param2 ) as resultaat2 from test_table"; + String sqlStr = + "select r.*, test.numeric_function ( p_1 => r.param1, p_2 => r.param2 ) as resultaat2 from test_table"; Statement statement = CCJSqlParserUtil.parse(sqlStr); - List tables = new TablesNamesFinder().getTableList(statement); + List tables = new TablesNamesFinder<>().getTableList(statement); assertEquals(1, tables.size()); assertTrue(tables.contains("test_table")); } /** - * This test will trigger the method {@link ExpressionValidator#visit() Visit Method} in the ExpressionValidator - * needed for the Code Coverage. + * This test will trigger the method {@link ExpressionValidator#visit() Visit Method} in the + * ExpressionValidator needed for the Code Coverage. * * @throws net.sf.jsqlparser.JSQLParserException */ @Test public void testValidator() throws JSQLParserException { - String sqlStr - = "select r.*, test.numeric_function ( p_1 => r.param1, p_2 => r.param2 ) as resultaat2"; + String sqlStr = + "select r.*, test.numeric_function ( p_1 => r.param1, p_2 => r.param2 ) as resultaat2"; ValidationTestAsserts.validateNoErrors(sqlStr, 1, DatabaseType.ORACLE); } diff --git a/src/test/java/net/sf/jsqlparser/expression/OverlapsConditionTest.java b/src/test/java/net/sf/jsqlparser/expression/OverlapsConditionTest.java index d91de5add..cd2c92bb1 100644 --- a/src/test/java/net/sf/jsqlparser/expression/OverlapsConditionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/OverlapsConditionTest.java @@ -17,11 +17,16 @@ public class OverlapsConditionTest { @Test public void testOverlapsCondition() throws JSQLParserException { - TestUtils.assertExpressionCanBeParsedAndDeparsed("(t1.start, t1.end) overlaps (t2.start, t2.end)", true); + TestUtils.assertExpressionCanBeParsedAndDeparsed( + "(t1.start, t1.end) overlaps (t2.start, t2.end)", true); - TestUtils.assertSqlCanBeParsedAndDeparsed("select * from dual where (start_one, end_one) overlaps (start_two, end_two)", true); + TestUtils.assertSqlCanBeParsedAndDeparsed( + "select * from dual where (start_one, end_one) overlaps (start_two, end_two)", + true); - TestUtils.assertSqlCanBeParsedAndDeparsed("select * from t1 left join t2 on (t1.start, t1.end) overlaps (t2.start, t2.end)", true); + TestUtils.assertSqlCanBeParsedAndDeparsed( + "select * from t1 left join t2 on (t1.start, t1.end) overlaps (t2.start, t2.end)", + true); } } diff --git a/src/test/java/net/sf/jsqlparser/expression/SafeCastExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/SafeCastExpressionTest.java index 8630c6264..0d58e5c20 100644 --- a/src/test/java/net/sf/jsqlparser/expression/SafeCastExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/SafeCastExpressionTest.java @@ -17,7 +17,10 @@ public class SafeCastExpressionTest { @Test public void testSafeCast() throws JSQLParserException { - TestUtils.assertExpressionCanBeParsedAndDeparsed("SAFE_CAST(ROW(dataid, value, calcMark) AS ROW(datapointid CHAR, value CHAR, calcMark CHAR))", true); - TestUtils.assertExpressionCanBeParsedAndDeparsed("SAFE_CAST(ROW(dataid, value, calcMark) AS testcol)", true); + TestUtils.assertExpressionCanBeParsedAndDeparsed( + "SAFE_CAST(ROW(dataid, value, calcMark) AS ROW(datapointid CHAR, value CHAR, calcMark CHAR))", + true); + TestUtils.assertExpressionCanBeParsedAndDeparsed( + "SAFE_CAST(ROW(dataid, value, calcMark) AS testcol)", true); } } diff --git a/src/test/java/net/sf/jsqlparser/expression/StructTypeTest.java b/src/test/java/net/sf/jsqlparser/expression/StructTypeTest.java new file mode 100644 index 000000000..c6645b4c9 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/StructTypeTest.java @@ -0,0 +1,82 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.SelectItem; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +import java.util.List; + +class StructTypeTest { + @Test + void testStructTypeBigQuery() throws JSQLParserException { + String sqlStr = "SELECT t, len, FORMAT('%T', LPAD(t, len)) AS LPAD FROM UNNEST([\n" + + " STRUCT('abc' AS t, 5 AS len),\n" + + " ('abc', 2),\n" + + " ('例子', 4)\n" + + "])"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT STRUCT(1, t.str_col)"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT STRUCT(1 AS a, 'abc' AS b)"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT STRUCT(1, t.str_col)"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testStructTypeDuckDB() throws JSQLParserException { + // @todo: check why the white-space after the "{" is needed?! + String sqlStr = "SELECT { t:'abc',len:5}"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT UNNEST({ t:'abc', len:5 })"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT * from (SELECT UNNEST([{ t:'abc', len:5 }]))"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT * from (SELECT UNNEST([{ t:'abc', len:5 }, ('abc', 6) ], recursive => true))"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testStructTypeConstructorDuckDB() throws JSQLParserException { + // @todo: check why the white-space after the "{" is needed?! + String sqlStr = "SELECT { t:'abc',len:5}"; + List> selectItems = List.of( + new SelectItem<>("abc", "t"), new SelectItem<>(5, "len")); + StructType struct = new StructType(StructType.Dialect.DUCKDB, selectItems); + PlainSelect select = new PlainSelect().withSelectItems(new SelectItem<>(struct)); + TestUtils.assertStatementCanBeDeparsedAs(select, sqlStr, true); + } + + @Test + void testStructTypeWithArgumentsDuckDB() throws JSQLParserException { + // @todo: check why the white-space after the "{" is needed?! + String sqlStr = "SELECT { t:'abc',len:5}::STRUCT( t VARCHAR, len INTEGER)"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT t, len, LPAD(t, len, ' ') as padded from (\n" + + "select Unnest([\n" + + " { t:'abc', len: 5}::STRUCT(t VARCHAR, len INTEGER),\n" + + " { t:'abc', len: 5},\n" + + " ('abc', 2),\n" + + " ('例子', 4)\n" + + "], \"recursive\" => true))"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } +} diff --git a/src/test/java/net/sf/jsqlparser/expression/TranscodingFunctionTest.java b/src/test/java/net/sf/jsqlparser/expression/TranscodingFunctionTest.java index 62599c6e0..090317ff0 100644 --- a/src/test/java/net/sf/jsqlparser/expression/TranscodingFunctionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/TranscodingFunctionTest.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.expression; import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.statement.Statement; import org.junit.jupiter.api.Test; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; @@ -49,4 +50,14 @@ void testIssue1257() throws JSQLParserException { + "ORDER BY convert(name using GBK) ASC"; assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + + @Test + public void testUnPivotWithAlias() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "SELECT cast(1 as Decimal(18,2))", true); + + Statement st = assertSqlCanBeParsedAndDeparsed( + "SELECT Convert( Decimal(18,2) , 1 )", true); + } } diff --git a/src/test/java/net/sf/jsqlparser/expression/mysql/MySqlSqlCalcFoundRowsTest.java b/src/test/java/net/sf/jsqlparser/expression/mysql/MySqlSqlCalcFoundRowsTest.java index abb816607..531d8968e 100644 --- a/src/test/java/net/sf/jsqlparser/expression/mysql/MySqlSqlCalcFoundRowsTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/mysql/MySqlSqlCalcFoundRowsTest.java @@ -52,15 +52,19 @@ public void testPossibleParsingWithSqlCalcFoundRowsHint() throws JSQLParserExcep } private void accept(Statement statement, final MySqlSqlCalcFoundRowRef ref) { - statement.accept(new StatementVisitorAdapter() { + SelectVisitorAdapter selectVisitorAdapter = new SelectVisitorAdapter<>() { @Override - public void visit(Select select) { - select.accept(new SelectVisitorAdapter() { - @Override - public void visit(PlainSelect plainSelect) { - ref.sqlCalcFoundRows = plainSelect.getMySqlSqlCalcFoundRows(); - } - }); + public Void visit(PlainSelect plainSelect, S parameters) { + ref.sqlCalcFoundRows = plainSelect.getMySqlSqlCalcFoundRows(); + return null; + } + }; + + statement.accept(new StatementVisitorAdapter() { + @Override + public Void visit(Select select, S context) { + select.accept(selectVisitorAdapter, context); + return null; } }); diff --git a/src/test/java/net/sf/jsqlparser/expression/operators/XorTest.java b/src/test/java/net/sf/jsqlparser/expression/operators/XorTest.java new file mode 100644 index 000000000..3b7d932fa --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/operators/XorTest.java @@ -0,0 +1,23 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression.operators; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +public class XorTest { + + @Test + void testXorIssue1980() throws JSQLParserException { + String sqlStr = "SELECT a or b from c"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } +} diff --git a/src/test/java/net/sf/jsqlparser/expression/operators/arithmetic/ArithmethicTests.java b/src/test/java/net/sf/jsqlparser/expression/operators/arithmetic/ArithmethicTests.java index 24bca2a8f..d78ce7971 100644 --- a/src/test/java/net/sf/jsqlparser/expression/operators/arithmetic/ArithmethicTests.java +++ b/src/test/java/net/sf/jsqlparser/expression/operators/arithmetic/ArithmethicTests.java @@ -19,13 +19,15 @@ public class ArithmethicTests { @Test public void testAddition() { assertEquals("1 + a", - new Addition().withLeftExpression(new LongValue(1)).withRightExpression(new Column("a")).toString()); + new Addition().withLeftExpression(new LongValue(1)) + .withRightExpression(new Column("a")).toString()); } @Test public void testBitwiseAnd() { assertEquals("a & b", - new BitwiseAnd().withLeftExpression(new Column("a")).withRightExpression(new Column("b")).toString()); + new BitwiseAnd().withLeftExpression(new Column("a")) + .withRightExpression(new Column("b")).toString()); } @Test @@ -37,32 +39,37 @@ public void testBitwiseLeftShift() { @Test public void testBitwiseOr() { assertEquals("a | b", - new BitwiseOr().withLeftExpression(new Column("a")).withRightExpression(new Column("b")).toString()); + new BitwiseOr().withLeftExpression(new Column("a")) + .withRightExpression(new Column("b")).toString()); } @Test public void testBitwiseRightShift() { assertEquals("a >> b", - new BitwiseRightShift().withLeftExpression(new Column("a")).withRightExpression(new Column("b")) + new BitwiseRightShift().withLeftExpression(new Column("a")) + .withRightExpression(new Column("b")) .toString()); } @Test public void testBitwiseXor() { assertEquals("a ^ b", - new BitwiseXor().withLeftExpression(new Column("a")).withRightExpression(new Column("b")).toString()); + new BitwiseXor().withLeftExpression(new Column("a")) + .withRightExpression(new Column("b")).toString()); } @Test public void testConcat() { assertEquals("a || b", - new Concat().withLeftExpression(new Column("a")).withRightExpression(new Column("b")).toString()); + new Concat().withLeftExpression(new Column("a")) + .withRightExpression(new Column("b")).toString()); } @Test public void testDivision() { assertEquals("a / b", - new Division().withLeftExpression(new Column("a")).withRightExpression(new Column("b")).toString()); + new Division().withLeftExpression(new Column("a")) + .withRightExpression(new Column("b")).toString()); } @Test @@ -74,13 +81,15 @@ public void testIntegerDivision() { @Test public void testModulo() { assertEquals("3 % 2", - new Modulo().withLeftExpression(new LongValue(3)).withRightExpression(new LongValue(2)).toString()); + new Modulo().withLeftExpression(new LongValue(3)) + .withRightExpression(new LongValue(2)).toString()); } @Test public void testMultiplication() { assertEquals("5 * 2", - new Multiplication().withLeftExpression(new LongValue(5)).withRightExpression(new LongValue(2)) + new Multiplication().withLeftExpression(new LongValue(5)) + .withRightExpression(new LongValue(2)) .toString()); } diff --git a/src/test/java/net/sf/jsqlparser/expression/operators/arithmetic/ConcatTest.java b/src/test/java/net/sf/jsqlparser/expression/operators/arithmetic/ConcatTest.java new file mode 100644 index 000000000..d5464b2c9 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/operators/arithmetic/ConcatTest.java @@ -0,0 +1,65 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression.operators.arithmetic; + +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.LongValue; +import net.sf.jsqlparser.expression.NullValue; +import net.sf.jsqlparser.expression.StringValue; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class ConcatTest { + + @Test + void concatTest() { + Expression expression = + Concat.concat(new StringValue("A"), new StringValue("B"), new StringValue("C")); + Assertions.assertInstanceOf(Concat.class, expression); + Assertions.assertEquals("'A' || 'B' || 'C'", expression.toString()); + + expression = Concat.concat(new StringValue("A")); + Assertions.assertInstanceOf(StringValue.class, expression); + Assertions.assertEquals("'A'", expression.toString()); + + expression = Concat.concat(); + Assertions.assertInstanceOf(NullValue.class, expression); + Assertions.assertEquals("NULL", expression.toString()); + } + + void addTest() { + Expression expression = Addition.add(new LongValue(1), new LongValue(2), new LongValue(3)); + Assertions.assertInstanceOf(Addition.class, expression); + Assertions.assertEquals("1 + 2 + 3", expression.toString()); + + expression = Addition.add(new LongValue(1)); + Assertions.assertInstanceOf(LongValue.class, expression); + Assertions.assertEquals("1", expression.toString()); + + expression = Addition.add(); + Assertions.assertInstanceOf(NullValue.class, expression); + Assertions.assertEquals("NULL", expression.toString()); + } + + void multiplyTest() { + Expression expression = + Multiplication.multiply(new LongValue(1), new LongValue(2), new LongValue(3)); + Assertions.assertInstanceOf(Addition.class, expression); + Assertions.assertEquals("1 + 2 + 3", expression.toString()); + + expression = Multiplication.multiply(new LongValue(1)); + Assertions.assertInstanceOf(LongValue.class, expression); + Assertions.assertEquals("1", expression.toString()); + + expression = Multiplication.multiply(); + Assertions.assertInstanceOf(NullValue.class, expression); + Assertions.assertEquals("NULL", expression.toString()); + } +} diff --git a/src/test/java/net/sf/jsqlparser/expression/operators/relational/BetweenTest.java b/src/test/java/net/sf/jsqlparser/expression/operators/relational/BetweenTest.java index ebe632c17..56f2f44df 100644 --- a/src/test/java/net/sf/jsqlparser/expression/operators/relational/BetweenTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/operators/relational/BetweenTest.java @@ -18,7 +18,8 @@ class BetweenTest { @Test void testBetweenWithAdditionIssue1948() throws JSQLParserException { - String sqlStr = "select col FROM tbl WHERE start_time BETWEEN 1706024185 AND MyFunc() - 734400"; + String sqlStr = + "select col FROM tbl WHERE start_time BETWEEN 1706024185 AND MyFunc() - 734400"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } } diff --git a/src/test/java/net/sf/jsqlparser/expression/operators/relational/FullTextSearchExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/operators/relational/FullTextSearchExpressionTest.java index 1ff244564..8a1c61714 100644 --- a/src/test/java/net/sf/jsqlparser/expression/operators/relational/FullTextSearchExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/operators/relational/FullTextSearchExpressionTest.java @@ -31,7 +31,8 @@ public void testFullTextSearchExpressionWithParameters() throws JSQLParserExcept public void testIssue1223() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed("select\n" + "c.*,\n" + "match (name) against (?) as full_text\n" + "from\n" + "commodity c\n" + "where\n" - + "match (name) against (?)\n" + "and c.deleted = 0\n" + "order by\n" + "full_text desc", + + "match (name) against (?)\n" + "and c.deleted = 0\n" + "order by\n" + + "full_text desc", true); } } diff --git a/src/test/java/net/sf/jsqlparser/expression/operators/relational/IsNullExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/operators/relational/IsNullExpressionTest.java index 98cbc695b..b7a5ec934 100644 --- a/src/test/java/net/sf/jsqlparser/expression/operators/relational/IsNullExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/operators/relational/IsNullExpressionTest.java @@ -20,4 +20,10 @@ void testNotNullExpression() throws JSQLParserException { String sqlStr = "select * from mytable where 1 notnull"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + void testStringConstructor() { + IsNullExpression isNullExpression = new IsNullExpression("x", true); + TestUtils.assertExpressionCanBeDeparsedAs(isNullExpression, "x IS NOT NULL"); + } } diff --git a/src/test/java/net/sf/jsqlparser/expression/operators/relational/LikeExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/operators/relational/LikeExpressionTest.java index 073a2cef2..acc1ef6be 100644 --- a/src/test/java/net/sf/jsqlparser/expression/operators/relational/LikeExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/operators/relational/LikeExpressionTest.java @@ -49,4 +49,13 @@ void testNotRLikeIssue1553() throws JSQLParserException { String sqlStr = "select * from test where id not rlike '111'"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + void testDuckDBSimuilarTo() throws JSQLParserException { + String sqlStr = "SELECT v\n" + + " FROM strings\n" + + " WHERE v SIMILAR TO 'San* [fF].*'\n" + + " ORDER BY v;"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/parser/ASTNodeAccessImplTest.java b/src/test/java/net/sf/jsqlparser/parser/ASTNodeAccessImplTest.java new file mode 100644 index 000000000..e9f757e4e --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/parser/ASTNodeAccessImplTest.java @@ -0,0 +1,36 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.parser; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.AnalyticExpression; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.statement.select.SelectItem; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; + +class ASTNodeAccessImplTest { + @Test + void testGetParent() throws JSQLParserException { + String sqlStr = "select listagg(sellerid)\n" + + "within group (order by sellerid)\n" + + "over() AS list from winsales;"; + + PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); + AnalyticExpression expression = + (AnalyticExpression) select.getSelectItem(0).getExpression(); + + assertInstanceOf(SelectItem.class, expression.getParent()); + assertEquals(select, expression.getParent(Select.class)); + } +} diff --git a/src/test/java/net/sf/jsqlparser/parser/CCJSqlParserUtilTest.java b/src/test/java/net/sf/jsqlparser/parser/CCJSqlParserUtilTest.java index b7caf3a64..6546eb25c 100644 --- a/src/test/java/net/sf/jsqlparser/parser/CCJSqlParserUtilTest.java +++ b/src/test/java/net/sf/jsqlparser/parser/CCJSqlParserUtilTest.java @@ -9,29 +9,12 @@ */ package net.sf.jsqlparser.parser; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.ByteArrayInputStream; -import java.io.StringReader; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.LongValue; -import net.sf.jsqlparser.expression.Parenthesis; import net.sf.jsqlparser.expression.operators.arithmetic.Addition; import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.Statements; @@ -39,9 +22,30 @@ import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.TableStatement; import net.sf.jsqlparser.test.MemoryLeakVerifier; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; +import java.io.ByteArrayInputStream; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class CCJSqlParserUtilTest { private final static String INVALID_SQL = "" @@ -98,7 +102,7 @@ public void testParseExpression2() throws Exception { assertTrue(result instanceof Multiplication); Multiplication mult = (Multiplication) result; assertTrue(mult.getLeftExpression() instanceof LongValue); - assertTrue(mult.getRightExpression() instanceof Parenthesis); + assertTrue(mult.getRightExpression() instanceof ParenthesedExpressionList); } @Test @@ -225,15 +229,18 @@ public void testParseStatementsFail() throws Exception { assertDoesNotThrow(new Executable() { @Override public void execute() throws Throwable { - final Statements statements = CCJSqlParserUtil.parseStatements(sqlStr); + final Statements statements = CCJSqlParserUtil.parseStatements( + sqlStr, + parser -> parser.withErrorRecovery(true).withUnsupportedStatements(true)); assertEquals(2, statements.size()); - assertTrue(statements.get(0) instanceof PlainSelect); - assertTrue(statements.get(1) instanceof UnsupportedStatement); + assertInstanceOf(PlainSelect.class, statements.get(0)); + assertInstanceOf(UnsupportedStatement.class, statements.get(1)); } }); } @Test + @Disabled public void testParseASTFail() throws Exception { assertThrows(JSQLParserException.class, () -> CCJSqlParserUtil.parseAST("select * from dual;WHATEVER!!")); @@ -514,4 +521,27 @@ void testParseEmpty() throws JSQLParserException { assertNull(CCJSqlParserUtil.parse("")); assertNull(CCJSqlParserUtil.parse((String) null)); } + + @Test + void testSingleStatementWithEmptyLines() throws JSQLParserException { + String sqlStr = "update shop_info set title=?,\n" + + "\n" + + "\n" + + "\n" + + "content='abc\n" + + "\n" + + "\n" + + "\n" + + "def'\n" + + "where id=?"; + + Statement statement = CCJSqlParserUtil.parse(CCJSqlParserUtil.sanitizeSingleSql(sqlStr)); + TestUtils.assertStatementCanBeDeparsedAs(statement, "update shop_info set title=?,\n" + + "content='abc\n" + + "\n" + + "\n" + + "\n" + + "def'\n" + + "where id=?", true); + } } diff --git a/src/test/java/net/sf/jsqlparser/parser/JSQLParserExceptionTest.java b/src/test/java/net/sf/jsqlparser/parser/JSQLParserExceptionTest.java index 34758fe48..7b5b033b2 100644 --- a/src/test/java/net/sf/jsqlparser/parser/JSQLParserExceptionTest.java +++ b/src/test/java/net/sf/jsqlparser/parser/JSQLParserExceptionTest.java @@ -58,7 +58,8 @@ public void testExceptionPrintStacktraceNoCause() throws Exception { assertFalse(sw.toString().contains("BRATKARTOFFEL")); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ex1.printStackTrace(new PrintStream(bos, true)); - assertFalse(new String(bos.toByteArray(), StandardCharsets.UTF_8).contains("BRATKARTOFFEL")); + assertFalse( + new String(bos.toByteArray(), StandardCharsets.UTF_8).contains("BRATKARTOFFEL")); } @Test diff --git a/src/test/java/net/sf/jsqlparser/parser/ParserKeywordsUtilsTest.java b/src/test/java/net/sf/jsqlparser/parser/ParserKeywordsUtilsTest.java index b1e9ed937..762620788 100644 --- a/src/test/java/net/sf/jsqlparser/parser/ParserKeywordsUtilsTest.java +++ b/src/test/java/net/sf/jsqlparser/parser/ParserKeywordsUtilsTest.java @@ -9,7 +9,10 @@ */ package net.sf.jsqlparser.parser; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; import org.javacc.jjtree.JJTree; +import org.javacc.parser.JavaCCErrors; import org.javacc.parser.JavaCCGlobals; import org.javacc.parser.JavaCCParser; import org.javacc.parser.RCharacterList; @@ -39,7 +42,6 @@ import java.util.Set; import java.util.TreeSet; import java.util.logging.Logger; -import org.javacc.parser.JavaCCErrors; class ParserKeywordsUtilsTest { @@ -202,4 +204,10 @@ void compareKeywordLists() throws Exception { } } } + + @Test + void testBase64() throws JSQLParserException { + String sqlStr = "SELECT base64('Spark SQL') AS b;"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/parser/feature/FeatureSetTest.java b/src/test/java/net/sf/jsqlparser/parser/feature/FeatureSetTest.java index 850f9a504..fdf2c8745 100644 --- a/src/test/java/net/sf/jsqlparser/parser/feature/FeatureSetTest.java +++ b/src/test/java/net/sf/jsqlparser/parser/feature/FeatureSetTest.java @@ -19,7 +19,8 @@ public class FeatureSetTest { @Test public void testGetNotContained() { assertEquals(EnumSet.of(Feature.select), new FeaturesAllowed(Feature.select, Feature.update) // - .getNotContained(new FeaturesAllowed(Feature.update, Feature.delete).getFeatures())); + .getNotContained( + new FeaturesAllowed(Feature.update, Feature.delete).getFeatures())); } @Test diff --git a/src/test/java/net/sf/jsqlparser/schema/ColumnTest.java b/src/test/java/net/sf/jsqlparser/schema/ColumnTest.java index 953a7ca9a..4c8469429 100644 --- a/src/test/java/net/sf/jsqlparser/schema/ColumnTest.java +++ b/src/test/java/net/sf/jsqlparser/schema/ColumnTest.java @@ -9,9 +9,13 @@ */ package net.sf.jsqlparser.schema; -import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + /** * * @author tw @@ -30,4 +34,24 @@ public String toString() { assertEquals("anonymous class", myColumn.toString()); } + @Test + public void testConstructorNameParts() { + Column column = new Column(List.of("schema", "table", "column")); + assertThat(column.getColumnName()).isEqualTo("column"); + + Table table = column.getTable(); + assertThat(table.getNameParts()).containsExactly("table", "schema"); + assertThat(table.getNamePartDelimiters()).containsExactly("."); + } + + @Test + public void testConstructorNamePartsAndDelimiters() { + Column column = new Column(List.of("a", "b", "c", "d"), List.of(":", ".", ":")); + assertThat(column.getColumnName()).isEqualTo("d"); + + Table table = column.getTable(); + assertThat(table.getNameParts()).containsExactly("c", "b", "a"); + assertThat(table.getNamePartDelimiters()).containsExactly(".", ":"); + } + } diff --git a/src/test/java/net/sf/jsqlparser/schema/SequenceTest.java b/src/test/java/net/sf/jsqlparser/schema/SequenceTest.java index a69c70920..ec027a8b5 100644 --- a/src/test/java/net/sf/jsqlparser/schema/SequenceTest.java +++ b/src/test/java/net/sf/jsqlparser/schema/SequenceTest.java @@ -32,7 +32,8 @@ public void testSetSchemaName() { @Test public void testSetDatabase() { - Sequence sequence = new Sequence().withName("foo").withSchemaName("bar").withDatabase(new Database("default")); + Sequence sequence = new Sequence().withName("foo").withSchemaName("bar") + .withDatabase(new Database("default")); assertThat(sequence.getDatabase().getDatabaseName()).isEqualTo("default"); assertThat(sequence.getFullyQualifiedName()).isEqualTo("default.bar.foo"); diff --git a/src/test/java/net/sf/jsqlparser/schema/ServerTest.java b/src/test/java/net/sf/jsqlparser/schema/ServerTest.java index 4b891499b..216248be9 100644 --- a/src/test/java/net/sf/jsqlparser/schema/ServerTest.java +++ b/src/test/java/net/sf/jsqlparser/schema/ServerTest.java @@ -57,7 +57,8 @@ public void testServerNameAndInstancePassValues() throws Exception { final Server server = new Server("SERVER", "INSTANCE"); assertEquals("SERVER", server.getServerName()); assertEquals("INSTANCE", server.getInstanceName()); - assertEquals(String.format("[%s\\%s]", "SERVER", "INSTANCE"), server.getFullyQualifiedName()); + assertEquals(String.format("[%s\\%s]", "SERVER", "INSTANCE"), + server.getFullyQualifiedName()); } @Test diff --git a/src/test/java/net/sf/jsqlparser/schema/TableTest.java b/src/test/java/net/sf/jsqlparser/schema/TableTest.java index 29569f6e0..5a3817251 100644 --- a/src/test/java/net/sf/jsqlparser/schema/TableTest.java +++ b/src/test/java/net/sf/jsqlparser/schema/TableTest.java @@ -17,7 +17,10 @@ import net.sf.jsqlparser.util.deparser.SelectDeParser; import org.junit.jupiter.api.Test; +import java.util.List; + import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -55,14 +58,15 @@ public void tableSetDatabaseIssue812() throws JSQLParserException { SelectDeParser deparser = new SelectDeParser(expressionDeParser, buffer) { @Override - public void visit(Table tableName) { + public StringBuilder visit(Table tableName, S parameters) { System.out.println(tableName); tableName.setDatabase(database); // Exception System.out.println(tableName.getDatabase()); + return null; } }; - deparser.visit((PlainSelect) select); + deparser.visit((PlainSelect) select, null); } @@ -73,4 +77,13 @@ public void testTableRemoveNameParts() { table.setSchemaName(null); assertThat(table.getFullyQualifiedName()).isEqualTo("DICTIONARY"); } + + @Test + public void testConstructorDelimitersInappropriateSize() { + assertThatThrownBy( + () -> new Table(List.of("a", "b", "c"), List.of("too", "many", "delimiters"))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining( + "the length of the delimiters list must be 1 less than nameParts"); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/AdaptersTest.java b/src/test/java/net/sf/jsqlparser/statement/AdaptersTest.java index 78d559a83..98c2044b7 100644 --- a/src/test/java/net/sf/jsqlparser/statement/AdaptersTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/AdaptersTest.java @@ -36,35 +36,40 @@ public void testAdapters() throws JSQLParserException { Statement stmnt = CCJSqlParserUtil.parse(sql); final Stack> params = new Stack<>(); - stmnt.accept(new StatementVisitorAdapter() { + stmnt.accept(new StatementVisitorAdapter() { @Override - public void visit(Select select) { - select.accept(new SelectVisitorAdapter() { + public Void visit(Select select, S context) { + select.accept(new SelectVisitorAdapter() { @Override - public void visit(PlainSelect plainSelect) { - plainSelect.getWhere().accept(new ExpressionVisitorAdapter() { + public Void visit(PlainSelect plainSelect, K context) { + plainSelect.getWhere().accept(new ExpressionVisitorAdapter() { @Override - protected void visitBinaryExpression(BinaryExpression expr) { + protected Void visitBinaryExpression(BinaryExpression expr, + J context) { if (!(expr instanceof AndExpression)) { params.push(new Pair<>(null, null)); } - super.visitBinaryExpression(expr); + return super.visitBinaryExpression(expr, context); } @Override - public void visit(Column column) { + public Void visit(Column column, J context) { params.push(new Pair<>(column.getColumnName(), params.pop().getRight())); + return null; } @Override - public void visit(JdbcNamedParameter parameter) { + public Void visit(JdbcNamedParameter parameter, J context) { params.push(new Pair<>(params.pop().getLeft(), parameter.getName())); + return null; } - }); + }, null); + return null; } - }); + }, null); + return null; } }); diff --git a/src/test/java/net/sf/jsqlparser/statement/BlockTest.java b/src/test/java/net/sf/jsqlparser/statement/BlockTest.java index e0d46acf7..99aedcbde 100644 --- a/src/test/java/net/sf/jsqlparser/statement/BlockTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/BlockTest.java @@ -28,17 +28,17 @@ public class BlockTest { @Test public void testGetStatements() throws JSQLParserException { String sqlStr = "begin\n" - + "select * from feature;\n" - + "end;"; + + "select * from feature;\n" + + "end;"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } @Test public void testBlock2() throws JSQLParserException { - String sqlStr="begin\n" - + "update table1 set a = 'xx' where b = 'condition1';\n" - + "update table1 set a = 'xx' where b = 'condition2';\n" - + "end;"; + String sqlStr = "begin\n" + + "update table1 set a = 'xx' where b = 'condition1';\n" + + "update table1 set a = 'xx' where b = 'condition2';\n" + + "end;"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } @@ -54,26 +54,26 @@ public void testBlockToStringIsNullSafe() throws JSQLParserException { Block block = new Block(); block.setStatements(null); assertEquals("BEGIN\n" - + "END", block.toString()); + + "END", block.toString()); } @Test public void testIfElseBlock() throws JSQLParserException { String sqlStr = "if (a=b) begin\n" - + "update table1 set a = 'xx' where b = 'condition1';\n" - + "update table1 set a = 'xx' where b = 'condition2';\n" - + "end"; + + "update table1 set a = 'xx' where b = 'condition1';\n" + + "update table1 set a = 'xx' where b = 'condition2';\n" + + "end"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); String sqlStr2 = "if (a=b) begin\n" - + "update table1 set a = 'xx' where b = 'condition1';\n" - + "update table1 set a = 'xx' where b = 'condition2';\n" - + "end;\n" - + "else begin\n" - + "update table1 set a = 'xx' where b = 'condition1';\n" - + "update table1 set a = 'xx' where b = 'condition2';\n" - + "end;"; + + "update table1 set a = 'xx' where b = 'condition1';\n" + + "update table1 set a = 'xx' where b = 'condition2';\n" + + "end;\n" + + "else begin\n" + + "update table1 set a = 'xx' where b = 'condition1';\n" + + "update table1 set a = 'xx' where b = 'condition2';\n" + + "end;"; Statements statements = CCJSqlParserUtil.parseStatements(sqlStr2); for (Statement stm : statements.getStatements()) { diff --git a/src/test/java/net/sf/jsqlparser/statement/DeclareStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/DeclareStatementTest.java index 647bb3d3e..c8b5ca1ac 100644 --- a/src/test/java/net/sf/jsqlparser/statement/DeclareStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/DeclareStatementTest.java @@ -28,8 +28,7 @@ */ public class DeclareStatementTest { - public DeclareStatementTest() { - } + public DeclareStatementTest() {} @Test public void testDeclareType() throws JSQLParserException { @@ -38,7 +37,7 @@ public void testDeclareType() throws JSQLParserException { DeclareStatement created = new DeclareStatement() .addTypeDefExprList( new TypeDefExpr(new UserVariable().withName("find"), - new ColDataType().withDataType("nvarchar").addArgumentsStringList("30"), null)) + new ColDataType().withDataType("nvarchar (30)"), null)) .withDeclareType(DeclareType.TYPE); assertDeparse(created, statement); assertEqualsObjectTree(parsed, created); @@ -50,7 +49,7 @@ public void testDeclareTypeWithDefault() throws JSQLParserException { Statement parsed = assertSqlCanBeParsedAndDeparsed(statement); DeclareStatement created = new DeclareStatement() .addTypeDefExprList(new TypeDefExpr(new UserVariable().withName("find"), - new ColDataType().withDataType("varchar").addArgumentsStringList("30"), + new ColDataType().withDataType("varchar (30)"), new StringValue().withValue("Man%"))) .withDeclareType(DeclareType.TYPE); assertDeparse(created, statement); @@ -64,7 +63,7 @@ public void testDeclareTypeList() throws JSQLParserException { DeclareStatement created = new DeclareStatement().addTypeDefExprList(asList( // new TypeDefExpr( new UserVariable().withName("group"), - new ColDataType().withDataType("nvarchar").addArgumentsStringList("50"), + new ColDataType().withDataType("nvarchar (50)"), null), new TypeDefExpr(new UserVariable().withName("sales"), new ColDataType().withDataType("money"), null))) @@ -80,9 +79,11 @@ public void testDeclareTypeList2() throws JSQLParserException { @Test public void testDeclareTable() throws JSQLParserException { - String statement = "DECLARE @MyTableVar TABLE (EmpID int NOT NULL, OldVacationHours int, NewVacationHours int, ModifiedDate datetime)"; + String statement = + "DECLARE @MyTableVar TABLE (EmpID int NOT NULL, OldVacationHours int, NewVacationHours int, ModifiedDate datetime)"; Statement parsed = assertSqlCanBeParsedAndDeparsed(statement); - DeclareStatement created = new DeclareStatement().withUserVariable(new UserVariable("MyTableVar")) + DeclareStatement created = new DeclareStatement() + .withUserVariable(new UserVariable("MyTableVar")) .withColumnDefinitions(new ArrayList<>()) .addColumnDefinitions( new ColumnDefinition("EmpID", new ColDataType().withDataType("int"), diff --git a/src/test/java/net/sf/jsqlparser/statement/ExplainTest.java b/src/test/java/net/sf/jsqlparser/statement/ExplainTest.java index 54e64cbbc..4652879fd 100644 --- a/src/test/java/net/sf/jsqlparser/statement/ExplainTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/ExplainTest.java @@ -49,21 +49,25 @@ public void testVerbose() throws JSQLParserException { @Test public void testMultiOptions_orderPreserved() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("EXPLAIN VERBOSE ANALYZE BUFFERS COSTS SELECT * FROM mytable"); + assertSqlCanBeParsedAndDeparsed( + "EXPLAIN VERBOSE ANALYZE BUFFERS COSTS SELECT * FROM mytable"); } @Test public void getOption_returnsValues() throws JSQLParserException { - ExplainStatement explain = (ExplainStatement) CCJSqlParserUtil.parse("EXPLAIN VERBOSE FORMAT JSON BUFFERS FALSE SELECT * FROM mytable"); + ExplainStatement explain = (ExplainStatement) CCJSqlParserUtil + .parse("EXPLAIN VERBOSE FORMAT JSON BUFFERS FALSE SELECT * FROM mytable"); assertThat(explain.getOption(ExplainStatement.OptionType.ANALYZE)).isNull(); assertThat(explain.getOption(ExplainStatement.OptionType.VERBOSE)).isNotNull(); ExplainStatement.Option format = explain.getOption(ExplainStatement.OptionType.FORMAT); - assertThat(format).isNotNull().extracting(ExplainStatement.Option::getValue).isEqualTo("JSON"); + assertThat(format).isNotNull().extracting(ExplainStatement.Option::getValue) + .isEqualTo("JSON"); ExplainStatement.Option buffers = explain.getOption(ExplainStatement.OptionType.BUFFERS); - assertThat(buffers).isNotNull().extracting(ExplainStatement.Option::getValue).isEqualTo("FALSE"); + assertThat(buffers).isNotNull().extracting(ExplainStatement.Option::getValue) + .isEqualTo("FALSE"); explain = (ExplainStatement) CCJSqlParserUtil.parse("EXPLAIN SELECT * FROM mytable"); assertThat(explain.getOption(ExplainStatement.OptionType.ANALYZE)).isNull(); diff --git a/src/test/java/net/sf/jsqlparser/statement/IfElseStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/IfElseStatementTest.java index daf812567..c06b42948 100644 --- a/src/test/java/net/sf/jsqlparser/statement/IfElseStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/IfElseStatementTest.java @@ -45,10 +45,10 @@ public void testSimpleIfElseStatement() throws Exception { @Test public void testIfElseStatements1() throws Exception { - String sqlStr - = "IF OBJECT_ID('tOrigin', 'U') IS NOT NULL DROP TABLE tOrigin1; ELSE CREATE TABLE tOrigin1 (ID VARCHAR (40));\n" - + "IF OBJECT_ID('tOrigin', 'U') IS NOT NULL DROP TABLE tOrigin2; ELSE CREATE TABLE tOrigin2 (ID VARCHAR (40));\n" - + "IF OBJECT_ID('tOrigin', 'U') IS NOT NULL DROP TABLE tOrigin3; ELSE CREATE TABLE tOrigin3 (ID VARCHAR (40));\n"; + String sqlStr = + "IF OBJECT_ID('tOrigin', 'U') IS NOT NULL DROP TABLE tOrigin1; ELSE CREATE TABLE tOrigin1 (ID VARCHAR (40));\n" + + "IF OBJECT_ID('tOrigin', 'U') IS NOT NULL DROP TABLE tOrigin2; ELSE CREATE TABLE tOrigin2 (ID VARCHAR (40));\n" + + "IF OBJECT_ID('tOrigin', 'U') IS NOT NULL DROP TABLE tOrigin3; ELSE CREATE TABLE tOrigin3 (ID VARCHAR (40));\n"; Statements result = CCJSqlParserUtil.parseStatements(sqlStr); assertEquals(sqlStr, result.toString()); @@ -86,8 +86,8 @@ public void testObjectBuilder() throws JSQLParserException { @Test public void testValidation() { String sqlStr = "IF OBJECT_ID('tOrigin', 'U') IS NOT NULL DROP TABLE tOrigin1;"; - List errors - = Validation.validate(Arrays.asList(DatabaseType.SQLSERVER, FeaturesAllowed.DROP), sqlStr); + List errors = Validation + .validate(Arrays.asList(DatabaseType.SQLSERVER, FeaturesAllowed.DROP), sqlStr); ValidationTestAsserts.assertErrorsSize(errors, 0); } diff --git a/src/test/java/net/sf/jsqlparser/statement/KeywordsTest.java b/src/test/java/net/sf/jsqlparser/statement/KeywordsTest.java index e1d6b51e6..474d27f7c 100644 --- a/src/test/java/net/sf/jsqlparser/statement/KeywordsTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/KeywordsTest.java @@ -35,8 +35,9 @@ public static Stream keyWords() { File file = new File("src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt"); List keywords = new ArrayList<>(); try { - keywords.addAll( ParserKeywordsUtils.getAllKeywordsUsingRegex(file) ); - for (String reserved: ParserKeywordsUtils.getReservedKeywords(ParserKeywordsUtils.RESTRICTED_JSQLPARSER)) { + keywords.addAll(ParserKeywordsUtils.getAllKeywordsUsingRegex(file)); + for (String reserved : ParserKeywordsUtils + .getReservedKeywords(ParserKeywordsUtils.RESTRICTED_JSQLPARSER)) { keywords.remove(reserved); } } catch (Exception ex) { @@ -48,7 +49,7 @@ public static Stream keyWords() { @ParameterizedTest(name = "Keyword {0}") @MethodSource("keyWords") public void testRelObjectNameWithoutValue(String keyword) throws JSQLParserException { - String sqlStr = String.format("SELECT %1$s.%1$s AS %1$s from %1$s.%1$s AS %1$s", keyword); + String sqlStr = String.format("SELECT %1$s.%1$s AS %1$s from %1$s.%1$s AS %1$s", keyword); assertSqlCanBeParsedAndDeparsed(sqlStr, true); } diff --git a/src/test/java/net/sf/jsqlparser/statement/PurgeStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/PurgeStatementTest.java index 390dde2e9..a0caa5c9c 100644 --- a/src/test/java/net/sf/jsqlparser/statement/PurgeStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/PurgeStatementTest.java @@ -53,8 +53,8 @@ public void testStatementVisitorAdaptor() throws JSQLParserException { } /** - * This test will trigger the method {@link TableNamesFinder#visit() Visit Method} in the TableNamesFinder needed - * for the Code Coverage. + * This test will trigger the method {@link TableNamesFinder#visit() Visit Method} in the + * TableNamesFinder needed for the Code Coverage. * * @throws net.sf.jsqlparser.JSQLParserException */ @@ -69,8 +69,8 @@ public void testTableNamesFinder() throws JSQLParserException { } /** - * This test will trigger the method {@link ExpressionValidator#visit() Visit Method} in the ExpressionValidator - * needed for the Code Coverage. + * This test will trigger the method {@link ExpressionValidator#visit() Visit Method} in the + * ExpressionValidator needed for the Code Coverage. * * @throws net.sf.jsqlparser.JSQLParserException */ diff --git a/src/test/java/net/sf/jsqlparser/statement/RollbackStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/RollbackStatementTest.java index e14af0c2f..6c4da3109 100644 --- a/src/test/java/net/sf/jsqlparser/statement/RollbackStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/RollbackStatementTest.java @@ -21,11 +21,13 @@ public void testObject() { .withUsingWorkKeyword(true) .withUsingSavepointKeyword(true) .withSavepointName("mySavePoint") - .withForceDistributedTransactionIdentifier("$ForceDistributedTransactionIdentifier"); + .withForceDistributedTransactionIdentifier( + "$ForceDistributedTransactionIdentifier"); assertTrue(rollbackStatement.isUsingSavepointKeyword()); assertEquals("mySavePoint", rollbackStatement.getSavepointName()); - assertEquals("$ForceDistributedTransactionIdentifier", rollbackStatement.getForceDistributedTransactionIdentifier()); + assertEquals("$ForceDistributedTransactionIdentifier", + rollbackStatement.getForceDistributedTransactionIdentifier()); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/ShowIndexStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/ShowIndexStatementTest.java index be525fc6b..0350fd585 100644 --- a/src/test/java/net/sf/jsqlparser/statement/ShowIndexStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/ShowIndexStatementTest.java @@ -14,9 +14,9 @@ import org.junit.jupiter.api.Test; /** -* -* @author Jayant Kumar Yadav -*/ + * + * @author Jayant Kumar Yadav + */ public class ShowIndexStatementTest { @@ -24,4 +24,4 @@ public class ShowIndexStatementTest { public void testSimpleUse() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("SHOW INDEX FROM mydatabase"); } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jsqlparser/statement/StatementSeparatorTest.java b/src/test/java/net/sf/jsqlparser/statement/StatementSeparatorTest.java index b99ee6f26..f8b766300 100644 --- a/src/test/java/net/sf/jsqlparser/statement/StatementSeparatorTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/StatementSeparatorTest.java @@ -9,10 +9,11 @@ */ package net.sf.jsqlparser.statement; -import net.sf.jsqlparser.*; -import net.sf.jsqlparser.parser.*; -import net.sf.jsqlparser.test.*; -import org.junit.jupiter.api.*; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class StatementSeparatorTest { @@ -62,4 +63,20 @@ void testMSSQLBlock() throws JSQLParserException { Statements statements = CCJSqlParserUtil.parseStatements(sqlStr); Assertions.assertEquals(2, statements.size()); } + + @Test + void testSOQLIncludes() throws JSQLParserException { + String sqlStr = + "select name,\ngoods from test_table where option includes ('option1', 'option2')"; + Statement statement = TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + System.out.println(statement); + } + + @Test + void testSOQLExcludes() throws JSQLParserException { + String sqlStr = + "select name,\ngoods from test_table where option excludes ('option1', 'option2')"; + Statement statement = TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + System.out.println(statement); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/StatementsTest.java b/src/test/java/net/sf/jsqlparser/statement/StatementsTest.java index 5e9e46f0d..835b9ca4f 100644 --- a/src/test/java/net/sf/jsqlparser/statement/StatementsTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/StatementsTest.java @@ -16,49 +16,50 @@ import net.sf.jsqlparser.parser.StringProvider; import net.sf.jsqlparser.statement.select.Select; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; + +import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Test; public class StatementsTest { @Test public void testStatements() throws JSQLParserException { - String sqls = "select * from mytable; select * from mytable2;"; - Statements parseStatements = CCJSqlParserUtil.parseStatements(sqls); + String sqlStr = "select * from mytable; select * from mytable2;"; + Statements statements = CCJSqlParserUtil.parseStatements(sqlStr); - assertEquals("SELECT * FROM mytable;\nSELECT * FROM mytable2;\n", parseStatements.toString()); + assertEquals("SELECT * FROM mytable;\nSELECT * FROM mytable2;\n", statements.toString()); - assertTrue(parseStatements.getStatements().get(0) instanceof Select); - assertTrue(parseStatements.getStatements().get(1) instanceof Select); + assertInstanceOf(Select.class, statements.get(0)); + assertInstanceOf(Select.class, statements.get(1)); } @Test public void testStatementsProblem() throws JSQLParserException { String sqls = ";;select * from mytable;;select * from mytable2;;;"; - Statements parseStatements = CCJSqlParserUtil.parseStatements(sqls); + Statements statements = CCJSqlParserUtil.parseStatements(sqls); - assertEquals("SELECT * FROM mytable;\nSELECT * FROM mytable2;\n", parseStatements.toString()); + assertEquals("SELECT * FROM mytable;\nSELECT * FROM mytable2;\n", statements.toString()); - assertTrue(parseStatements.getStatements().get(0) instanceof Select); - assertTrue(parseStatements.getStatements().get(1) instanceof Select); + assertInstanceOf(Select.class, statements.get(0)); + assertInstanceOf(Select.class, statements.get(1)); } @Test public void testStatementsErrorRecovery() throws JSQLParserException, ParseException { - // "SELECT *" and "SELECT 1,2" are valid statements and so would return a correct SELECT object - // String sqls = "select * from mytable; select * from;"; - String sqls = "select * from mytable; select from;"; + String sqlStr = "select * from mytable; select from;"; - CCJSqlParser parser = new CCJSqlParser(new StringProvider(sqls)); + CCJSqlParser parser = new CCJSqlParser(new StringProvider(sqlStr)); parser.setErrorRecovery(true); Statements parseStatements = parser.Statements(); - assertEquals(2, parseStatements.getStatements().size()); + assertEquals(2, parseStatements.size()); - assertTrue(parseStatements.getStatements().get(0) instanceof Select); + assertInstanceOf(Select.class, parseStatements.get(0)); + assertInstanceOf(Select.class, parseStatements.get(0)); - assertNull(parseStatements.getStatements().get(1)); + assertEquals(1, parser.getParseErrors().size()); } @Test @@ -68,27 +69,40 @@ public void testStatementsErrorRecovery2() throws JSQLParserException, ParseExce parser.setErrorRecovery(true); Statements parseStatements = parser.Statements(); - assertEquals(1, parseStatements.getStatements().size()); + assertEquals(1, parseStatements.size()); - assertTrue(parseStatements.getStatements().get(0) instanceof Select); + assertNull(parseStatements.get(0)); assertEquals(1, parser.getParseErrors().size()); } @Test public void testStatementsErrorRecovery3() throws JSQLParserException, ParseException { - // "SELECT *" and "SELECT 1, 2" are valid SELECT statements - // String sqls = "select * from mytable; select * from;select * from mytable2"; - String sqls = "select * from mytable; select from;select * from mytable2"; + CCJSqlParser parser = + new CCJSqlParser("select * from mytable; select from; select * from mytable2"); + Statements statements = parser.withErrorRecovery().Statements(); - CCJSqlParser parser = new CCJSqlParser(new StringProvider(sqls)); - parser.setErrorRecovery(true); - Statements parseStatements = parser.Statements(); + assertEquals(3, statements.size()); + + assertInstanceOf(Select.class, statements.get(0)); + assertNull(statements.get(1)); + assertInstanceOf(Select.class, statements.get(2)); + + assertEquals(1, parser.getParseErrors().size()); + } + + @Test + public void testStatementsErrorRecovery4() throws JSQLParserException { + Statements statements = CCJSqlParserUtil.parseStatements( + "select * from mytable; select from; select * from mytable2; select 4 from dual;", + parser -> parser.withUnsupportedStatements()); - assertEquals(2, parseStatements.getStatements().size()); + assertEquals(4, statements.size()); - assertTrue(parseStatements.getStatements().get(0) instanceof Select); - assertNull(parseStatements.getStatements().get(1)); + assertInstanceOf(Select.class, statements.get(0)); + assertInstanceOf(UnsupportedStatement.class, statements.get(1)); + assertInstanceOf(Select.class, statements.get(2)); + assertInstanceOf(Select.class, statements.get(3)); - assertEquals(2, parser.getParseErrors().size()); + TestUtils.assertStatementCanBeDeparsedAs(statements.get(1), "select from", true); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/UnsupportedStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/UnsupportedStatementTest.java index c07a0b996..4ff4c8333 100644 --- a/src/test/java/net/sf/jsqlparser/statement/UnsupportedStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/UnsupportedStatementTest.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.statement; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertTrue; import net.sf.jsqlparser.JSQLParserException; @@ -17,6 +18,7 @@ import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; @@ -36,16 +38,19 @@ public void execute() throws Throwable { }); } + // This test does not work since the first statement MUST be a regular statement + // for the current grammar to work @Test + @Disabled public void testUnsupportedStatementsFirstInBlock() throws JSQLParserException { String sqlStr = "This is an unsupported statement; Select * from dual; Select * from dual;"; Statements statements = CCJSqlParserUtil.parseStatements(sqlStr, parser -> parser.withUnsupportedStatements(true)); - Assertions.assertEquals(3, statements.getStatements().size()); - Assertions.assertInstanceOf(UnsupportedStatement.class, statements.getStatements().get(0)); - Assertions.assertInstanceOf(Select.class, statements.getStatements().get(1)); - Assertions.assertInstanceOf(Select.class, statements.getStatements().get(2)); + Assertions.assertEquals(3, statements.size()); + Assertions.assertInstanceOf(UnsupportedStatement.class, statements.get(0)); + Assertions.assertInstanceOf(Select.class, statements.get(1)); + Assertions.assertInstanceOf(Select.class, statements.get(2)); Assertions.assertThrowsExactly(JSQLParserException.class, new Executable() { @Override @@ -61,23 +66,52 @@ public void testUnsupportedStatementsMiddleInBlock() throws JSQLParserException String sqlStr = "Select * from dual; This is an unsupported statement; Select * from dual;"; Statements statements = CCJSqlParserUtil.parseStatements(sqlStr, - parser -> parser.withUnsupportedStatements(true)); - Assertions.assertEquals(3, statements.getStatements().size()); - - Assertions.assertInstanceOf(Select.class, statements.getStatements().get(0)); - Assertions.assertInstanceOf(UnsupportedStatement.class, statements.getStatements().get(1)); - Assertions.assertInstanceOf(Select.class, statements.getStatements().get(2)); - - // This will not fail, but always return the Unsupported Statements - // Since we can't LOOKAHEAD in the Statements() production - - // Assertions.assertThrowsExactly(JSQLParserException.class, new Executable() { - // @Override - // public void execute() throws Throwable { - // CCJSqlParserUtil.parseStatements(sqlStr, parser -> - // parser.withUnsupportedStatements(false) ); - // } - // }); + parser -> parser.withUnsupportedStatements(true).withErrorRecovery(true)); + Assertions.assertEquals(3, statements.size()); + + Assertions.assertInstanceOf(Select.class, statements.get(0)); + Assertions.assertInstanceOf(UnsupportedStatement.class, statements.get(1)); + Assertions.assertInstanceOf(Select.class, statements.get(2)); + + Assertions.assertThrowsExactly(JSQLParserException.class, new Executable() { + @Override + public void execute() throws Throwable { + CCJSqlParserUtil.parseStatements(sqlStr, + parser -> parser.withUnsupportedStatements(false)); + } + }); + } + + @Test + public void testTwoUnsupportedStatementsMiddleInBlock() throws JSQLParserException { + String sqlStr = + "Select * from dual; This is an unsupported statement; Some more rubbish; Select * from dual;"; + + Statements statements = CCJSqlParserUtil.parseStatements(sqlStr, + parser -> parser.withUnsupportedStatements(true).withErrorRecovery(true)); + Assertions.assertEquals(4, statements.size()); + + Assertions.assertInstanceOf(Select.class, statements.get(0)); + Assertions.assertInstanceOf(UnsupportedStatement.class, statements.get(1)); + Assertions.assertInstanceOf(UnsupportedStatement.class, statements.get(2)); + Assertions.assertInstanceOf(Select.class, statements.get(3)); + + Assertions.assertThrowsExactly(JSQLParserException.class, new Executable() { + @Override + public void execute() throws Throwable { + CCJSqlParserUtil.parseStatements(sqlStr, + parser -> parser.withUnsupportedStatements(false)); + } + }); + } + + @Test + public void testCaptureRestIssue1993() throws JSQLParserException { + String sqlStr = "Select 1; ALTER TABLE \"inter\".\"inter_user_rec\" \n" + + " OWNER TO \"postgres\"; select 2; select 3;"; + Statements statements = CCJSqlParserUtil.parseStatements(sqlStr, + parser -> parser.withErrorRecovery(false)); + Assertions.assertEquals(4, statements.size()); } @Test @@ -85,7 +119,7 @@ void testAlter() throws JSQLParserException { String sqlStr = "ALTER INDEX idx_t_fa RENAME TO idx_t_fb"; Statement statement = TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); - assertTrue(statement instanceof UnsupportedStatement); + assertInstanceOf(UnsupportedStatement.class, statement); } @Test @@ -128,4 +162,40 @@ void testFunctions() throws JSQLParserException { Statements statements = CCJSqlParserUtil.parseStatements(sqlStr); assertEquals(2, statements.size()); } + + @Test + void testSQLServerSetStatementIssue1984() throws JSQLParserException { + String sqlStr = "SET IDENTITY_INSERT tb_inter_d2v_transfer on"; + Statements statements = CCJSqlParserUtil.parseStatements(sqlStr, + parser -> parser.withUnsupportedStatements(true)); + assertEquals(1, statements.size()); + assertInstanceOf(UnsupportedStatement.class, statements.get(0)); + + TestUtils.assertStatementCanBeDeparsedAs(statements.get(0), sqlStr, true); + + Statement statement = CCJSqlParserUtil.parse(sqlStr, + parser -> parser.withUnsupportedStatements(true)); + assertInstanceOf(UnsupportedStatement.class, statement); + + TestUtils.assertStatementCanBeDeparsedAs(statement, sqlStr, true); + } + + @Test + void testInformixSetStatementIssue1945() throws JSQLParserException { + String sqlStr = "set isolation to dirty read;"; + Statement statement = CCJSqlParserUtil.parse(sqlStr, + parser -> parser.withUnsupportedStatements(true)); + assertInstanceOf(UnsupportedStatement.class, statement); + TestUtils.assertStatementCanBeDeparsedAs(statement, sqlStr, true); + + TestUtils.assertSqlCanBeParsedAndDeparsed( + "set isolation to dirty read;", true, parser -> parser.withUnsupportedStatements()); + } + + @Test + void testRedshiftSetStatementIssue1708() throws JSQLParserException { + Statement st = TestUtils.assertSqlCanBeParsedAndDeparsed( + "SET x TO y;", true, parser -> parser.withUnsupportedStatements()); + assertInstanceOf(UnsupportedStatement.class, st); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterSequenceTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterSequenceTest.java index c5fa4fbbf..bb97f4235 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterSequenceTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterSequenceTest.java @@ -106,8 +106,10 @@ public void testAlterSequence_withGlobal() throws JSQLParserException { @Test public void testAlterSequence_preservesParamOrder() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("ALTER SEQUENCE my_sec INCREMENT BY 2 START WITH 10"); - assertSqlCanBeParsedAndDeparsed("ALTER SEQUENCE my_sec START WITH 2 INCREMENT BY 5 NOCACHE"); - assertSqlCanBeParsedAndDeparsed("ALTER SEQUENCE my_sec START WITH 2 INCREMENT BY 5 CACHE 200 CYCLE"); + assertSqlCanBeParsedAndDeparsed( + "ALTER SEQUENCE my_sec START WITH 2 INCREMENT BY 5 NOCACHE"); + assertSqlCanBeParsedAndDeparsed( + "ALTER SEQUENCE my_sec START WITH 2 INCREMENT BY 5 CACHE 200 CYCLE"); } @Test diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterSessionTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterSessionTest.java index b2a62ff13..57813ee13 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterSessionTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterSessionTest.java @@ -35,16 +35,20 @@ public void testAlterSessionEnable() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION ENABLE COMMIT IN PROCEDURE", true); TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION ENABLE GUARD", true); TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION ENABLE PARALLEL DML", true); - TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION ENABLE PARALLEL DML PARALLEL 10", true); + TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION ENABLE PARALLEL DML PARALLEL 10", + true); TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION ENABLE PARALLEL DDL", true); - TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION ENABLE PARALLEL DDL PARALLEL 10", true); + TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION ENABLE PARALLEL DDL PARALLEL 10", + true); TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION ENABLE PARALLEL QUERY", true); - TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION ENABLE PARALLEL QUERY PARALLEL 10", true); + TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION ENABLE PARALLEL QUERY PARALLEL 10", + true); } @Test public void testAlterSessionDisable() throws JSQLParserException { - TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION DISABLE COMMIT IN PROCEDURE", true); + TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION DISABLE COMMIT IN PROCEDURE", + true); TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION DISABLE GUARD", true); TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION DISABLE PARALLEL DML", true); TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION DISABLE PARALLEL DDL", true); @@ -54,17 +58,21 @@ public void testAlterSessionDisable() throws JSQLParserException { @Test public void testAlterSessionForceParallel() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION FORCE PARALLEL DML", true); - TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION FORCE PARALLEL DML PARALLEL 10", true); + TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION FORCE PARALLEL DML PARALLEL 10", + true); TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION FORCE PARALLEL DDL", true); - TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION FORCE PARALLEL DDL PARALLEL 10", true); + TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION FORCE PARALLEL DDL PARALLEL 10", + true); TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION FORCE PARALLEL QUERY", true); - TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION FORCE PARALLEL QUERY PARALLEL 10", true); + TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION FORCE PARALLEL QUERY PARALLEL 10", + true); } @Test public void testAlterSessionSet() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION SET ddl_lock_timeout=7200", true); - TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION SET ddl_lock_timeout = 7200", true); + TestUtils.assertSqlCanBeParsedAndDeparsed("ALTER SESSION SET ddl_lock_timeout = 7200", + true); } @Test @@ -75,7 +83,8 @@ public void testAlterSessionResumable() throws JSQLParserException { @Test public void testObject() { - AlterSession alterSession = new AlterSession(AlterSessionOperation.FORCE_PARALLEL_QUERY, Collections.emptyList()); + AlterSession alterSession = new AlterSession(AlterSessionOperation.FORCE_PARALLEL_QUERY, + Collections.emptyList()); assertEquals(AlterSessionOperation.FORCE_PARALLEL_QUERY, alterSession.getOperation()); alterSession.setOperation(AlterSessionOperation.DISABLE_PARALLEL_DML); diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterSystemTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterSystemTest.java index 3bef48a34..ea7594d21 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterSystemTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterSystemTest.java @@ -25,7 +25,8 @@ /** * * @author Andreas Reichel - * @see ALTER SESSION + * @see ALTER + * SESSION */ public class AlterSystemTest { @@ -48,8 +49,8 @@ public void testStatementVisitorAdaptor() throws JSQLParserException { } /** - * This test will trigger the method {@link TableNamesFinder#visit() Visit Method} in the TableNamesFinder needed - * for the Code Coverage. + * This test will trigger the method {@link TableNamesFinder#visit() Visit Method} in the + * TableNamesFinder needed for the Code Coverage. * * @throws net.sf.jsqlparser.JSQLParserException */ @@ -63,8 +64,8 @@ public void testTableNamesFinder() throws JSQLParserException { } /** - * This test will trigger the method {@link ExpressionValidator#visit() Visit Method} in the ExpressionValidator - * needed for the Code Coverage. + * This test will trigger the method {@link ExpressionValidator#visit() Visit Method} in the + * ExpressionValidator needed for the Code Coverage. * * @throws net.sf.jsqlparser.JSQLParserException */ diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/RenameTableStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/RenameTableStatementTest.java index a53a5051e..6123687ad 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/RenameTableStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/RenameTableStatementTest.java @@ -32,7 +32,8 @@ public class RenameTableStatementTest { /** - * This test will parse and deparse the statement and assures the functional coverage by JSQLParser. + * This test will parse and deparse the statement and assures the functional coverage by + * JSQLParser. * * @throws net.sf.jsqlparser.JSQLParserException */ @@ -65,8 +66,8 @@ public void testStatementVisitorAdaptor() throws JSQLParserException { } /** - * This test will trigger the method {@link TableNamesFinder#visit() Visit Method} in the TableNamesFinder needed - * for the Code Coverage. + * This test will trigger the method {@link TableNamesFinder#visit() Visit Method} in the + * TableNamesFinder needed for the Code Coverage. * * @throws net.sf.jsqlparser.JSQLParserException */ @@ -82,8 +83,8 @@ public void testTableNamesFinder() throws JSQLParserException { } /** - * This test will trigger the method {@link ExpressionValidator#visit() Visit Method} in the ExpressionValidator - * needed for the Code Coverage. + * This test will trigger the method {@link ExpressionValidator#visit() Visit Method} in the + * ExpressionValidator needed for the Code Coverage. * * @throws net.sf.jsqlparser.JSQLParserException */ @@ -101,7 +102,8 @@ public void testValidator() throws JSQLParserException { sqlStr = "ALTER TABLE public.oldTableName RENAME TO newTableName"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); - // this needs to succeed according to: https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_3001.htm + // this needs to succeed according to: + // https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_3001.htm ValidationTestAsserts.validateNoErrors(sqlStr, 1, DatabaseType.ORACLE); // this needs to succeed @@ -110,7 +112,7 @@ public void testValidator() throws JSQLParserException { sqlStr = "ALTER TABLE IF EXISTS public.oldTableName RENAME TO newTableName"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); - // should fail when IF EXISTS is not supported in Oracle 11 + // should fail when IF EXISTS is not supported in Oracle 11 ValidationTestAsserts.validateNoErrors(sqlStr, 1, DatabaseType.ORACLE); // this needs to succeed diff --git a/src/test/java/net/sf/jsqlparser/statement/analyze/AnalyzeTest.java b/src/test/java/net/sf/jsqlparser/statement/analyze/AnalyzeTest.java index 087bc4ebb..7f19370f4 100644 --- a/src/test/java/net/sf/jsqlparser/statement/analyze/AnalyzeTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/analyze/AnalyzeTest.java @@ -33,7 +33,7 @@ public void testAnalyze() throws JSQLParserException { assertDeparse(new Analyze().withTable(new Table("mytab")), statement); } - + @Test public void testAnalyze2() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("ANALYZE mytable"); diff --git a/src/test/java/net/sf/jsqlparser/statement/builder/JSQLParserFluentModelTests.java b/src/test/java/net/sf/jsqlparser/statement/builder/JSQLParserFluentModelTests.java index 19257ff75..bd703bdee 100644 --- a/src/test/java/net/sf/jsqlparser/statement/builder/JSQLParserFluentModelTests.java +++ b/src/test/java/net/sf/jsqlparser/statement/builder/JSQLParserFluentModelTests.java @@ -12,7 +12,6 @@ import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.JdbcParameter; -import net.sf.jsqlparser.expression.Parenthesis; import net.sf.jsqlparser.expression.StringValue; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; import net.sf.jsqlparser.expression.operators.conditional.OrExpression; @@ -46,7 +45,7 @@ public void testParseAndBuild() throws JSQLParserException { Table t2 = new Table("tab2").withAlias(new Alias("t2", false)); AndExpression where = new AndExpression().withLeftExpression( - new Parenthesis(new OrExpression().withLeftExpression( + new ParenthesedExpressionList<>(new OrExpression().withLeftExpression( new EqualsTo() .withLeftExpression(new Column(asList("t1", "col1"))) .withRightExpression(new JdbcParameter().withIndex(1))) @@ -58,7 +57,7 @@ public void testParseAndBuild() throws JSQLParserException { new InExpression() .withLeftExpression(new Column(asList("t1", "col3"))) .withRightExpression( - new ParenthesedExpressionList(new StringValue("A")))); + new ParenthesedExpressionList<>(new StringValue("A")))); PlainSelect select = new PlainSelect().addSelectItems(new AllColumns()).withFromItem(t1) .addJoins(new Join().withRightItem(t2) @@ -84,7 +83,7 @@ public void testParseAndBuildForXOR() throws JSQLParserException { XorExpression where = new XorExpression() .withLeftExpression(new AndExpression() .withLeftExpression( - new Parenthesis( + new ParenthesedExpressionList<>( new XorExpression() .withLeftExpression( new Column(asList("t1", "col1"))) @@ -94,7 +93,8 @@ public void testParseAndBuildForXOR() throws JSQLParserException { new InExpression() .withLeftExpression(new Column(asList("t1", "col3"))) .withRightExpression( - new ParenthesedExpressionList(new StringValue("B"), + new ParenthesedExpressionList<>( + new StringValue("B"), new StringValue("C"))))) .withRightExpression(new Column(asList("t2", "col4"))); diff --git a/src/test/java/net/sf/jsqlparser/statement/builder/ReflectionModelTest.java b/src/test/java/net/sf/jsqlparser/statement/builder/ReflectionModelTest.java index 75ec41db1..7d4c33714 100644 --- a/src/test/java/net/sf/jsqlparser/statement/builder/ReflectionModelTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/builder/ReflectionModelTest.java @@ -9,10 +9,6 @@ */ package net.sf.jsqlparser.statement.builder; -import static net.sf.jsqlparser.test.TestUtils.asList; - -import java.util.ArrayList; -import java.util.List; import net.sf.jsqlparser.expression.AnyType; import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperatorType; import net.sf.jsqlparser.schema.Sequence.ParameterType; @@ -24,6 +20,11 @@ import net.sf.jsqlparser.util.ReflectionTestUtils; import org.junit.jupiter.api.Test; +import java.util.ArrayList; +import java.util.List; + +import static net.sf.jsqlparser.test.TestUtils.asList; + /** * Testing of setters, getters, with-/add-methods by calling them with random parameter-values *
      @@ -71,7 +72,6 @@ public class ReflectionModelTest { new net.sf.jsqlparser.expression.OracleHierarchicalExpression(), new net.sf.jsqlparser.expression.OracleHint(), new net.sf.jsqlparser.expression.OrderByClause(), - new net.sf.jsqlparser.expression.Parenthesis(), new net.sf.jsqlparser.expression.PartitionByClause(), // new net.sf.jsqlparser.expression.RowConstructor<>("ROW", new ExpressionList<>()), new net.sf.jsqlparser.expression.SQLServerHints(), diff --git a/src/test/java/net/sf/jsqlparser/statement/comment/CommentTest.java b/src/test/java/net/sf/jsqlparser/statement/comment/CommentTest.java index 231a9f1b6..840905bdd 100755 --- a/src/test/java/net/sf/jsqlparser/statement/comment/CommentTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/comment/CommentTest.java @@ -48,7 +48,8 @@ public void testCommentTableDeparse() throws JSQLParserException { String statement = "COMMENT ON TABLE table1 IS 'comment1'"; assertSqlCanBeParsedAndDeparsed(statement); - Comment c = new Comment().withTable(new Table("table1")).withComment(new StringValue("comment1")); + Comment c = new Comment().withTable(new Table("table1")) + .withComment(new StringValue("comment1")); assertEquals("table1", c.getTable().getName()); assertEquals("comment1", c.getComment().getValue()); assertDeparse(c, statement, false); @@ -82,12 +83,14 @@ public void testToString() { @Test public void testCommentColumnDeparseIssue696() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("COMMENT ON COLUMN hotels.hotelid IS 'Primary key of the table'"); + assertSqlCanBeParsedAndDeparsed( + "COMMENT ON COLUMN hotels.hotelid IS 'Primary key of the table'"); } @Test public void testCommentTableColumnDiffersIssue984() throws JSQLParserException { - Comment comment = (Comment) CCJSqlParserUtil.parse("COMMENT ON COLUMN myTable.myColumn is 'Some comment'"); + Comment comment = (Comment) CCJSqlParserUtil + .parse("COMMENT ON COLUMN myTable.myColumn is 'Some comment'"); assertThat(comment.getTable()).isNull(); assertThat(comment.getColumn().getColumnName()).isEqualTo("myColumn"); assertThat(comment.getColumn().getTable().getFullyQualifiedName()).isEqualTo("myTable"); @@ -95,10 +98,12 @@ public void testCommentTableColumnDiffersIssue984() throws JSQLParserException { @Test public void testCommentTableColumnDiffersIssue984_2() throws JSQLParserException { - Comment comment = (Comment) CCJSqlParserUtil.parse("COMMENT ON COLUMN mySchema.myTable.myColumn is 'Some comment'"); + Comment comment = (Comment) CCJSqlParserUtil + .parse("COMMENT ON COLUMN mySchema.myTable.myColumn is 'Some comment'"); assertThat(comment.getTable()).isNull(); assertThat(comment.getColumn().getColumnName()).isEqualTo("myColumn"); - assertThat(comment.getColumn().getTable().getFullyQualifiedName()).isEqualTo("mySchema.myTable"); + assertThat(comment.getColumn().getTable().getFullyQualifiedName()) + .isEqualTo("mySchema.myTable"); assertThat(comment.getColumn().getTable().getName()).isEqualTo("myTable"); assertThat(comment.getColumn().getTable().getSchemaName()).isEqualTo("mySchema"); } diff --git a/src/test/java/net/sf/jsqlparser/statement/create/CreateFunctionalStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/create/CreateFunctionalStatementTest.java index 9689737ff..4906c19d0 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/CreateFunctionalStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/CreateFunctionalStatementTest.java @@ -20,7 +20,8 @@ import org.junit.jupiter.api.Test; /** - * Tests the behavior of {@link net.sf.jsqlparser.statement.CreateFunctionalStatement funtion statements} + * Tests the behavior of {@link net.sf.jsqlparser.statement.CreateFunctionalStatement funtion + * statements} */ public class CreateFunctionalStatementTest { @@ -36,16 +37,17 @@ public void createFunctionMinimal() throws JSQLParserException { @Test public void createFunctionLong() throws JSQLParserException { - CreateFunction stm = (CreateFunction) CCJSqlParserUtil.parse("CREATE FUNCTION fun(query_from_time date) RETURNS TABLE(foo double precision, bar double precision)\n" - + " LANGUAGE plpgsql\n" - + " AS $$\n" - + " BEGIN\n" - + " RETURN QUERY\n" - + " WITH bla AS (\n" - + " SELECT * from foo)\n" - + " Select * from bla;\n" - + " END;\n" - + " $$;"); + CreateFunction stm = (CreateFunction) CCJSqlParserUtil.parse( + "CREATE FUNCTION fun(query_from_time date) RETURNS TABLE(foo double precision, bar double precision)\n" + + " LANGUAGE plpgsql\n" + + " AS $$\n" + + " BEGIN\n" + + " RETURN QUERY\n" + + " WITH bla AS (\n" + + " SELECT * from foo)\n" + + " Select * from bla;\n" + + " END;\n" + + " $$;"); assertThat(stm).isNotNull(); assertThat(stm.formatDeclaration()).contains("fun ( query_from_time date )"); } @@ -62,13 +64,14 @@ public void createProcedureMinimal() throws JSQLParserException { @Test public void createProcedureLong() throws JSQLParserException { - CreateProcedure stm = (CreateProcedure) CCJSqlParserUtil.parse("CREATE PROCEDURE remove_emp (employee_id NUMBER) AS\n" - + " tot_emps NUMBER;\n" - + " BEGIN\n" - + " DELETE FROM employees\n" - + " WHERE employees.employee_id = remove_emp.employee_id;\n" - + " tot_emps := tot_emps - 1;\n" - + " END;"); + CreateProcedure stm = (CreateProcedure) CCJSqlParserUtil + .parse("CREATE PROCEDURE remove_emp (employee_id NUMBER) AS\n" + + " tot_emps NUMBER;\n" + + " BEGIN\n" + + " DELETE FROM employees\n" + + " WHERE employees.employee_id = remove_emp.employee_id;\n" + + " tot_emps := tot_emps - 1;\n" + + " END;"); assertThat(stm).isNotNull(); assertThat(stm.formatDeclaration()).contains("remove_emp ( employee_id NUMBER )"); } diff --git a/src/test/java/net/sf/jsqlparser/statement/create/CreateSequenceTest.java b/src/test/java/net/sf/jsqlparser/statement/create/CreateSequenceTest.java index d73e433bd..db4e1984d 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/CreateSequenceTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/CreateSequenceTest.java @@ -24,7 +24,8 @@ public class CreateSequenceTest { public void testCreateSequence_noParams() throws JSQLParserException { String statement = "CREATE SEQUENCE my_seq"; assertSqlCanBeParsedAndDeparsed(statement); - assertDeparse(new CreateSequence().withSequence(new Sequence().withName("my_seq")), statement); + assertDeparse(new CreateSequence().withSequence(new Sequence().withName("my_seq")), + statement); } @Test @@ -32,8 +33,10 @@ public void testCreateSequence_withIncrement() throws JSQLParserException { String statement = "CREATE SEQUENCE db.schema.my_seq INCREMENT BY 1"; assertSqlCanBeParsedAndDeparsed(statement); assertDeparse(new CreateSequence().withSequence( - new Sequence().withDatabase(new Database("db")).withSchemaName("schema").withName("my_seq") - .addParameters(new Parameter(ParameterType.INCREMENT_BY).withValue(1L))), statement); + new Sequence().withDatabase(new Database("db")).withSchemaName("schema") + .withName("my_seq") + .addParameters(new Parameter(ParameterType.INCREMENT_BY).withValue(1L))), + statement); } @Test @@ -117,7 +120,8 @@ public void testCreateSequence_withGlobal() throws JSQLParserException { @Test public void testCreateSequence_preservesParamOrder() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("CREATE SEQUENCE my_sec INCREMENT BY 2 START WITH 10"); - assertSqlCanBeParsedAndDeparsed("CREATE SEQUENCE my_sec START WITH 2 INCREMENT BY 5 NOCACHE"); + assertSqlCanBeParsedAndDeparsed( + "CREATE SEQUENCE my_sec START WITH 2 INCREMENT BY 5 NOCACHE"); String statement = "CREATE SEQUENCE my_sec START WITH 2 INCREMENT BY 5 CACHE 200 CYCLE"; assertSqlCanBeParsedAndDeparsed(statement); assertDeparse(new CreateSequence().withSequence(new Sequence().withName("my_sec") diff --git a/src/test/java/net/sf/jsqlparser/statement/create/schema/CreateSchemaTest.java b/src/test/java/net/sf/jsqlparser/statement/create/schema/CreateSchemaTest.java index 7dd8496c1..c002bbd01 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/schema/CreateSchemaTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/schema/CreateSchemaTest.java @@ -31,6 +31,7 @@ public void testSimpleCreateSchema() throws JSQLParserException { public void testSimpleCreateWithAuth() throws JSQLParserException { String statement = "CREATE SCHEMA myschema AUTHORIZATION myauth"; assertSqlCanBeParsedAndDeparsed(statement); - assertDeparse(new CreateSchema().withSchemaName("myschema").withAuthorization("myauth"), statement); + assertDeparse(new CreateSchema().withSchemaName("myschema").withAuthorization("myauth"), + statement); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/create/synonym/CreateSynonymTest.java b/src/test/java/net/sf/jsqlparser/statement/create/synonym/CreateSynonymTest.java index 9669f1efe..53886e267 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/synonym/CreateSynonymTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/synonym/CreateSynonymTest.java @@ -21,17 +21,20 @@ public class CreateSynonymTest { @Test public void createPublic() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("CREATE PUBLIC SYNONYM TBL_TABLE_NAME FOR SCHEMA.T_TBL_NAME"); + assertSqlCanBeParsedAndDeparsed( + "CREATE PUBLIC SYNONYM TBL_TABLE_NAME FOR SCHEMA.T_TBL_NAME"); } @Test public void createWithReplace() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("CREATE OR REPLACE SYNONYM TBL_TABLE_NAME FOR SCHEMA.T_TBL_NAME"); + assertSqlCanBeParsedAndDeparsed( + "CREATE OR REPLACE SYNONYM TBL_TABLE_NAME FOR SCHEMA.T_TBL_NAME"); } @Test public void createWithReplacePublic() throws Exception { - assertSqlCanBeParsedAndDeparsed("CREATE OR REPLACE PUBLIC SYNONYM TBL_TABLE_NAME FOR SCHEMA.T_TBL_NAME"); + assertSqlCanBeParsedAndDeparsed( + "CREATE OR REPLACE PUBLIC SYNONYM TBL_TABLE_NAME FOR SCHEMA.T_TBL_NAME"); } /** @@ -41,12 +44,14 @@ public void createWithReplacePublic() throws Exception { */ @Test public void createWithDbLink() throws Exception { - assertSqlCanBeParsedAndDeparsed("CREATE PUBLIC SYNONYM emp_table FOR hr.employees@remote.us.oracle.com"); + assertSqlCanBeParsedAndDeparsed( + "CREATE PUBLIC SYNONYM emp_table FOR hr.employees@remote.us.oracle.com"); } @Test public void synonymAttributes() throws Exception { - final CreateSynonym createSynonym = (CreateSynonym) CCJSqlParserUtil.parse("CREATE OR REPLACE PUBLIC SYNONYM TBL_TABLE_NAME FOR SCHEMA.T_TBL_NAME"); + final CreateSynonym createSynonym = (CreateSynonym) CCJSqlParserUtil + .parse("CREATE OR REPLACE PUBLIC SYNONYM TBL_TABLE_NAME FOR SCHEMA.T_TBL_NAME"); assertThat(createSynonym.isOrReplace()).isTrue(); assertThat(createSynonym.isPublicSynonym()).isTrue(); @@ -54,6 +59,7 @@ public void synonymAttributes() throws Exception { assertThat(createSynonym.getFor()).isEqualTo("SCHEMA.T_TBL_NAME"); assertEquals(2, createSynonym.getForList().size()); - assertEquals("NEW_TBL_TABLE_NAME", createSynonym.withSynonym(new Synonym().withName("NEW_TBL_TABLE_NAME")).getSynonym().getName()); + assertEquals("NEW_TBL_TABLE_NAME", createSynonym + .withSynonym(new Synonym().withName("NEW_TBL_TABLE_NAME")).getSynonym().getName()); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/create/table/ColDataTypeTest.java b/src/test/java/net/sf/jsqlparser/statement/create/table/ColDataTypeTest.java index bc2cb5c4b..e3462a66f 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/table/ColDataTypeTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/table/ColDataTypeTest.java @@ -13,6 +13,8 @@ import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Test; +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; + class ColDataTypeTest { @Test void testPublicType() throws JSQLParserException { @@ -40,4 +42,9 @@ void testIssue1879() throws JSQLParserException { ")"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + public void testNestedCast() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed("SELECT acolumn::bit(64)::int(64) FROM mytable"); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java b/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java index 7c32fe3ec..a528035c8 100644 --- a/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java @@ -58,7 +58,8 @@ public void testDeleteWithLimit() throws JSQLParserException { @Test public void testDeleteDoesNotAllowLimitOffset() { String statement = "DELETE FROM table1 WHERE A.cod_table = 'YYY' LIMIT 3,4"; - assertThrows(JSQLParserException.class, () -> parserManager.parse(new StringReader(statement))); + assertThrows(JSQLParserException.class, + () -> parserManager.parse(new StringReader(statement))); } @Test @@ -86,8 +87,10 @@ public void testDeleteFromTableUsingLeftJoinToAnotherTable() throws JSQLParserEx } @Test - public void testDeleteFromTableUsingInnerJoinToAnotherTableWithAlias() throws JSQLParserException { - String stmt = "DELETE gc FROM guide_category AS gc LEFT JOIN guide AS g ON g.id_guide = gc.id_guide WHERE g.title IS NULL LIMIT 5"; + public void testDeleteFromTableUsingInnerJoinToAnotherTableWithAlias() + throws JSQLParserException { + String stmt = + "DELETE gc FROM guide_category AS gc LEFT JOIN guide AS g ON g.id_guide = gc.id_guide WHERE g.title IS NULL LIMIT 5"; assertSqlCanBeParsedAndDeparsed(stmt); } @@ -102,13 +105,12 @@ public void testOracleHint() throws JSQLParserException { assertOracleHintExists(sql, true, "SOMEHINT"); - //@todo: add a testcase supposed to not finding a misplaced hint + // @todo: add a testcase supposed to not finding a misplaced hint } @Test public void testWith() throws JSQLParserException { - String statement - = "" + String statement = "" + "WITH a\n" + " AS (SELECT 1 id_instrument_ref)\n" + " , b\n" @@ -189,17 +191,14 @@ public void testDeleteReturningIssue1527() throws JSQLParserException { " RETURNING name, price AS new_price"; assertSqlCanBeParsedAndDeparsed(statement, true); } + @Test public void testDeleteOutputClause() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( - "DELETE Sales.ShoppingCartItem OUTPUT DELETED.* FROM Sales" - , true - ); + "DELETE Sales.ShoppingCartItem OUTPUT DELETED.* FROM Sales", true); assertSqlCanBeParsedAndDeparsed( - "DELETE Sales.ShoppingCartItem OUTPUT Sales.ShoppingCartItem FROM Sales" - , true - ); + "DELETE Sales.ShoppingCartItem OUTPUT Sales.ShoppingCartItem FROM Sales", true); assertSqlCanBeParsedAndDeparsed( "DELETE Production.ProductProductPhoto \n" + @@ -211,9 +210,8 @@ public void testDeleteOutputClause() throws JSQLParserException { "FROM Production.ProductProductPhoto AS ph \n" + "JOIN Production.Product as p \n" + " ON ph.ProductID = p.ProductID \n" + - " WHERE p.ProductModelID BETWEEN 120 and 130" - , true - ); + " WHERE p.ProductModelID BETWEEN 120 and 130", + true); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/drop/DropTest.java b/src/test/java/net/sf/jsqlparser/statement/drop/DropTest.java index 062374f39..a97eed829 100644 --- a/src/test/java/net/sf/jsqlparser/statement/drop/DropTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/drop/DropTest.java @@ -42,11 +42,12 @@ public void testDropIndex() throws JSQLParserException { assertEquals("myindex", parsed.getName().getFullyQualifiedName()); assertEquals("CASCADE", parsed.getParameters().get(0)); assertEquals(statement, "" + parsed); - Drop created = new Drop().withType("INDEX").withName(new Table("myindex")).addParameters("CASCADE"); + Drop created = new Drop().withType("INDEX").withName(new Table("myindex")) + .addParameters("CASCADE"); assertDeparse(created, statement); assertEqualsObjectTree(parsed, created); } - + @Test public void testDropIndexOnTable() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("DROP INDEX idx ON abc"); @@ -63,7 +64,8 @@ public void testDrop2() throws JSQLParserException { public void testDropIfExists() throws JSQLParserException { String statement = "DROP TABLE IF EXISTS my_table"; Statement parsed = assertSqlCanBeParsedAndDeparsed(statement); - Drop created = new Drop().withType("TABLE").withIfExists(true).withName(new Table("my_table")); + Drop created = + new Drop().withType("TABLE").withIfExists(true).withName(new Table("my_table")); assertDeparse(created, statement); assertEqualsObjectTree(parsed, created); } @@ -72,7 +74,8 @@ public void testDropIfExists() throws JSQLParserException { public void testDropRestrictIssue510() throws JSQLParserException { String statement = "DROP TABLE TABLE2 RESTRICT"; Statement parsed = assertSqlCanBeParsedAndDeparsed(statement); - Drop created = new Drop().withType("TABLE").withName(new Table("TABLE2")).addParameters(asList("RESTRICT")); + Drop created = new Drop().withType("TABLE").withName(new Table("TABLE2")) + .addParameters(asList("RESTRICT")); assertDeparse(created, statement); assertEqualsObjectTree(parsed, created); } @@ -104,7 +107,7 @@ public void testDropSequence() throws JSQLParserException { @Test public void testOracleMultiColumnDrop() throws JSQLParserException { - //assertSqlCanBeParsedAndDeparsed("ALTER TABLE foo DROP (bar, baz)"); + // assertSqlCanBeParsedAndDeparsed("ALTER TABLE foo DROP (bar, baz)"); assertSqlCanBeParsedAndDeparsed("ALTER TABLE foo DROP (bar, baz) CASCADE"); } @@ -135,7 +138,7 @@ public void testDropFunctionWithNameAndParameterizedType() throws JSQLParserExce @Test void dropTemporaryTableTestIssue1712() throws JSQLParserException { - String sqlStr="drop temporary table if exists tmp_MwYT8N0z"; + String sqlStr = "drop temporary table if exists tmp_MwYT8N0z"; assertSqlCanBeParsedAndDeparsed(sqlStr, true); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java index 3f214f990..8e3704dd1 100644 --- a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java @@ -98,7 +98,7 @@ public void testInsertWithKeywordValue() throws JSQLParserException { assertEquals("mytable", insert.getTable().getName()); assertEquals(1, insert.getColumns().size()); assertEquals("col1", insert.getColumns().get(0).getColumnName()); - assertEquals("('val1')", + assertEquals("'val1'", (insert.getValues().getExpressions().get(0)).toString()); assertEquals("INSERT INTO mytable (col1) VALUES ('val1')", insert.toString()); @@ -207,7 +207,8 @@ public void testInsertMultiRowValue() throws JSQLParserException { .addExpression( new ParenthesedExpressionList(new Column("a"), new Column("b"))) .addExpression( - new ParenthesedExpressionList(new Column("d"), new Column("e"))); + new ParenthesedExpressionList(new Column("d"), + new Column("e"))); Select select = new Values().withExpressions(multiExpressionList); diff --git a/src/test/java/net/sf/jsqlparser/statement/select/AllColumnsTest.java b/src/test/java/net/sf/jsqlparser/statement/select/AllColumnsTest.java index 35173ec3d..7f5aaba4c 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/AllColumnsTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/AllColumnsTest.java @@ -19,7 +19,15 @@ class AllColumnsTest { @Test void testBigQuerySyntax() throws JSQLParserException { String sqlStr = - "SELECT * EXCEPT (order_id) REPLACE (\"widget\" AS item_name), \"more\" as more_fields\n" + "SELECT * EXCEPT(order_id) REPLACE(\"widget\" AS item_name), \"more\" as more_fields\n" + + "FROM orders"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testDuckDBQuerySyntax() throws JSQLParserException { + String sqlStr = + "SELECT * EXCLUDE(order_id) REPLACE(\"widget\" AS item_name), \"more\" as more_fields\n" + "FROM orders"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/AllTableColumnsTest.java b/src/test/java/net/sf/jsqlparser/statement/select/AllTableColumnsTest.java index 0a0a9950c..f6dca8eba 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/AllTableColumnsTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/AllTableColumnsTest.java @@ -22,4 +22,12 @@ void testBigQuerySyntax() throws JSQLParserException { + "FROM orders"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + void testDuckDBSyntax() throws JSQLParserException { + String sqlStr = + "SELECT orders.* EXCLUDE (order_id)\n" + + "FROM orders"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/BigQueryTest.java b/src/test/java/net/sf/jsqlparser/statement/select/BigQueryTest.java new file mode 100644 index 000000000..d4dbd74b0 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/statement/select/BigQueryTest.java @@ -0,0 +1,95 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement.select; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +public class BigQueryTest { + + @Test + @Disabled + void testTrailingComma() { + // allows trailing commas after the last select items + String sqlStr = "WITH\n" + + " Products AS (\n" + + " SELECT 'shirt' AS product_type, 't-shirt' AS product_name, 3 AS product_count UNION ALL\n" + + + " SELECT 'shirt', 't-shirt', 8 UNION ALL\n" + + " SELECT 'shirt', 'polo', 25 UNION ALL\n" + + " SELECT 'pants', 'jeans', 6\n" + + " )\n" + + "SELECT\n" + + " product_type,\n" + + " product_name,\n" + + " SUM(product_count) AS product_sum,\n" + + " GROUPING(product_type) AS product_type_agg,\n" + + " GROUPING(product_name) AS product_name_agg,\n" + + "FROM Products\n" + + "GROUP BY GROUPING SETS(product_type, product_name, ())\n" + + "ORDER BY product_name, product_type"; + } + + @Test + void testAggregateFunctionIgnoreNulls() throws JSQLParserException { + String sqlStr = "SELECT ARRAY_AGG(x IGNORE NULLS) AS array_agg\n" + + "FROM UNNEST([NULL, 1, -2, 3, -2, 1, NULL]) AS x"; + + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testAggregateFunctionLimit() throws JSQLParserException { + String sqlStr = "SELECT ARRAY_AGG(x LIMIT 5) AS array_agg\n" + + "FROM UNNEST([2, 1, -2, 3, -2, 1, 2]) AS x;\n"; + + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testAny() throws JSQLParserException { + String sqlStr = "SELECT\n" + + " fruit,\n" + + " ANY_VALUE(fruit) OVER (ORDER BY LENGTH(fruit) ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS any_value\n" + + + "FROM UNNEST(['apple', 'banana', 'pear']) as fruit;\n"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testAggregateFunctionHaving() throws JSQLParserException { + String sqlStr = "WITH\n" + + " Store AS (\n" + + " SELECT 20 AS sold, \"apples\" AS fruit\n" + + " UNION ALL\n" + + " SELECT 30 AS sold, \"pears\" AS fruit\n" + + " UNION ALL\n" + + " SELECT 30 AS sold, \"bananas\" AS fruit\n" + + " UNION ALL\n" + + " SELECT 10 AS sold, \"oranges\" AS fruit\n" + + " )\n" + + "SELECT ANY_VALUE(fruit HAVING MAX sold) AS a_highest_selling_fruit FROM Store;\n"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testAsStruct() throws JSQLParserException { + String sqlStr = "SELECT ARRAY(SELECT AS STRUCT 1 a, 2 b)"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testAsValue() throws JSQLParserException { + String sqlStr = "SELECT AS VALUE STRUCT(1 AS a, 2 AS b) xyz"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } +} diff --git a/src/test/java/net/sf/jsqlparser/statement/select/DB2Test.java b/src/test/java/net/sf/jsqlparser/statement/select/DB2Test.java index 2aab3162b..296aab55d 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/DB2Test.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/DB2Test.java @@ -16,7 +16,8 @@ public class DB2Test { @Test void testDB2SpecialRegister() throws JSQLParserException { - String sqlStr = "SELECT * FROM TABLE1 where COL_WITH_TIMESTAMP <= CURRENT TIMESTAMP - CURRENT TIMEZONE"; + String sqlStr = + "SELECT * FROM TABLE1 where COL_WITH_TIMESTAMP <= CURRENT TIMESTAMP - CURRENT TIMEZONE"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/ExpressionDelimiterTest.java b/src/test/java/net/sf/jsqlparser/statement/select/ExpressionDelimiterTest.java new file mode 100644 index 000000000..cb4a63c97 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/statement/select/ExpressionDelimiterTest.java @@ -0,0 +1,40 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement.select; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.schema.Column; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ExpressionDelimiterTest { + + @Test + public void testColumnWithDifferentDelimiters() throws JSQLParserException { + String statement = "SELECT mytable.mycolumn:parent:child FROM mytable"; + PlainSelect parsed = (PlainSelect) assertSqlCanBeParsedAndDeparsed(statement); + Column column = parsed.getSelectItem(0).getExpression(Column.class); + assertEquals(":", column.getTableDelimiter()); + assertEquals(List.of(":", "."), column.getTable().getNamePartDelimiters()); + } + + @Test + public void testColumnWithEmptyNameParts() throws JSQLParserException { + String statement = "SELECT mytable.:.child FROM mytable"; + PlainSelect parsed = (PlainSelect) assertSqlCanBeParsedAndDeparsed(statement); + Column column = parsed.getSelectItem(0).getExpression(Column.class); + assertEquals(".", column.getTableDelimiter()); + assertEquals(List.of(":", "."), column.getTable().getNamePartDelimiters()); + } +} diff --git a/src/test/java/net/sf/jsqlparser/statement/select/ForUpdateTest.java b/src/test/java/net/sf/jsqlparser/statement/select/ForUpdateTest.java new file mode 100644 index 000000000..ecd216217 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/statement/select/ForUpdateTest.java @@ -0,0 +1,47 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement.select; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +public class ForUpdateTest { + + @Test + void testOracleForUpdate() throws JSQLParserException { + String sqlStr = "SELECT e.employee_id, e.salary, e.commission_pct\n" + + " FROM employees e, departments d\n" + + " WHERE job_id = 'SA_REP'\n" + + " AND e.department_id = d.department_id\n" + + " AND location_id = 2500\n" + + " ORDER BY e.employee_id\n" + + " FOR UPDATE;\n"; + + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT e.employee_id, e.salary, e.commission_pct\n" + + " FROM employees e JOIN departments d\n" + + " USING (department_id)\n" + + " WHERE job_id = 'SA_REP'\n" + + " AND location_id = 2500\n" + + " ORDER BY e.employee_id\n" + + " FOR UPDATE OF e.salary;"; + + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testMySqlIssue1995() throws JSQLParserException { + String sqlStr = "select * from t_demo where a = 1 order by b asc limit 1 for update"; + + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } +} diff --git a/src/test/java/net/sf/jsqlparser/statement/select/MemoryTest.java b/src/test/java/net/sf/jsqlparser/statement/select/MemoryTest.java index 1c0135ec1..9f452566f 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/MemoryTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/MemoryTest.java @@ -23,19 +23,28 @@ public static void main(String[] args) throws Exception { String longQuery = "select * from k where ID > 4"; /* - * String longQuery = "select * from ( SELECT intermediate.id as id , intermediate.date as " - * + "date FROM ( SELECT DISTINCT ( id ) FROM ( SELECT " + - * "wct_workflows.workflow_id as id , wct_transaction.date as date FROM " + - * "wct_audit_entry , wct_transaction , wct_workflows WHERE " + - * "( wct_audit_entry.privilege = 'W' or wct_audit_entry.privilege = " + "'C' ))))"; + * String longQuery = + * "select * from ( SELECT intermediate.id as id , intermediate.date as " + * + + * "date FROM ( SELECT DISTINCT ( id ) FROM ( SELECT " + * + + * "wct_workflows.workflow_id as id , wct_transaction.date as date FROM " + * + + * "wct_audit_entry , wct_transaction , wct_workflows WHERE " + * + + * "( wct_audit_entry.privilege = 'W' or wct_audit_entry.privilege = " + * + "'C' ))))"; */ - /* + /* * String longQuery = "select * from d WHERE " + - * "( wct_audit_entry.privilege = 'W' or wct_audit_entry.privilege = " + - * "'C' ) and wct_audit_entry.outcome = 't' and " + - * "wct_audit_entry.transaction_id = wct_transaction.transaction_id and " + - * "wct_transaction.user_id = 164 and wct_audit_entry.object_id = " + - * "wct_workflows.active_version_id "; + * "( wct_audit_entry.privilege = 'W' or wct_audit_entry.privilege = " + * + + * "'C' ) and wct_audit_entry.outcome = 't' and " + * + + * "wct_audit_entry.transaction_id = wct_transaction.transaction_id and " + * + + * "wct_transaction.user_id = 164 and wct_audit_entry.object_id = " + * + "wct_workflows.active_version_id "; */ StringReader stringReader = new StringReader(longQuery); Statement statement = parserManager.parse(stringReader); diff --git a/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java b/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java index 569b88873..83a4fe7ae 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.statement.select; import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; @@ -124,12 +125,10 @@ public void testRecursiveBracketExpressionIssue1019() { } // maxDepth = 10 collides with the Parser Timeout = 6 seconds - // temporarily restrict it to maxDepth = 4 for the moment // @todo: implement methods to set the Parser Timeout explicitly and on demand - // @todo Investigate performance deterioration since JSQLParser 5.0pre development @Test public void testRecursiveBracketExpressionIssue1019_2() throws JSQLParserException { - doIncreaseOfParseTimeTesting("IF(1=1, $1, 2)", "1", 4); + doIncreaseOfParseTimeTesting("IF(1=1, $1, 2)", "1", 8); } @Test @@ -355,4 +354,168 @@ public void testDeepFunctionParameters() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + @Disabled + void testIssue1983() throws JSQLParserException { + String sqlStr = "INSERT INTO\n" + + "C01_INDIV_TELBK_CUST_INFO_H_T2 (PARTY_ID, PARTY_SIGN_STAT_CD, SIGN_TM, CLOSE_TM)\n" + + + "SELECT\n" + + "A1.PARTY_ID,\n" + + "A1.PARTY_SIGN_STAT_CD,\n" + + "CAST(\n" + + "(\n" + + "CASE\n" + + "WHEN A1.SIGN_TM IS NULL\n" + + "OR A1.SIGN_TM = '' THEN CAST(\n" + + "CAST(\n" + + "CAST('ATkkIVQJZm' AS DATE FORMAT 'YYYYMMDD') AS DATE\n" + + ") || ' 00:00:00' AS TIMESTAMP\n" + + ")\n" + + "WHEN CHARACTERS (TRIM(A1.SIGN_TM)) <> 19\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 1, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 1, 1) > '9'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 2, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 2, 1) > '9'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 3, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 3, 1) > '9'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 4, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 4, 1) > '9'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 6, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 6, 1) > '1'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 7, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 7, 1) > '9'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 9, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 9, 1) > '3'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 10, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 10, 1) > '9'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 1, 4) = '0000'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 6, 2) = '00'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 9, 2) = '00'\n" + + "OR SUBSTR (TRIM(A1.SIGN_TM), 1, 1) = '0' THEN CAST(\n" + + "CAST(\n" + + "CAST('cDXtwdFyky' AS DATE FORMAT 'YYYYMMDD') AS DATE\n" + + ") || ' 00:00:00' AS TIMESTAMP\n" + + ")\n" + + "ELSE (\n" + + "CASE\n" + + "WHEN (\n" + + "CAST(SUBSTR (TRIM(A1.SIGN_TM), 9, 2) AS INTEGER) < 29\n" + + "AND SUBSTR (TRIM(A1.SIGN_TM), 6, 2) = '02'\n" + + ")\n" + + "OR (\n" + + "CAST(SUBSTR (TRIM(A1.SIGN_TM), 9, 2) AS INTEGER) < 31\n" + + "AND SUBSTR (TRIM(A1.SIGN_TM), 6, 2) <> '02'\n" + + "AND SUBSTR (TRIM(A1.SIGN_TM), 6, 2) <= 12\n" + + ")\n" + + "OR (\n" + + "CAST(SUBSTR (TRIM(A1.SIGN_TM), 9, 2) AS INTEGER) = 31\n" + + "AND SUBSTR (TRIM(A1.SIGN_TM), 6, 2) IN ('01', '03', '05', '07', '08', '10', '12')\n" + + + ") THEN CAST(A1.SIGN_TM AS TIMESTAMP)\n" + + "WHEN SUBSTR (TRIM(A1.SIGN_TM), 6, 2) || SUBSTR (TRIM(A1.SIGN_TM), 9, 2) = '0229'\n" + + + "AND (\n" + + "CAST(SUBSTR (TRIM(A1.SIGN_TM), 1, 4) AS INTEGER) MOD 400 = 0\n" + + "OR (\n" + + "CAST(SUBSTR (TRIM(A1.SIGN_TM), 1, 4) AS INTEGER) MOD 4 = 0\n" + + "AND CAST(SUBSTR (TRIM(A1.SIGN_TM), 1, 4) AS INTEGER) MOD 100 <> 0\n" + + ")\n" + + ") THEN CAST(A1.SIGN_TM AS TIMESTAMP)\n" + + "ELSE CAST(\n" + + "CAST(\n" + + "CAST('cDXtwdFyky' AS DATE FORMAT 'YYYYMMDD') AS DATE\n" + + ") || ' 00:00:00' AS TIMESTAMP\n" + + ")\n" + + "END\n" + + ")\n" + + "END\n" + + ") AS DATE FORMAT 'YYYYMMDD'\n" + + "),\n" + + "CAST(\n" + + "(\n" + + "CASE\n" + + "WHEN A1.CLOSE_TM IS NULL\n" + + "OR A1.CLOSE_TM = '' THEN CAST(\n" + + "CAST(\n" + + "CAST('ATkkIVQJZm' AS DATE FORMAT 'YYYYMMDD') AS DATE\n" + + ") || ' 00:00:00' AS TIMESTAMP\n" + + ")\n" + + "WHEN CHARACTERS (TRIM(A1.CLOSE_TM)) <> 19\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 1, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 1, 1) > '9'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 2, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 2, 1) > '9'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 3, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 3, 1) > '9'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 4, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 4, 1) > '9'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 6, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 6, 1) > '1'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 7, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 7, 1) > '9'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 9, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 9, 1) > '3'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 10, 1) < '0'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 10, 1) > '9'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 1, 4) = '0000'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 6, 2) = '00'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 9, 2) = '00'\n" + + "OR SUBSTR (TRIM(A1.CLOSE_TM), 1, 1) = '0' THEN CAST(\n" + + "CAST(\n" + + "CAST('cDXtwdFyky' AS DATE FORMAT 'YYYYMMDD') AS DATE\n" + + ") || ' 00:00:00' AS TIMESTAMP\n" + + ")\n" + + "ELSE (\n" + + "CASE\n" + + "WHEN (\n" + + "CAST(SUBSTR (TRIM(A1.CLOSE_TM), 9, 2) AS INTEGER) < 29\n" + + "AND SUBSTR (TRIM(A1.CLOSE_TM), 6, 2) = '02'\n" + + ")\n" + + "OR (\n" + + "CAST(SUBSTR (TRIM(A1.CLOSE_TM), 9, 2) AS INTEGER) < 31\n" + + "AND SUBSTR (TRIM(A1.CLOSE_TM), 6, 2) <> '02'\n" + + "AND SUBSTR (TRIM(A1.CLOSE_TM), 6, 2) <= 12\n" + + ")\n" + + "OR (\n" + + "CAST(SUBSTR (TRIM(A1.CLOSE_TM), 9, 2) AS INTEGER) = 31\n" + + "AND SUBSTR (TRIM(A1.CLOSE_TM), 6, 2) IN ('01', '03', '05', '07', '08', '10', '12')\n" + + + ") THEN CAST(A1.CLOSE_TM AS TIMESTAMP)\n" + + "WHEN SUBSTR (TRIM(A1.CLOSE_TM), 6, 2) || SUBSTR (TRIM(A1.CLOSE_TM), 9, 2) = '0229'\n" + + + "AND (\n" + + "CAST(SUBSTR (TRIM(A1.CLOSE_TM), 1, 4) AS INTEGER) MOD 400 = 0\n" + + "OR (\n" + + "CAST(SUBSTR (TRIM(A1.CLOSE_TM), 1, 4) AS INTEGER) MOD 4 = 0\n" + + "AND CAST(SUBSTR (TRIM(A1.CLOSE_TM), 1, 4) AS INTEGER) MOD 100 <> 0\n" + + ")\n" + + ") THEN CAST(A1.CLOSE_TM AS TIMESTAMP)\n" + + "ELSE CAST(\n" + + "CAST(\n" + + "CAST('cDXtwdFyky' AS DATE FORMAT 'YYYYMMDD') AS DATE\n" + + ") || ' 00:00:00' AS TIMESTAMP\n" + + ")\n" + + "END\n" + + ")\n" + + "END\n" + + ") AS DATE FORMAT 'YYYYMMDD'\n" + + ")\n" + + "FROM\n" + + "T01_PTY_SIGN_H_T1 A1\n" + + "WHERE\n" + + "A1.PARTY_SIGN_TYPE_CD = 'CD_021'\n" + + "AND A1.ST_DT <= CAST('LDBCGtCIyo' AS DATE FORMAT 'YYYYMMDD')\n" + + "AND A1.END_DT > CAST('LDBCGtCIyo' AS DATE FORMAT 'YYYYMMDD')\n" + + "GROUP BY\n" + + "1,\n" + + "2,\n" + + "3,\n" + + "4"; + CCJSqlParserUtil.parse(sqlStr, parser -> parser + .withSquareBracketQuotation(false) + .withAllowComplexParsing(true) + .withTimeOut(60000)); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/ParenthesedSelectTest.java b/src/test/java/net/sf/jsqlparser/statement/select/ParenthesedSelectTest.java new file mode 100644 index 000000000..6ddccb8e5 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/statement/select/ParenthesedSelectTest.java @@ -0,0 +1,38 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement.select; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class ParenthesedSelectTest { + @Test + void testConstructFromItem() throws JSQLParserException { + String sqlStr = "select winsales.* from winsales;"; + + PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); + select.setFromItem(new ParenthesedSelect(select.getFromItem())); + + TestUtils.assertStatementCanBeDeparsedAs(select, + "select winsales.* from (select * from winsales) AS winsales;", true); + + sqlStr = "select a.* from winsales AS a;"; + + select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); + select.setFromItem(new ParenthesedSelect(select.getFromItem())); + + TestUtils.assertStatementCanBeDeparsedAs(select, + "select a.* from (select * from winsales AS a) AS a;", true); + } +} diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SQLiteTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SQLiteTest.java index cd8e41c95..ecb120495 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SQLiteTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SQLiteTest.java @@ -16,7 +16,7 @@ public class SQLiteTest { @Test void testInsertOrReplaceUpsert() throws JSQLParserException { - String sqlString="INSERT OR REPLACE INTO kjobLocks VALUES (?, ?, ?)"; + String sqlString = "INSERT OR REPLACE INTO kjobLocks VALUES (?, ?, ?)"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlString, true); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java index fd4f28099..4111ba34a 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -16,6 +16,7 @@ import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; import static net.sf.jsqlparser.test.TestUtils.assertStatementCanBeDeparsedAs; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -24,7 +25,6 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.StringReader; @@ -1080,13 +1080,15 @@ public void testDistinctTop() throws JSQLParserException { @Test public void testDistinctTop2() { - String statement = "SELECT TOP 5 DISTINCT myid, mycol FROM mytable WHERE mytable.col = 9"; - try { - parserManager.parse(new StringReader(statement)); - fail("sould not work"); - } catch (JSQLParserException ex) { - // expected to fail - } + // valid on Redshift + // https://docs.aws.amazon.com/redshift/latest/dg/r_SELECT_list.html + String sqlStr = "SELECT TOP 5 DISTINCT myid, mycol FROM mytable WHERE mytable.col = 9"; + assertDoesNotThrow(new Executable() { + @Override + public void execute() throws Throwable { + CCJSqlParserUtil.parse(sqlStr); + } + }); } @Test @@ -2749,7 +2751,8 @@ public void testUnPivotWithAlias() throws JSQLParserException { + " WHERE simulation_id = 210 AND data_timestamp BETWEEN convert(datetime, '2021-09-14', 120) AND convert(datetime, '2021-09-18', 120)" + " GROUP BY simulation_id) sim_data" + " UNPIVOT" + " (" + "val" + " FOR signal IN (DosingOnStatus_TenMinutes_sim, DosingOnDuration_Hour_sim)" - + ") un_piv_alias"); + + ") un_piv_alias", + true); } @Test @@ -4369,21 +4372,22 @@ public void testDateArithmentic11() throws JSQLParserException { String sql = "select CURRENT_DATE + (dayofweek(MY_DUE_DATE) + 5) DAY FROM mytable"; assertSqlCanBeParsedAndDeparsed(sql, true); Select select = (Select) CCJSqlParserUtil.parse(sql); - final List list = new ArrayList<>(); - select.accept(new SelectVisitorAdapter() { + final List> list = new ArrayList<>(); + select.accept(new SelectVisitorAdapter() { @Override - public void visit(PlainSelect plainSelect) { + public Void visit(PlainSelect plainSelect, S parameters) { list.addAll(plainSelect.getSelectItems()); + return null; } - }); + }, null); assertEquals(1, list.size()); - assertTrue(list.get(0) instanceof SelectItem); - SelectItem item = list.get(0); - assertTrue(item.getExpression() instanceof Addition); + assertInstanceOf(SelectItem.class, list.get(0)); + SelectItem item = list.get(0); + assertInstanceOf(Addition.class, item.getExpression()); Addition add = (Addition) item.getExpression(); - assertTrue(add.getRightExpression() instanceof IntervalExpression); + assertInstanceOf(IntervalExpression.class, add.getRightExpression()); } @Test @@ -4398,18 +4402,19 @@ public void testDateArithmentic13() throws JSQLParserException { String sql = "SELECT INTERVAL 5 MONTH MONTH FROM mytable"; assertSqlCanBeParsedAndDeparsed(sql); Select select = (Select) CCJSqlParserUtil.parse(sql); - final List list = new ArrayList<>(); - select.accept(new SelectVisitorAdapter() { + final List> list = new ArrayList<>(); + select.accept(new SelectVisitorAdapter() { @Override - public void visit(PlainSelect plainSelect) { + public Void visit(PlainSelect plainSelect, S parameters) { list.addAll(plainSelect.getSelectItems()); + return null; } - }); + }, null); assertEquals(1, list.size()); - assertTrue(list.get(0) instanceof SelectItem); - SelectItem item = list.get(0); - assertTrue(item.getExpression() instanceof IntervalExpression); + assertInstanceOf(SelectItem.class, list.get(0)); + SelectItem item = list.get(0); + assertInstanceOf(IntervalExpression.class, item.getExpression()); IntervalExpression interval = (IntervalExpression) item.getExpression(); assertEquals("INTERVAL 5 MONTH", interval.toString()); assertEquals("MONTH", item.getAlias().getName()); @@ -4421,21 +4426,23 @@ public void testRawStringExpressionIssue656(String prefix) throws JSQLParserExce String sql = "select " + prefix + "'test' from foo"; Statement statement = CCJSqlParserUtil.parse(sql); assertNotNull(statement); - statement.accept(new StatementVisitorAdapter() { + statement.accept(new StatementVisitorAdapter() { @Override - public void visit(Select select) { - select.accept(new SelectVisitorAdapter() { + public Void visit(Select select, S context) { + select.accept(new SelectVisitorAdapter() { @Override - public void visit(PlainSelect plainSelect) { - SelectItem typedExpression = - (SelectItem) plainSelect.getSelectItems().get(0); + public Void visit(PlainSelect plainSelect, K context) { + SelectItem typedExpression = + (SelectItem) plainSelect.getSelectItems().get(0); assertNotNull(typedExpression); assertNull(typedExpression.getAlias()); StringValue value = (StringValue) typedExpression.getExpression(); assertEquals(prefix.toUpperCase(), value.getPrefix()); assertEquals("test", value.getValue()); + return null; } - }); + }, context); + return null; } }); } @@ -4817,7 +4824,7 @@ public void testIssue1878ViaJava() throws JSQLParserException { // Step 1: generate the Java Object Hierarchy for Table table = new Table().withName("MY_TABLE1"); - PlainSelect select = new PlainSelect().addSelectItem(new AllColumns()) + Select select = new PlainSelect().addSelectItem(new AllColumns()) .withFromItem(table).withForMode(ForMode.KEY_SHARE).withForMode(ForMode.SHARE); Assertions.assertEquals(expectedSQLStr, select.toString()); @@ -5638,14 +5645,6 @@ void testSetOperationListWithBracketsIssue1737() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed(sqlStr, true); } - @Test - void subJoinTest() throws JSQLParserException { - String sqlStr = - "select su.d\n" + "from sku su\n" + "for update of su.up\n" + "order by su.d"; - - TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); - } - @Test void testNestedWithItems() throws JSQLParserException { String sqlStr = @@ -5819,4 +5818,22 @@ public void testIssue1833() throws JSQLParserException { String stmt = "SELECT age, name, gender FROM user_info INTO TEMP user_temp WITH NO LOG"; assertSqlCanBeParsedAndDeparsed(stmt); } + + @Test + void testGroupByWithHaving() throws JSQLParserException { + String sqlStr = "-- GROUP BY\n" + + "SELECT a\n" + + " , b\n" + + " , c\n" + + " , Sum( d )\n" + + "FROM t\n" + + "GROUP BY a\n" + + " , b\n" + + " , c\n" + + "HAVING Sum( d ) > 0\n" + + " AND Count( * ) > 1\n" + + ";"; + Statement stmt = assertSqlCanBeParsedAndDeparsed(sqlStr); + Assertions.assertInstanceOf(Select.class, stmt); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java index d0bbed775..f4cb8637d 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java @@ -84,7 +84,7 @@ public class SpecialOracleTest { "datetime02.sql", "datetime04.sql", "datetime05.sql", "datetime06.sql", "dblink01.sql", "for_update01.sql", "for_update02.sql", "for_update03.sql", "function04.sql", "function05.sql", "for_update04.sql", "for_update05.sql", "for_update06.sql", - "for_update08.sql", "function01.sql", "function02.sql", "function03.sql", + "function01.sql", "function02.sql", "function03.sql", "function06.sql", "groupby01.sql", "groupby02.sql", "groupby03.sql", "groupby04.sql", "groupby05.sql", "groupby06.sql", @@ -99,7 +99,8 @@ public class SpecialOracleTest { "join21.sql", "keywordasidentifier01.sql", "keywordasidentifier02.sql", "keywordasidentifier03.sql", "keywordasidentifier04.sql", "keywordasidentifier05.sql", "lexer02.sql", "lexer03.sql", "lexer04.sql", "lexer05.sql", "like01.sql", "merge01.sql", - "merge02.sql", "merge03.sql", "merge04.sql", "order_by01.sql", "order_by02.sql", + "merge02.sql", "merge03.sql", "merge04.sql", "object_access01.sql", "order_by01.sql", + "order_by02.sql", "order_by03.sql", "order_by04.sql", "order_by05.sql", "order_by06.sql", "pivot01.sql", "pivot02.sql", "pivot03.sql", "pivot04.sql", "pivot05.sql", "pivot06.sql", "pivot07.sql", "pivot07_Parenthesis.sql", diff --git a/src/test/java/net/sf/jsqlparser/statement/select/TableFunctionTest.java b/src/test/java/net/sf/jsqlparser/statement/select/TableFunctionTest.java index dec463eda..b53000455 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/TableFunctionTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/TableFunctionTest.java @@ -31,4 +31,20 @@ void testLateralFlat() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + /** + * The SQL keyword "OUTER" is a valid parameter name for Snowflake's FLATTEN table function. + */ + @Test + void testTableFunctionWithNamedParameterWhereNameIsOuterKeyword() throws JSQLParserException { + String sqlStr = + "INSERT INTO db.schema.target\n" + + " (Name, FriendParent)\n" + + " SELECT\n" + + " i.DATA_VALUE:Name AS Name,\n" + + " f1.Value:Parent:Name AS FriendParent\n" + + " FROM\n" + + " db.schema.source AS i,\n" + + " lateral flatten(input => i.DATA_VALUE:Friends, outer => true) AS f1;"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/WindowFunctionTest.java b/src/test/java/net/sf/jsqlparser/statement/select/WindowFunctionTest.java index e6d8f1e92..6a0beb7ac 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/WindowFunctionTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/WindowFunctionTest.java @@ -18,8 +18,23 @@ public class WindowFunctionTest { public void testListAggOverIssue1652() throws JSQLParserException { String sqlString = "SELECT\n" + - " LISTAGG (d.COL_TO_AGG, ' / ') WITHIN GROUP (ORDER BY d.COL_TO_AGG) OVER (PARTITION BY d.PART_COL) AS MY_LISTAGG\n" + - "FROM cte_dummy_data d"; + " LISTAGG (d.COL_TO_AGG, ' / ') WITHIN GROUP (ORDER BY d.COL_TO_AGG) OVER (PARTITION BY d.PART_COL) AS MY_LISTAGG\n" + + + "FROM cte_dummy_data d"; + + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlString, true); + } + + @Test + public void RedshiftRespectIgnoreNulls() throws JSQLParserException { + String sqlString = + "select venuestate, venueseats, venuename,\n" + + "first_value(venuename) ignore nulls\n" + + "over(partition by venuestate\n" + + "order by venueseats desc\n" + + "rows between unbounded preceding and unbounded following) AS first\n" + + "from (select * from venue where venuestate='CA')\n" + + "order by venuestate;"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlString, true); } diff --git a/src/test/java/net/sf/jsqlparser/statement/show/ShowTablesStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/show/ShowTablesStatementTest.java index e5743e7a3..c880640b1 100644 --- a/src/test/java/net/sf/jsqlparser/statement/show/ShowTablesStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/show/ShowTablesStatementTest.java @@ -50,15 +50,20 @@ public void showTablesWhereExpression() throws Exception { @Test public void testObject() throws JSQLParserException, JSQLParserException { - ShowTablesStatement showTablesStatement = (ShowTablesStatement) CCJSqlParserUtil.parse("SHOW TABLES WHERE table_name = 'FOO'"); + ShowTablesStatement showTablesStatement = (ShowTablesStatement) CCJSqlParserUtil + .parse("SHOW TABLES WHERE table_name = 'FOO'"); assertEquals(0, showTablesStatement.getModifiers().size()); - TestUtils.assertExpressionCanBeDeparsedAs(showTablesStatement.getWhereCondition(), "table_name = 'FOO'"); + TestUtils.assertExpressionCanBeDeparsedAs(showTablesStatement.getWhereCondition(), + "table_name = 'FOO'"); - showTablesStatement = (ShowTablesStatement) CCJSqlParserUtil.parse("SHOW FULL TABLES IN db_name"); + showTablesStatement = + (ShowTablesStatement) CCJSqlParserUtil.parse("SHOW FULL TABLES IN db_name"); assertEquals(1, showTablesStatement.getModifiers().size()); assertEquals(ShowTablesStatement.SelectionMode.IN, showTablesStatement.getSelectionMode()); - showTablesStatement = (ShowTablesStatement) CCJSqlParserUtil.parse("SHOW TABLES LIKE '%FOO%'"); - TestUtils.assertExpressionCanBeDeparsedAs(showTablesStatement.getLikeExpression(), "'%FOO%'"); + showTablesStatement = + (ShowTablesStatement) CCJSqlParserUtil.parse("SHOW TABLES LIKE '%FOO%'"); + TestUtils.assertExpressionCanBeDeparsedAs(showTablesStatement.getLikeExpression(), + "'%FOO%'"); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/simpleparsing/CCJSqlParserManagerTest.java b/src/test/java/net/sf/jsqlparser/statement/simpleparsing/CCJSqlParserManagerTest.java index 6664f5405..1a342b42d 100644 --- a/src/test/java/net/sf/jsqlparser/statement/simpleparsing/CCJSqlParserManagerTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/simpleparsing/CCJSqlParserManagerTest.java @@ -24,8 +24,8 @@ public class CCJSqlParserManagerTest { @Test public void testParse() throws Exception { CCJSqlParserManager parserManager = new CCJSqlParserManager(); - BufferedReader in = new BufferedReader(new InputStreamReader(Objects.requireNonNull(CreateTableTest.class. - getResourceAsStream("/simple_parsing.txt")))); + BufferedReader in = new BufferedReader(new InputStreamReader(Objects + .requireNonNull(CreateTableTest.class.getResourceAsStream("/simple_parsing.txt")))); String statement = ""; while (true) { @@ -69,8 +69,7 @@ public static String getLine(BufferedReader in) throws Exception { while (true) { line = in.readLine(); if (line != null) { - if (line.length() < 2 || !(line.charAt(0) == '/' && line. - charAt(1) == '/')) { + if (line.length() < 2 || !(line.charAt(0) == '/' && line.charAt(1) == '/')) { break; } } else { diff --git a/src/test/java/net/sf/jsqlparser/statement/values/ValuesTest.java b/src/test/java/net/sf/jsqlparser/statement/values/ValuesTest.java index 71718ad56..62a07a9ba 100644 --- a/src/test/java/net/sf/jsqlparser/statement/values/ValuesTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/values/ValuesTest.java @@ -29,6 +29,15 @@ public void testRowConstructor() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + @Test + public void testSelectRowConstructor() throws JSQLParserException { + String sqlStr = "select * from values 1, 2, 3;"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "select * from values (1, 2), (3, 4), (5,6);"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + @Test public void testDuplicateKey() throws JSQLParserException { String statement = "VALUES (1, 2, 'test')"; @@ -55,4 +64,11 @@ public void testObject() { valuesStatement.accept(new StatementVisitorAdapter()); } + + @Test + public void testValuesWithAliasWithoutAs() throws JSQLParserException { + String sqlStr = "SELECT a, b, cume_dist() OVER (PARTITION BY a ORDER BY b) AS cume_dist\n" + + " FROM VALUES ('A1', 2), ('A1', 1), ('A2', 3), ('A1', 1) tab(a, b);"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/test/AssortedFeatureTests.java b/src/test/java/net/sf/jsqlparser/test/AssortedFeatureTests.java index 971a7f434..e2c488b40 100644 --- a/src/test/java/net/sf/jsqlparser/test/AssortedFeatureTests.java +++ b/src/test/java/net/sf/jsqlparser/test/AssortedFeatureTests.java @@ -24,13 +24,15 @@ public class AssortedFeatureTests { static class ReplaceColumnAndLongValues extends ExpressionDeParser { @Override - public void visit(StringValue stringValue) { + public StringBuilder visit(StringValue stringValue, K parameters) { this.getBuffer().append("?"); + return null; } @Override - public void visit(LongValue longValue) { + public StringBuilder visit(LongValue longValue, K parameters) { this.getBuffer().append("?"); + return null; } } @@ -53,8 +55,10 @@ public static String cleanStatement(String sql) throws JSQLParserException { @Test public void testIssue1608() throws JSQLParserException { System.out.println(cleanStatement("SELECT 'abc', 5 FROM mytable WHERE col='test'")); - System.out.println(cleanStatement("UPDATE table1 A SET A.columna = 'XXX' WHERE A.cod_table = 'YYY'")); - System.out.println(cleanStatement("INSERT INTO example (num, name, address, tel) VALUES (1, 'name', 'test ', '1234-1234')")); + System.out.println( + cleanStatement("UPDATE table1 A SET A.columna = 'XXX' WHERE A.cod_table = 'YYY'")); + System.out.println(cleanStatement( + "INSERT INTO example (num, name, address, tel) VALUES (1, 'name', 'test ', '1234-1234')")); System.out.println(cleanStatement("DELETE FROM table1 where col=5 and col2=4")); } } diff --git a/src/test/java/net/sf/jsqlparser/test/HowToUseSample.java b/src/test/java/net/sf/jsqlparser/test/HowToUseSample.java index 91cd3aa8f..731e24e2c 100644 --- a/src/test/java/net/sf/jsqlparser/test/HowToUseSample.java +++ b/src/test/java/net/sf/jsqlparser/test/HowToUseSample.java @@ -118,7 +118,7 @@ public void howToParseStatement() throws JSQLParserException { PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); - SelectItem selectItem = + SelectItem selectItem = select.getSelectItems().get(0); Assertions.assertEquals( new LongValue(1), selectItem.getExpression()); @@ -138,30 +138,33 @@ public void howToUseVisitors() throws JSQLParserException { // Define an Expression Visitor reacting on any Expression // Overwrite the visit() methods for each Expression Class - ExpressionVisitorAdapter expressionVisitorAdapter = new ExpressionVisitorAdapter() { - public void visit(EqualsTo equalsTo) { - equalsTo.getLeftExpression().accept(this); - equalsTo.getRightExpression().accept(this); - } - - public void visit(Column column) { - System.out.println("Found a Column " + column.getColumnName()); - } - }; + ExpressionVisitorAdapter expressionVisitorAdapter = + new ExpressionVisitorAdapter() { + public Void visit(EqualsTo equalsTo, K context) { + equalsTo.getLeftExpression().accept(this, context); + equalsTo.getRightExpression().accept(this, context); + return null; + } + + public Void visit(Column column, K context) { + System.out.println("Found a Column " + column.getColumnName()); + return null; + } + }; // Define a Select Visitor reacting on a Plain Select invoking the Expression Visitor on the // Where Clause - SelectVisitorAdapter selectVisitorAdapter = new SelectVisitorAdapter() { + SelectVisitorAdapter selectVisitorAdapter = new SelectVisitorAdapter() { @Override - public void visit(PlainSelect plainSelect) { - plainSelect.getWhere().accept(expressionVisitorAdapter); + public Void visit(PlainSelect plainSelect, K context) { + return plainSelect.getWhere().accept(expressionVisitorAdapter, context); } }; // Define a Statement Visitor for dispatching the Statements - StatementVisitorAdapter statementVisitor = new StatementVisitorAdapter() { - public void visit(Select select) { - select.accept(selectVisitorAdapter); + StatementVisitorAdapter statementVisitor = new StatementVisitorAdapter() { + public Void visit(Select select, K context) { + return select.accept(selectVisitorAdapter, context); } }; @@ -213,8 +216,8 @@ void migrationTest2() throws JSQLParserException { " FROM ( VALUES 1, 2, 3 )"; PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); - ParenthesedSelect subSelect = (ParenthesedSelect) select.getFromItem(); - Values values = (Values) subSelect.getSelect(); + ParenthesedFromItem fromItem = (ParenthesedFromItem) select.getFromItem(); + Values values = (Values) fromItem.getFromItem(); Assertions.assertEquals(3, values.getExpressions().size()); } diff --git a/src/test/java/net/sf/jsqlparser/test/MemoryLeakVerifier.java b/src/test/java/net/sf/jsqlparser/test/MemoryLeakVerifier.java index 112b6896d..f93e178c1 100644 --- a/src/test/java/net/sf/jsqlparser/test/MemoryLeakVerifier.java +++ b/src/test/java/net/sf/jsqlparser/test/MemoryLeakVerifier.java @@ -9,24 +9,23 @@ */ package net.sf.jsqlparser.test; -/* ==================================================================== - Taken from Apache POI, with a big thanks. - - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ +/* + * ==================================================================== Taken from Apache POI, with + * a big thanks. + * + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. You may obtain a + * copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. ==================================================================== + */ import static org.junit.jupiter.api.Assertions.assertNull; @@ -40,28 +39,21 @@ Licensed to the Apache Software Foundation (ASF) under one or more * * Usage is something like * - * private final MemoryLeakVerifier verifier = new MemoryLeakVerifier(); - - {@literal}After - void tearDown() { - verifier.assertGarbageCollected(); - } - - {@literal}Test - void someTest() { - ... - verifier.addObject(object); - } - + * private final MemoryLeakVerifier verifier = new MemoryLeakVerifier(); + * + * {@literal}After void tearDown() { verifier.assertGarbageCollected(); } + * + * {@literal}Test void someTest() { ... verifier.addObject(object); } * - * This will verify at the end of the test if the object is actually removed by the - * garbage collector or if it lingers in memory for some reason. + * + * This will verify at the end of the test if the object is actually removed by the garbage + * collector or if it lingers in memory for some reason. * * Idea taken from http://stackoverflow.com/a/7410460/411846 */ public class MemoryLeakVerifier { private static final int MAX_GC_ITERATIONS = 50; - private static final int GC_SLEEP_TIME = 100; + private static final int GC_SLEEP_TIME = 100; private final List> references = new ArrayList<>(); @@ -70,13 +62,15 @@ public void addObject(Object object) { } /** - * Attempts to perform a full garbage collection so that all weak references will be removed. Usually only - * a single GC is required, but there have been situations where some unused memory is not cleared up on the - * first pass. This method performs a full garbage collection and then validates that the weak reference - * now has been cleared. If it hasn't then the thread will sleep for 100 milliseconds and then retry up to - * 50 more times. If after this the object still has not been collected then the assertion will fail. + * Attempts to perform a full garbage collection so that all weak references will be removed. + * Usually only a single GC is required, but there have been situations where some unused memory + * is not cleared up on the first pass. This method performs a full garbage collection and then + * validates that the weak reference now has been cleared. If it hasn't then the thread will + * sleep for 100 milliseconds and then retry up to 50 more times. If after this the object still + * has not been collected then the assertion will fail. * - * Based upon the method described in: http://www.javaworld.com/javaworld/javatips/jw-javatip130.html + * Based upon the method described in: + * http://www.javaworld.com/javaworld/javatips/jw-javatip130.html */ public void assertGarbageCollected() { assertGarbageCollected(MAX_GC_ITERATIONS); @@ -84,7 +78,9 @@ public void assertGarbageCollected() { /** * Used only for testing the class itself where we would like to fail faster than 5 seconds - * @param maxIterations The number of times a GC will be invoked until a possible memory leak is reported + * + * @param maxIterations The number of times a GC will be invoked until a possible memory leak is + * reported */ void assertGarbageCollected(int maxIterations) { try { @@ -96,7 +92,8 @@ void assertGarbageCollected(int maxIterations) { } } - private static void assertGarbageCollected(WeakReference ref, int maxIterations) throws InterruptedException { + private static void assertGarbageCollected(WeakReference ref, int maxIterations) + throws InterruptedException { Runtime runtime = Runtime.getRuntime(); for (int i = 0; i < maxIterations; i++) { runtime.runFinalization(); @@ -106,11 +103,13 @@ private static void assertGarbageCollected(WeakReference ref, int maxIte } // Pause for a while and then go back around the loop to try again... - //EventQueue.invokeAndWait(Procedure.NoOp); // Wait for the AWT event queue to have completed processing + // EventQueue.invokeAndWait(Procedure.NoOp); // Wait for the AWT event queue to have + // completed processing Thread.sleep(GC_SLEEP_TIME); } - assertNull(ref.get(), "Object should not exist after " + MAX_GC_ITERATIONS + " collections, but still had: " + ref.get()); + assertNull(ref.get(), "Object should not exist after " + MAX_GC_ITERATIONS + + " collections, but still had: " + ref.get()); } } diff --git a/src/test/java/net/sf/jsqlparser/test/TestUtils.java b/src/test/java/net/sf/jsqlparser/test/TestUtils.java index 9ee16ae69..60629087e 100644 --- a/src/test/java/net/sf/jsqlparser/test/TestUtils.java +++ b/src/test/java/net/sf/jsqlparser/test/TestUtils.java @@ -59,7 +59,7 @@ public class TestUtils { // Assure SPACE around Syntax Characters private static final Pattern SQL_SANITATION_PATTERN2 = - Pattern.compile("\\s*([!/,()=+\\-*|\\]<>:])\\s*", Pattern.MULTILINE); + Pattern.compile("\\s*([!/,()=+\\-*|\\]<>:\\[\\]\\{\\}])\\s*", Pattern.MULTILINE); /** * @param statement @@ -68,7 +68,7 @@ public class TestUtils { */ public static Statement assertSqlCanBeParsedAndDeparsed(String statement) throws JSQLParserException { - return assertSqlCanBeParsedAndDeparsed(statement, false); + return assertSqlCanBeParsedAndDeparsed(statement, true); } /** @@ -328,13 +328,19 @@ public static String buildSqlString(final String originalSql, boolean laxDeparsi sanitizedSqlStr = sanitizedSqlStr.trim().toLowerCase(); + if (laxDeparsingCheck && sanitizedSqlStr.endsWith(";")) { + sanitizedSqlStr = sanitizedSqlStr.substring(0, sanitizedSqlStr.length() - 1).trim(); + } + // Rewrite statement separators "/" and "GO" if (sanitizedSqlStr.endsWith("/")) { - sanitizedSqlStr = sanitizedSqlStr.substring(0, sanitizedSqlStr.length() - 1) + ";"; + sanitizedSqlStr = sanitizedSqlStr.substring(0, sanitizedSqlStr.length() - 1); } else if (sanitizedSqlStr.endsWith("go")) { - sanitizedSqlStr = sanitizedSqlStr.substring(0, sanitizedSqlStr.length() - 2) + ";"; + sanitizedSqlStr = sanitizedSqlStr.substring(0, sanitizedSqlStr.length() - 2); } + + return sanitizedSqlStr; } else { @@ -356,7 +362,7 @@ public static void assertExpressionCanBeDeparsedAs(final Expression parsed, Stri expressionDeParser.setBuffer(stringBuilder); SelectDeParser selectDeParser = new SelectDeParser(expressionDeParser, stringBuilder); expressionDeParser.setSelectVisitor(selectDeParser); - parsed.accept(expressionDeParser); + parsed.accept(expressionDeParser, null); assertEquals(expression, stringBuilder.toString()); } diff --git a/src/test/java/net/sf/jsqlparser/util/AddAliasesVisitorTest.java b/src/test/java/net/sf/jsqlparser/util/AddAliasesVisitorTest.java index e079a9427..6a8a919e5 100644 --- a/src/test/java/net/sf/jsqlparser/util/AddAliasesVisitorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/AddAliasesVisitorTest.java @@ -20,7 +20,7 @@ public class AddAliasesVisitorTest { - private CCJSqlParserManager parserManager = new CCJSqlParserManager(); + private final CCJSqlParserManager parserManager = new CCJSqlParserManager(); /** * Test of visit method, of class AddAliasesVisitor. @@ -29,8 +29,8 @@ public class AddAliasesVisitorTest { public void testVisit_PlainSelect() throws JSQLParserException { String sql = "select a,b,c from test"; Select select = (Select) parserManager.parse(new StringReader(sql)); - final AddAliasesVisitor instance = new AddAliasesVisitor(); - select.accept(instance); + final AddAliasesVisitor instance = new AddAliasesVisitor<>(); + select.accept(instance, null); assertEquals("SELECT a AS A1, b AS A2, c AS A3 FROM test", select.toString()); } @@ -39,8 +39,8 @@ public void testVisit_PlainSelect() throws JSQLParserException { public void testVisit_PlainSelect_duplicates() throws JSQLParserException { String sql = "select a,b as a1,c from test"; Select select = (Select) parserManager.parse(new StringReader(sql)); - final AddAliasesVisitor instance = new AddAliasesVisitor(); - select.accept(instance); + final AddAliasesVisitor instance = new AddAliasesVisitor<>(); + select.accept(instance, null); assertEquals("SELECT a AS A2, b AS a1, c AS A3 FROM test", select.toString()); } @@ -49,8 +49,8 @@ public void testVisit_PlainSelect_duplicates() throws JSQLParserException { public void testVisit_PlainSelect_expression() throws JSQLParserException { String sql = "select 3+4 from test"; Select select = (Select) parserManager.parse(new StringReader(sql)); - final AddAliasesVisitor instance = new AddAliasesVisitor(); - select.accept(instance); + final AddAliasesVisitor instance = new AddAliasesVisitor<>(); + select.accept(instance, null); assertEquals("SELECT 3 + 4 AS A1 FROM test", select.toString()); } @@ -62,8 +62,8 @@ public void testVisit_PlainSelect_expression() throws JSQLParserException { public void testVisit_SetOperationList() throws JSQLParserException { String sql = "select 3+4 from test union select 7+8 from test2"; Select setOpList = (Select) parserManager.parse(new StringReader(sql)); - final AddAliasesVisitor instance = new AddAliasesVisitor(); - setOpList.accept(instance); + final AddAliasesVisitor instance = new AddAliasesVisitor<>(); + setOpList.accept(instance, null); assertEquals("SELECT 3 + 4 AS A1 FROM test UNION SELECT 7 + 8 AS A1 FROM test2", setOpList.toString()); diff --git a/src/test/java/net/sf/jsqlparser/util/ConnectExpressionsVisitorTest.java b/src/test/java/net/sf/jsqlparser/util/ConnectExpressionsVisitorTest.java index 7f3902368..712e1950f 100644 --- a/src/test/java/net/sf/jsqlparser/util/ConnectExpressionsVisitorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/ConnectExpressionsVisitorTest.java @@ -23,19 +23,19 @@ public class ConnectExpressionsVisitorTest { - private CCJSqlParserManager parserManager = new CCJSqlParserManager(); + private final CCJSqlParserManager parserManager = new CCJSqlParserManager(); @Test public void testVisit_PlainSelect_concat() throws JSQLParserException { String sql = "select a,b,c from test"; Select select = (Select) parserManager.parse(new StringReader(sql)); - ConnectExpressionsVisitor instance = new ConnectExpressionsVisitor() { + ConnectExpressionsVisitor instance = new ConnectExpressionsVisitor<>() { @Override protected BinaryExpression createBinaryExpression() { return new Concat(); } }; - select.accept(instance); + select.accept(instance, null); assertEquals("SELECT a || b || c AS expr FROM test", select.toString()); } @@ -44,13 +44,13 @@ protected BinaryExpression createBinaryExpression() { public void testVisit_PlainSelect_addition() throws JSQLParserException { String sql = "select a,b,c from test"; Select select = (Select) parserManager.parse(new StringReader(sql)); - ConnectExpressionsVisitor instance = new ConnectExpressionsVisitor("testexpr") { + ConnectExpressionsVisitor instance = new ConnectExpressionsVisitor<>("testexpr") { @Override protected BinaryExpression createBinaryExpression() { return new Addition(); } }; - select.accept(instance); + select.accept(instance, null); assertEquals("SELECT a + b + c AS testexpr FROM test", select.toString()); } diff --git a/src/test/java/net/sf/jsqlparser/util/RandomUtils.java b/src/test/java/net/sf/jsqlparser/util/RandomUtils.java index 23beb02a7..dfd527999 100644 --- a/src/test/java/net/sf/jsqlparser/util/RandomUtils.java +++ b/src/test/java/net/sf/jsqlparser/util/RandomUtils.java @@ -69,7 +69,8 @@ public static void pushObjects(List obj) { /** * @param * @param type - * @return a random non-null value for given type or null if not supported. + * @return a random non-null value for given type or null if not + * supported. */ public static T getRandomValueForType(Class type) { Object value = null; @@ -125,14 +126,18 @@ public static T getRandomValueForType(Class type) { if (type.isEnum()) { @SuppressWarnings("unchecked") EnumSet enums = EnumSet.allOf(type.asSubclass(Enum.class)); - value = new ArrayList<>(enums).get(RandomUtils.RANDOM.nextInt(enums.size())); + value = new ArrayList<>(enums) + .get(RandomUtils.RANDOM.nextInt(enums.size())); } else { try { value = type.getConstructor().newInstance(); - } catch (InstantiationException | IllegalAccessException | IllegalArgumentException - | InvocationTargetException | NoSuchMethodException | SecurityException e) { + } catch (InstantiationException | IllegalAccessException + | IllegalArgumentException + | InvocationTargetException | NoSuchMethodException + | SecurityException e) { // cannot get default instance with empty constructor - LOG.log(Level.WARNING, "cannot get default instance with reflection for type " + type); + LOG.log(Level.WARNING, + "cannot get default instance with reflection for type " + type); } } } diff --git a/src/test/java/net/sf/jsqlparser/util/ReflectionTestUtils.java b/src/test/java/net/sf/jsqlparser/util/ReflectionTestUtils.java index df6bca701..8be1c9275 100644 --- a/src/test/java/net/sf/jsqlparser/util/ReflectionTestUtils.java +++ b/src/test/java/net/sf/jsqlparser/util/ReflectionTestUtils.java @@ -30,13 +30,15 @@ */ public class ReflectionTestUtils { - public static final Predicate GETTER_METHODS = m -> !void.class.isAssignableFrom(m.getReturnType()) - && m.getParameterCount() == 0 - && (m.getName().startsWith("get") || m.getName().startsWith("is")); + public static final Predicate GETTER_METHODS = + m -> !void.class.isAssignableFrom(m.getReturnType()) + && m.getParameterCount() == 0 + && (m.getName().startsWith("get") || m.getName().startsWith("is")); - public static final Predicate SETTER_METHODS = m -> void.class.isAssignableFrom(m.getReturnType()) - && m.getParameterCount() == 1 - && m.getName().startsWith("set"); + public static final Predicate SETTER_METHODS = + m -> void.class.isAssignableFrom(m.getReturnType()) + && m.getParameterCount() == 1 + && m.getName().startsWith("set"); public static final Predicate CHAINING_METHODS = m -> m.getDeclaringClass() .isAssignableFrom(m.getReturnType()) @@ -51,21 +53,27 @@ public class ReflectionTestUtils { * * * @param objs - * @param testMethodFilter - additional filter to skip some methods (by returning false). - * Default-Filters: null {@link #notDeclaredInObjectClass(Method)}, - * {@link #GETTER_METHODS}, {@link #SETTER_METHODS}, - * {@link #CHAINING_METHODS} + * @param testMethodFilter - additional filter to skip some methods (by returning + * false). Default-Filters: null {@link #notDeclaredInObjectClass(Method)}, + * {@link #GETTER_METHODS}, {@link #SETTER_METHODS}, {@link #CHAINING_METHODS} */ @SafeVarargs - public static void testGetterSetterChaining(List objs, Predicate... testMethodFilter) { + public static void testGetterSetterChaining(List objs, + Predicate... testMethodFilter) { RandomUtils.pushObjects(objs); objs.forEach(o -> { - testMethodInvocation(o, ReflectionTestUtils::anyReturnType, ReflectionTestUtils::reflectiveNonNullArgs, - ArrayUtils.insert(0, testMethodFilter, GETTER_METHODS, ReflectionTestUtils::notDeclaredInObjectClass)); - testMethodInvocation(o, ReflectionTestUtils::noReturnTypeValid, ReflectionTestUtils::reflectiveNonNullArgs, - ArrayUtils.insert(0, testMethodFilter, SETTER_METHODS, ReflectionTestUtils::notDeclaredInObjectClass)); - testMethodInvocation(o, ReflectionTestUtils::returnTypeThis, ReflectionTestUtils::reflectiveNonNullArgs, - ArrayUtils.insert(0, testMethodFilter, CHAINING_METHODS, ReflectionTestUtils::notDeclaredInObjectClass)); + testMethodInvocation(o, ReflectionTestUtils::anyReturnType, + ReflectionTestUtils::reflectiveNonNullArgs, + ArrayUtils.insert(0, testMethodFilter, GETTER_METHODS, + ReflectionTestUtils::notDeclaredInObjectClass)); + testMethodInvocation(o, ReflectionTestUtils::noReturnTypeValid, + ReflectionTestUtils::reflectiveNonNullArgs, + ArrayUtils.insert(0, testMethodFilter, SETTER_METHODS, + ReflectionTestUtils::notDeclaredInObjectClass)); + testMethodInvocation(o, ReflectionTestUtils::returnTypeThis, + ReflectionTestUtils::reflectiveNonNullArgs, + ArrayUtils.insert(0, testMethodFilter, CHAINING_METHODS, + ReflectionTestUtils::notDeclaredInObjectClass)); }); } @@ -117,7 +125,8 @@ private static boolean noReturnTypeValid(Object returnValue, Method m) { * @param methodFilters */ @SafeVarargs - public static void testMethodInvocation(Object object, BiPredicate returnTypeCheck, + public static void testMethodInvocation(Object object, + BiPredicate returnTypeCheck, Function argsFunction, Predicate... methodFilters) { log(Level.INFO, "testing methods of class " + object.getClass()); @@ -137,7 +146,8 @@ public static void testMethodInvocation(Object object, BiPredicate returnValue try { Object returnValue = method.invoke(object, argsFunction.apply(method)); if (!void.class.isAssignableFrom(method.getReturnType())) { - assertTrue(returnValueCheck.test(returnValue, method), "unexpected return-value with type " + returnValue.getClass() + " for method " - + method.toGenericString()); + assertTrue(returnValueCheck.test(returnValue, method), + "unexpected return-value with type " + returnValue.getClass() + + " for method " + + method.toGenericString()); } } catch (TestAbortedException tae) { - log(Level.INFO, "skip methods " + method.toGenericString() + ", detail: " + tae.getMessage()); + log(Level.INFO, + "skip methods " + method.toGenericString() + ", detail: " + tae.getMessage()); } } diff --git a/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java b/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java index ab63d1f9f..5a27f8aa1 100644 --- a/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java +++ b/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java @@ -11,7 +11,6 @@ import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.OracleHint; -import net.sf.jsqlparser.parser.CCJSqlParserManager; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; @@ -19,16 +18,9 @@ import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.comment.Comment; import net.sf.jsqlparser.statement.select.PlainSelect; -import net.sf.jsqlparser.statement.simpleparsing.CCJSqlParserManagerTest; -import net.sf.jsqlparser.test.TestException; import net.sf.jsqlparser.test.TestUtils; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.StringReader; -import java.util.List; import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; @@ -39,79 +31,6 @@ public class TablesNamesFinderTest { - private static final CCJSqlParserManager PARSER_MANAGER = new CCJSqlParserManager(); - - @Disabled - public void testRUBiSTableList() throws Exception { - runTestOnResource("/RUBiS-select-requests.txt"); - } - - @Disabled - public void testMoreComplexExamples() throws Exception { - runTestOnResource("complex-select-requests.txt"); - } - - @Disabled - public void testComplexMergeExamples() throws Exception { - runTestOnResource("complex-merge-requests.txt"); - } - - private void runTestOnResource(String resPath) throws Exception { - - try (BufferedReader in = new BufferedReader( - new InputStreamReader(TablesNamesFinderTest.class.getResourceAsStream(resPath)))) { - TablesNamesFinder tablesNamesFinder = new TablesNamesFinder(); - int numSt = 1; - while (true) { - String line = getLine(in); - if (line == null) { - break; - } - - if (line.isEmpty()) { - continue; - } - - if (!"#begin".equals(line)) { - break; - } - line = getLine(in); - StringBuilder buf = new StringBuilder(line); - while (true) { - line = getLine(in); - if ("#end".equals(line)) { - break; - } - buf.append("\n"); - buf.append(line); - } - - String query = buf.toString(); - if (!getLine(in).equals("true")) { - continue; - } - - String tables = getLine(in); - try { - Statement statement = PARSER_MANAGER.parse(new StringReader(query)); - - String[] tablesArray = tables.split("\\s+"); - - List tableListRetr = tablesNamesFinder.getTableList(statement); - assertEquals(tablesArray.length, tableListRetr.size(), "stm num:" + numSt); - - for (String element : tablesArray) { - assertTrue(tableListRetr.contains(element), "stm num:" + numSt); - } - } catch (Exception e) { - throw new TestException("error at stm num: " + numSt + " in file " + resPath, - e); - } - numSt++; - } - } - } - @Test public void testGetTables() throws Exception { String sqlStr = @@ -252,21 +171,18 @@ public void testExpr() throws JSQLParserException { .containsExactlyInAnyOrder("mytable"); } - private String getLine(BufferedReader in) throws Exception { - return CCJSqlParserManagerTest.getLine(in); - } - @Test public void testOracleHint() throws JSQLParserException { String sql = "select --+ HINT\ncol2 from mytable"; PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sql); final OracleHint[] holder = new OracleHint[1]; - TablesNamesFinder tablesNamesFinder = new TablesNamesFinder() { + TablesNamesFinder tablesNamesFinder = new TablesNamesFinder() { @Override - public void visit(OracleHint hint) { - super.visit(hint); + public Void visit(OracleHint hint, K parameters) { + super.visit(hint, parameters); holder[0] = hint; + return null; } }; @@ -278,7 +194,7 @@ public void visit(OracleHint hint) { public void testGetTablesIssue194() throws Exception { String sql = "SELECT 1"; Statement statement = TestUtils.assertSqlCanBeParsedAndDeparsed(sql, true); - TablesNamesFinder tablesNamesFinder = new TablesNamesFinder(); + TablesNamesFinder tablesNamesFinder = new TablesNamesFinder(); Set tableList = tablesNamesFinder.getTables(statement); assertEquals(0, tableList.size()); } @@ -531,5 +447,55 @@ void testFromParenthesesJoin() throws JSQLParserException { assertThat(tables).containsExactly("t1", "t2"); } + + @Test + void testOtherSources() throws JSQLParserException { + String sqlStr = "WITH Datetimes AS (\n" + + " SELECT DATETIME '2005-01-03 12:34:56' as datetime UNION ALL\n" + + " SELECT DATETIME '2007-12-31' UNION ALL\n" + + " SELECT DATETIME '2009-01-01' UNION ALL\n" + + " SELECT DATETIME '2009-12-31' UNION ALL\n" + + " SELECT DATETIME '2017-01-02' UNION ALL\n" + + " SELECT DATETIME '2017-05-26'\n" + + ")\n" + + "SELECT\n" + + " datetime,\n" + + " EXTRACT(ISOYEAR FROM datetime) AS isoyear,\n" + + " EXTRACT(WEEK FROM datetime) AS isoweek,\n" + + " EXTRACT(YEAR FROM datetime) AS year,\n" + + " /*APPROXIMATION: WEEK*/ EXTRACT(WEEK FROM datetime) AS week\n" + + "FROM Datetimes\n" + + "ORDER BY datetime\n" + + ";"; + Set tables = TablesNamesFinder.findTablesOrOtherSources(sqlStr); + assertThat(tables).containsExactly("Datetimes"); + } + + @Test + void testSubqueryAliasesIssue1987() throws JSQLParserException { + String sqlStr = "select * from (select * from a) as a1, b;"; + Set tables = TablesNamesFinder.findTablesOrOtherSources(sqlStr); + assertThat(tables).containsExactlyInAnyOrder("a", "b", "a1"); + + tables = TablesNamesFinder.findTables(sqlStr); + assertThat(tables).containsExactlyInAnyOrder("a", "b"); + assertThat(tables).doesNotContain("a1"); + + sqlStr = "select * from b, (select * from a) as a1"; + tables = TablesNamesFinder.findTablesOrOtherSources(sqlStr); + assertThat(tables).containsExactlyInAnyOrder("a1", "a", "b"); + + tables = TablesNamesFinder.findTables(sqlStr); + assertThat(tables).containsExactlyInAnyOrder("a", "b"); + assertThat(tables).doesNotContain("a1"); + + sqlStr = "SELECT * FROM b, (SELECT * FROM a) as a1 WHERE b.id IN ( SELECT id FROM a1 )"; + tables = TablesNamesFinder.findTablesOrOtherSources(sqlStr); + assertThat(tables).containsExactlyInAnyOrder("a1", "a", "b"); + + tables = TablesNamesFinder.findTables(sqlStr); + assertThat(tables).containsExactlyInAnyOrder("a", "b"); + assertThat(tables).doesNotContain("a1"); + } } diff --git a/src/test/java/net/sf/jsqlparser/util/cnfexpression/CNFTest.java b/src/test/java/net/sf/jsqlparser/util/cnfexpression/CNFTest.java index d7b1f288d..e4dd322c5 100644 --- a/src/test/java/net/sf/jsqlparser/util/cnfexpression/CNFTest.java +++ b/src/test/java/net/sf/jsqlparser/util/cnfexpression/CNFTest.java @@ -20,18 +20,19 @@ public class CNFTest { /** - * The purpose of this method is to check when there is a Not Operator at the root. Which means the root must be - * switched. + * The purpose of this method is to check when there is a Not Operator at the root. Which means + * the root must be switched. * * Here is the expression tree: * - * NOT | ( ) | AND / \ ( ) ( ) | | OR OR / \ / \ - * < = != >= / \ / \ / \ / \ 1.2 2.3 3.5 4.6 1.1 2.5 8.0 7.2 + * NOT | ( ) | AND / \ ( ) ( ) | | OR OR / \ / \ < = != >= / \ / \ / \ / \ 1.2 2.3 3.5 4.6 1.1 + * 2.5 8.0 7.2 * * Here is the converted expression tree: * - * AND / \ AND ( ) / \ | AND ( ) OR / \ | / \ ( ) ( ) OR NOT NOT | | / \ | | OR OR NOT NOT = >= / \ / \ | | / \ / \ - * NOT NOT NOT NOT = != 3.5 4.6 8.0 7.2 | | | | / \ / \ < != < >= / \ / \ / \ / \ 1.2 2.3 1.1 2.5 1.2 2.3 8.0 7.2 + * AND / \ AND ( ) / \ | AND ( ) OR / \ | / \ ( ) ( ) OR NOT NOT | | / \ | | OR OR NOT NOT = >= + * / \ / \ | | / \ / \ NOT NOT NOT NOT = != 3.5 4.6 8.0 7.2 | | | | / \ / \ < != < >= / \ / \ / + * \ / \ 1.2 2.3 1.1 2.5 1.2 2.3 8.0 7.2 * */ @Test @@ -40,249 +41,134 @@ public void test1() throws Exception { "NOT ((1.2 < 2.3 OR 3.5 = 4.6) AND (1.1 <> 2.5 OR 8.0 >= 7.2))"); Expression expected = CCJSqlParserUtil.parseCondExpression( "(NOT 1.2 < 2.3 OR NOT 1.1 <> 2.5) AND (NOT 1.2 < 2.3 OR NOT 8.0 >= 7.2) AND" - + " (NOT 3.5 = 4.6 OR NOT 1.1 <> 2.5) AND (NOT 3.5 = 4.6 OR NOT 8.0 >= 7.2)"); + + " (NOT 3.5 = 4.6 OR NOT 1.1 <> 2.5) AND (NOT 3.5 = 4.6 OR NOT 8.0 >= 7.2)"); Expression result = CNFConverter.convertToCNF(expr); assertEquals(expected.toString(), result.toString()); } /** - * The purpose is to test the double negation law. As you can see when you build the tree, there will be two Not - * Operators together on the line. It is there when we use the double negation law. + * The purpose is to test the double negation law. As you can see when you build the tree, there + * will be two Not Operators together on the line. It is there when we use the double negation + * law. * - * Here is the expression tree: ( ) | OR / \ ( ) ( ) | | NOT AND | / \ ( ) LIKE = | / \ / \ OR S.A "%%%" S.B "orz" / - * \ NOT < - * | / \ - * >= 3.3 4.5 / \ 1.1 2.3 + * Here is the expression tree: ( ) | OR / \ ( ) ( ) | | NOT AND | / \ ( ) LIKE = | / \ / \ OR + * S.A "%%%" S.B "orz" / \ NOT < | / \ >= 3.3 4.5 / \ 1.1 2.3 * * Here is the converted expression tree: * - * AND / \ AND ( ) / \ | AND ( ) OR / \ | / \ ( ) ( ) OR NOT = | | / \ | / \ OR OR NOT LIKE < S.B "orz" - * / \ / \ | / \ / \ - * >= LIKE >= = < S.A "%%%" 3.3 4.5 / \ / \ / \ / \ 1.1 2.3 S.A "%%%" 1.1 2.3 S.B "orz" + * AND / \ AND ( ) / \ | AND ( ) OR / \ | / \ ( ) ( ) OR NOT = | | / \ | / \ OR OR NOT LIKE < + * S.B "orz" / \ / \ | / \ / \ >= LIKE >= = < S.A "%%%" 3.3 4.5 / \ / \ / \ / \ 1.1 2.3 S.A + * "%%%" 1.1 2.3 S.B "orz" * */ @Test public void test2() throws Exception { Expression expr = CCJSqlParserUtil.parseCondExpression( "((NOT (NOT 1.1 >= 2.3 OR 3.3 < 4.5)) OR " - + "(S.A LIKE '\"%%%\"' AND S.B = '\"orz\"'))"); + + "(S.A LIKE '\"%%%\"' AND S.B = '\"orz\"'))"); Expression expected = CCJSqlParserUtil.parseCondExpression( "(1.1 >= 2.3 OR S.A LIKE '\"%%%\"') AND (1.1 >= 2.3 OR S.B = '\"orz\"')" - + " AND (NOT 3.3 < 4.5 OR S.A LIKE '\"%%%\"') AND (NOT 3.3 < 4.5 OR S.B = '\"orz\"')"); + + " AND (NOT 3.3 < 4.5 OR S.A LIKE '\"%%%\"') AND (NOT 3.3 < 4.5 OR S.B = '\"orz\"')"); Expression result = CNFConverter.convertToCNF(expr); assertEquals(expected.toString(), result.toString()); } /** - * This is the case when we test a more complex tree structure, Notice you could see the amount of line to build up - * the CNF tree. You could tell how complicated the CNF could be. + * This is the case when we test a more complex tree structure, Notice you could see the amount + * of line to build up the CNF tree. You could tell how complicated the CNF could be. * - * OR / \ ( ) ( ) | | AND OR / \ / \ >= <= ( ) NOT / \ / \ | | 7.0 8.0 9.0 10.0 AND OR / \ / \ ( ) = != ( ) | / \ / - * \ | AND 11.0 12.0 13.0 14.0 AND / \ / \ < > = ( ) - * / \ / \ / \ | - * 7.0 8.0 9.0 10.0 15.0 16.0 OR / \ = > / \ / \ 17.0 18.0 19.0 20.0 + * OR / \ ( ) ( ) | | AND OR / \ / \ >= <= ( ) NOT / \ / \ | | 7.0 8.0 9.0 10.0 AND OR / \ / \ ( + * ) = != ( ) | / \ / \ | AND 11.0 12.0 13.0 14.0 AND / \ / \ < > = ( ) / \ / \ / \ | 7.0 8.0 + * 9.0 10.0 15.0 16.0 OR / \ = > / \ / \ 17.0 18.0 19.0 20.0 * * Here is the converted expression tree: * - * AND / \ AND ( ) / \ | AND ( ) part18 / \ | AND ( ) part17 / \ | AND ( ) part16 / \ | AND ( ) part15 / \ | AND ( ) - * part14 / \ | AND ( ) part13 / \ | AND ( ) part12 / \ | AND ( ) part11 / \ | AND ( ) part10 / \ | AND ( ) part9 / - * \ | AND ( ) part8 / \ | AND ( ) part7 / \ | AND ( ) part6 / \ | AND ( ) part5 / \ | AND ( ) part4 / \ | ( ) ( ) - * part3 | | part1 part2 - * - * part1: OR / \ OR NOT / \ | >= < != - * / \ / \ / \ - * 3.0 4.0 7.0 8.0 13.0 14.0 - * - * part2: OR - * / \ - * OR NOT - * / \ | - * OR NOT = - * / \ | / \ - * >= < = 17.0 18.0 - * / \ / \ / \ - * 3.0 4.0 7.0 8.0 15.0 16.0 - * - * part3: OR - * / \ - * OR NOT - * / \ | - * OR NOT = - * / \ | / \ - * >= < = 19.0 20.0 - * / \ / \ / \ - * 3.0 4.0 7.0 8.0 15.0 16.0 - * - * part4: OR - * / \ - * OR NOT - * / \ | - * >= < != - * / \ / \ / \ - * 3.0 4.0 9.0 10.0 13.0 14.0 - * - * part5: OR - * / \ - * OR NOT - * / \ | - * OR NOT = - * / \ | / \ - * >= < = 17.0 18.0 - * / \ / \ / \ - * 3.0 4.0 9.0 10.0 15.0 16.0 - * - * part6: OR - * / \ - * OR NOT - * / \ | - * OR NOT = - * / \ | / \ - * >= < = 19.0 20.0 - * / \ / \ / \ - * 3.0 4.0 9.0 10.0 15.0 16.0 - * - * part7: OR - * / \ - * OR NOT - * / \ | - * >= < != - * / \ / \ / \ - * 3.0 4.0 11.0 12.0 13.0 14.0 - * - * part8: OR - * / \ - * OR NOT - * / \ | - * OR NOT = - * / \ | / \ - * >= < = 17.0 18.0 - * / \ / \ / \ - * 3.0 4.0 11.0 12.0 15.0 16.0 - * - * part9: OR - * / \ - * OR NOT - * / \ | - * OR NOT = - * / \ | / \ - * >= < = 19.0 20.0 - * / \ / \ / \ - * 3.0 4.0 11.0 12.0 15.0 16.0 - * - * part10: OR - * / \ - * OR NOT - * / \ | - * >= < != - * / \ / \ / \ - * 5.0 6.0 7.0 8.0 13.0 14.0 - * - * part11: OR - * / \ - * OR NOT - * / \ | - * OR NOT = - * / \ | / \ - * >= < = 17.0 18.0 - * / \ / \ / \ - * 5.0 6.0 7.0 8.0 15.0 16.0 - * - * part12: OR - * / \ - * OR NOT - * / \ | - * OR NOT = - * / \ | / \ - * >= < = 19.0 20.0 - * / \ / \ / \ - * 5.0 6.0 7.0 8.0 15.0 16.0 - * - * part13: OR - * / \ - * OR NOT - * / \ | - * >= < != - * / \ / \ / \ - * 5.0 6.0 9.0 10.0 13.0 14.0 - * - * part14: OR - * / \ - * OR NOT - * / \ | - * OR NOT = - * / \ | / \ - * >= < = 17.0 18.0 - * / \ / \ / \ - * 5.0 6.0 9.0 10.0 15.0 16.0 - * - * part15: OR - * / \ - * OR NOT - * / \ | - * OR NOT = - * / \ | / \ - * >= < = 19.0 20.0 - * / \ / \ / \ - * 5.0 6.0 9.0 10.0 15.0 16.0 - * - * part16: OR - * / \ - * OR NOT - * / \ | - * >= < != - * / \ / \ / \ - * 5.0 6.0 11.0 12.0 13.0 14.0 - * - * part17: OR - * / \ - * OR NOT - * / \ | - * OR NOT = - * / \ | / \ - * >= < = 17.0 18.0 - * / \ / \ / \ - * 5.0 6.0 11.0 12.0 15.0 16.0 - * - * part18: OR - * / \ - * OR NOT - * / \ | - * OR NOT = - * / \ | / \ - * >= < = 19.0 20.0 / \ / \ / \ 5.0 6.0 11.0 12.0 15.0 16.0 + * AND / \ AND ( ) / \ | AND ( ) part18 / \ | AND ( ) part17 / \ | AND ( ) part16 / \ | AND ( ) + * part15 / \ | AND ( ) part14 / \ | AND ( ) part13 / \ | AND ( ) part12 / \ | AND ( ) part11 / + * \ | AND ( ) part10 / \ | AND ( ) part9 / \ | AND ( ) part8 / \ | AND ( ) part7 / \ | AND ( ) + * part6 / \ | AND ( ) part5 / \ | AND ( ) part4 / \ | ( ) ( ) part3 | | part1 part2 + * + * part1: OR / \ OR NOT / \ | >= < != / \ / \ / \ 3.0 4.0 7.0 8.0 13.0 14.0 + * + * part2: OR / \ OR NOT / \ | OR NOT = / \ | / \ >= < = 17.0 18.0 / \ / \ / \ 3.0 4.0 7.0 8.0 + * 15.0 16.0 + * + * part3: OR / \ OR NOT / \ | OR NOT = / \ | / \ >= < = 19.0 20.0 / \ / \ / \ 3.0 4.0 7.0 8.0 + * 15.0 16.0 + * + * part4: OR / \ OR NOT / \ | >= < != / \ / \ / \ 3.0 4.0 9.0 10.0 13.0 14.0 + * + * part5: OR / \ OR NOT / \ | OR NOT = / \ | / \ >= < = 17.0 18.0 / \ / \ / \ 3.0 4.0 9.0 10.0 + * 15.0 16.0 + * + * part6: OR / \ OR NOT / \ | OR NOT = / \ | / \ >= < = 19.0 20.0 / \ / \ / \ 3.0 4.0 9.0 10.0 + * 15.0 16.0 + * + * part7: OR / \ OR NOT / \ | >= < != / \ / \ / \ 3.0 4.0 11.0 12.0 13.0 14.0 + * + * part8: OR / \ OR NOT / \ | OR NOT = / \ | / \ >= < = 17.0 18.0 / \ / \ / \ 3.0 4.0 11.0 12.0 + * 15.0 16.0 + * + * part9: OR / \ OR NOT / \ | OR NOT = / \ | / \ >= < = 19.0 20.0 / \ / \ / \ 3.0 4.0 11.0 12.0 + * 15.0 16.0 + * + * part10: OR / \ OR NOT / \ | >= < != / \ / \ / \ 5.0 6.0 7.0 8.0 13.0 14.0 + * + * part11: OR / \ OR NOT / \ | OR NOT = / \ | / \ >= < = 17.0 18.0 / \ / \ / \ 5.0 6.0 7.0 8.0 + * 15.0 16.0 + * + * part12: OR / \ OR NOT / \ | OR NOT = / \ | / \ >= < = 19.0 20.0 / \ / \ / \ 5.0 6.0 7.0 8.0 + * 15.0 16.0 + * + * part13: OR / \ OR NOT / \ | >= < != / \ / \ / \ 5.0 6.0 9.0 10.0 13.0 14.0 + * + * part14: OR / \ OR NOT / \ | OR NOT = / \ | / \ >= < = 17.0 18.0 / \ / \ / \ 5.0 6.0 9.0 10.0 + * 15.0 16.0 + * + * part15: OR / \ OR NOT / \ | OR NOT = / \ | / \ >= < = 19.0 20.0 / \ / \ / \ 5.0 6.0 9.0 10.0 + * 15.0 16.0 + * + * part16: OR / \ OR NOT / \ | >= < != / \ / \ / \ 5.0 6.0 11.0 12.0 13.0 14.0 + * + * part17: OR / \ OR NOT / \ | OR NOT = / \ | / \ >= < = 17.0 18.0 / \ / \ / \ 5.0 6.0 11.0 12.0 + * 15.0 16.0 + * + * part18: OR / \ OR NOT / \ | OR NOT = / \ | / \ >= < = 19.0 20.0 / \ / \ / \ 5.0 6.0 11.0 12.0 + * 15.0 16.0 * */ @Test public void test3() throws Exception { Expression expr = CCJSqlParserUtil.parseCondExpression( "(3.0 >= 4.0 AND 5.0 <= 6.0) OR " - + "(((7.0 < 8.0 AND 9.0 > 10.0) AND 11.0 = 12.0) OR " - + "NOT (13.0 <> 14.0 OR (15.0 = 16.0 AND (17.0 = 18.0 OR 19.0 > 20.0))))"); + + "(((7.0 < 8.0 AND 9.0 > 10.0) AND 11.0 = 12.0) OR " + + "NOT (13.0 <> 14.0 OR (15.0 = 16.0 AND (17.0 = 18.0 OR 19.0 > 20.0))))"); Expression expected = CCJSqlParserUtil.parseCondExpression( "(3.0 >= 4.0 OR 7.0 < 8.0 OR NOT 13.0 <> 14.0) AND " - + "(3.0 >= 4.0 OR 7.0 < 8.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND " - + "(3.0 >= 4.0 OR 7.0 < 8.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND " - + "(3.0 >= 4.0 OR 9.0 > 10.0 OR NOT 13.0 <> 14.0) AND " - + "(3.0 >= 4.0 OR 9.0 > 10.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND " - + "(3.0 >= 4.0 OR 9.0 > 10.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND " - + "(3.0 >= 4.0 OR 11.0 = 12.0 OR NOT 13.0 <> 14.0) AND " - + "(3.0 >= 4.0 OR 11.0 = 12.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND " - + "(3.0 >= 4.0 OR 11.0 = 12.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND " - + "(5.0 <= 6.0 OR 7.0 < 8.0 OR NOT 13.0 <> 14.0) AND " - + "(5.0 <= 6.0 OR 7.0 < 8.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND " - + "(5.0 <= 6.0 OR 7.0 < 8.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND " - + "(5.0 <= 6.0 OR 9.0 > 10.0 OR NOT 13.0 <> 14.0) AND " - + "(5.0 <= 6.0 OR 9.0 > 10.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND " - + "(5.0 <= 6.0 OR 9.0 > 10.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND " - + "(5.0 <= 6.0 OR 11.0 = 12.0 OR NOT 13.0 <> 14.0) AND " - + "(5.0 <= 6.0 OR 11.0 = 12.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND " - + "(5.0 <= 6.0 OR 11.0 = 12.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0)"); + + "(3.0 >= 4.0 OR 7.0 < 8.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND " + + "(3.0 >= 4.0 OR 7.0 < 8.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND " + + "(3.0 >= 4.0 OR 9.0 > 10.0 OR NOT 13.0 <> 14.0) AND " + + "(3.0 >= 4.0 OR 9.0 > 10.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND " + + "(3.0 >= 4.0 OR 9.0 > 10.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND " + + "(3.0 >= 4.0 OR 11.0 = 12.0 OR NOT 13.0 <> 14.0) AND " + + "(3.0 >= 4.0 OR 11.0 = 12.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND " + + "(3.0 >= 4.0 OR 11.0 = 12.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND " + + "(5.0 <= 6.0 OR 7.0 < 8.0 OR NOT 13.0 <> 14.0) AND " + + "(5.0 <= 6.0 OR 7.0 < 8.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND " + + "(5.0 <= 6.0 OR 7.0 < 8.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND " + + "(5.0 <= 6.0 OR 9.0 > 10.0 OR NOT 13.0 <> 14.0) AND " + + "(5.0 <= 6.0 OR 9.0 > 10.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND " + + "(5.0 <= 6.0 OR 9.0 > 10.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND " + + "(5.0 <= 6.0 OR 11.0 = 12.0 OR NOT 13.0 <> 14.0) AND " + + "(5.0 <= 6.0 OR 11.0 = 12.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND " + + "(5.0 <= 6.0 OR 11.0 = 12.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0)"); Expression result = CNFConverter.convertToCNF(expr); assertEquals(expected.toString(), result.toString()); } /** - * This is the case when we test a very simple tree structure that has neither AND operator or OR operator. + * This is the case when we test a very simple tree structure that has neither AND operator or + * OR operator. * * Here is the expression tree: * @@ -302,31 +188,26 @@ public void test4() throws Exception { } /** - * This is the case when we test the tree that only contains AND operator without having an OR operator. + * This is the case when we test the tree that only contains AND operator without having an OR + * operator. * - * Here is the original expression tree: NOT | ( ) | OR / \ ( ) ( ) | | NOT OR | / \ AND LIKE = / \ / \ / \ > < S.C "%%" S.D {t '12:04:34'} - * / \ / \ - * S.A 3.5 S.B 4 + * Here is the original expression tree: NOT | ( ) | OR / \ ( ) ( ) | | NOT OR | / \ AND LIKE = + * / \ / \ / \ > < S.C "%%" S.D {t '12:04:34'} / \ / \ S.A 3.5 S.B 4 * * Here is the converted expression tree: * - * AND - * / \ - * AND = - * / \ / \ - * AND NOT LIKE S.D {t '12:04:34'} - * / \ / \ - * > < S.C "%%" / \ / \ S.A 3.5 S.B 4 + * AND / \ AND = / \ / \ AND NOT LIKE S.D {t '12:04:34'} / \ / \ > < S.C "%%" / \ / \ S.A 3.5 + * S.B 4 * */ @Test public void test5() throws Exception { Expression expr = CCJSqlParserUtil.parseCondExpression( "NOT ((NOT (S.A > 3.5 AND S.B < 4)) OR " - + "(S.C LIKE '\"%%\"' OR S.D = {t '12:04:34'}))"); + + "(S.C LIKE '\"%%\"' OR S.D = {t '12:04:34'}))"); Expression expected = CCJSqlParserUtil.parseCondExpression( "S.A > 3.5 AND S.B < 4 AND NOT S.C LIKE '\"%%\"' " - + "AND NOT S.D = {t '12:04:34'}"); + + "AND NOT S.D = {t '12:04:34'}"); Expression result = CNFConverter.convertToCNF(expr); assertEquals(expected.toString(), result.toString()); } @@ -335,65 +216,63 @@ public void test5() throws Exception { public void testStackOverflowIssue1576() throws JSQLParserException { Expression expr = CCJSqlParserUtil.parseCondExpression( "((3.0 >= 4.0 AND 5.0 <= 6.0) OR " - + "(7.0 < 8.0 AND 9.0 > 10.0) OR " - + "(11.0 = 11.0 AND 19.0 > 20.0) OR " - + "(17.0 = 14.0 AND 19.0 > 17.0) OR " - + "(17.0 = 18.0 AND 20.0 > 20.0) OR " - + "(17.0 = 16.0 AND 19.0 > 20.0) OR " - + "(17.0 = 18.0 AND 19.0 > 20.0) OR " - + "(17.0 = 18.0 AND 19.0 > 20.0) OR " - + "(17.0 = 22.0 AND 19.0 > 20.0) OR " - + "(18.0 = 18.0 AND 22.0 > 20.0) OR " - + "(17.0 = 18.0 AND 19.0 > 20.0) OR " - + "(18.0 = 18.0 AND 22.0 > 20.0) OR " - + "(18.0 = 19.0 AND 22.0 > 20.0) OR " - + "(17.0 = 18.0 AND 19.0 > 20.0))" - ); + + "(7.0 < 8.0 AND 9.0 > 10.0) OR " + + "(11.0 = 11.0 AND 19.0 > 20.0) OR " + + "(17.0 = 14.0 AND 19.0 > 17.0) OR " + + "(17.0 = 18.0 AND 20.0 > 20.0) OR " + + "(17.0 = 16.0 AND 19.0 > 20.0) OR " + + "(17.0 = 18.0 AND 19.0 > 20.0) OR " + + "(17.0 = 18.0 AND 19.0 > 20.0) OR " + + "(17.0 = 22.0 AND 19.0 > 20.0) OR " + + "(18.0 = 18.0 AND 22.0 > 20.0) OR " + + "(17.0 = 18.0 AND 19.0 > 20.0) OR " + + "(18.0 = 18.0 AND 22.0 > 20.0) OR " + + "(18.0 = 19.0 AND 22.0 > 20.0) OR " + + "(17.0 = 18.0 AND 19.0 > 20.0))"); Expression result = CNFConverter.convertToCNF(expr); assertThat(result).asString().hasSize(3448827); } - - + + @Test @Disabled public void testStackOverflowIssue1576_veryLarge() throws JSQLParserException { Expression expr = CCJSqlParserUtil.parseCondExpression( "((3.0 >= 4.0 AND 5.0 <= 6.0) OR " - + "(7.0 < 8.0 AND 9.0 > 10.0) OR " - + "(11.0 = 11.0 AND 19.0 > 20.0) OR " - + "(17.0 = 14.0 AND 19.0 > 17.0) OR " - + "(17.0 = 18.0 AND 20.0 > 20.0) OR " - + "(17.0 = 16.0 AND 19.0 > 20.0) OR " - + "(17.0 = 18.0 AND 19.0 > 20.0) OR " - + "(17.0 = 18.0 AND 19.0 > 20.0) OR " - + "(17.0 = 22.0 AND 19.0 > 20.0) OR " - + "(18.0 = 18.0 AND 22.0 > 20.0) OR " - + "(17.0 = 18.0 AND 19.0 > 20.0) OR " - + "(18.0 = 18.0 AND 22.0 > 20.0) OR " - + "(18.0 = 19.0 AND 22.0 > 20.0) OR " - + "(117.0 = 22.0 AND 19.0 > 20.0) OR " - + "(118.0 = 18.0 AND 22.0 > 20.0) OR " - + "(117.0 = 18.0 AND 19.0 > 20.0) OR " - //+ "(118.0 = 18.0 AND 22.0 > 20.0) OR " - //+ "(118.0 = 19.0 AND 22.0 > 20.0) OR " - + "(17.0 = 18.0 AND 19.0 > 20.0))" - ); + + "(7.0 < 8.0 AND 9.0 > 10.0) OR " + + "(11.0 = 11.0 AND 19.0 > 20.0) OR " + + "(17.0 = 14.0 AND 19.0 > 17.0) OR " + + "(17.0 = 18.0 AND 20.0 > 20.0) OR " + + "(17.0 = 16.0 AND 19.0 > 20.0) OR " + + "(17.0 = 18.0 AND 19.0 > 20.0) OR " + + "(17.0 = 18.0 AND 19.0 > 20.0) OR " + + "(17.0 = 22.0 AND 19.0 > 20.0) OR " + + "(18.0 = 18.0 AND 22.0 > 20.0) OR " + + "(17.0 = 18.0 AND 19.0 > 20.0) OR " + + "(18.0 = 18.0 AND 22.0 > 20.0) OR " + + "(18.0 = 19.0 AND 22.0 > 20.0) OR " + + "(117.0 = 22.0 AND 19.0 > 20.0) OR " + + "(118.0 = 18.0 AND 22.0 > 20.0) OR " + + "(117.0 = 18.0 AND 19.0 > 20.0) OR " + // + "(118.0 = 18.0 AND 22.0 > 20.0) OR " + // + "(118.0 = 19.0 AND 22.0 > 20.0) OR " + + "(17.0 = 18.0 AND 19.0 > 20.0))"); Expression result = CNFConverter.convertToCNF(expr); assertThat(result).asString().hasSize(33685499); } - + @Test public void testStackOverflowIssue1576_2() throws JSQLParserException { Expression expr = CCJSqlParserUtil.parseCondExpression( "((3.0 >= 4.0 AND 5.0 <= 6.0) OR " - + "(7.0 < 8.0 AND 9.0 > 10.0) OR " - + "(11.0 = 11.0 AND 19.0 > 20.0) OR " - + "(17.0 = 14.0 AND 19.0 > 17.0) OR " - + "(17.0 = 18.0 AND 20.0 > 20.0) OR " - + "(17.0 = 16.0 AND 19.0 > 20.0))" - ); + + "(7.0 < 8.0 AND 9.0 > 10.0) OR " + + "(11.0 = 11.0 AND 19.0 > 20.0) OR " + + "(17.0 = 14.0 AND 19.0 > 17.0) OR " + + "(17.0 = 18.0 AND 20.0 > 20.0) OR " + + "(17.0 = 16.0 AND 19.0 > 20.0))"); Expression result = CNFConverter.convertToCNF(expr); - assertThat(result).asString().isEqualTo("(3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0)"); + assertThat(result).asString().isEqualTo( + "(3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0)"); } } diff --git a/src/test/java/net/sf/jsqlparser/util/cnfexpression/CloneHelperTest.java b/src/test/java/net/sf/jsqlparser/util/cnfexpression/CloneHelperTest.java index ee320d51a..36b6068b8 100644 --- a/src/test/java/net/sf/jsqlparser/util/cnfexpression/CloneHelperTest.java +++ b/src/test/java/net/sf/jsqlparser/util/cnfexpression/CloneHelperTest.java @@ -9,17 +9,19 @@ */ package net.sf.jsqlparser.util.cnfexpression; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import org.junit.jupiter.api.Test; + import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; + import static java.util.stream.Collectors.toList; -import net.sf.jsqlparser.JSQLParserException; -import net.sf.jsqlparser.expression.Expression; -import net.sf.jsqlparser.expression.Parenthesis; -import net.sf.jsqlparser.parser.CCJSqlParserUtil; import static org.assertj.core.api.Assertions.assertThat; -import org.junit.jupiter.api.Test; /** * @@ -29,20 +31,20 @@ public class CloneHelperTest { @Test public void testChangeBack() { - MultipleExpression ors = transform( Arrays.asList("a>b", "5=a", "b=c", "a>c")); + MultipleExpression ors = transform(Arrays.asList("a>b", "5=a", "b=c", "a>c")); Expression expr = CloneHelper.changeBack(true, ors); - assertThat(expr).isInstanceOf(Parenthesis.class); + assertThat(expr).isInstanceOf(ParenthesedExpressionList.class); assertThat(expr.toString()).isEqualTo("(a > b OR 5 = a OR b = c OR a > c)"); } - + @Test public void testChangeBackOddNumberOfExpressions() { - MultipleExpression ors = transform( Arrays.asList("a>b", "5=a", "b=c", "a>c", "eb", "5=a", "b=c", "a>c", "e b OR 5 = a OR b = c OR a > c OR e < f)"); } - + private static MultipleExpression transform(List expressions) { return new MultiOrExpression( expressions.stream() @@ -50,7 +52,8 @@ private static MultipleExpression transform(List expressions) { try { return CCJSqlParserUtil.parseCondExpression(expr); } catch (JSQLParserException ex) { - Logger.getLogger(CloneHelperTest.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(CloneHelperTest.class.getName()).log(Level.SEVERE, + null, ex); return null; } }) diff --git a/src/test/java/net/sf/jsqlparser/util/deparser/CreateViewDeParserTest.java b/src/test/java/net/sf/jsqlparser/util/deparser/CreateViewDeParserTest.java index 0979a4884..6149ef32b 100644 --- a/src/test/java/net/sf/jsqlparser/util/deparser/CreateViewDeParserTest.java +++ b/src/test/java/net/sf/jsqlparser/util/deparser/CreateViewDeParserTest.java @@ -37,7 +37,7 @@ public void testUseExtrnalExpressionDeparser() throws JSQLParserException { ExpressionDeParser expressionDeParser = new ExpressionDeParser(selectDeParser, b) { @Override - public void visit(Column tableColumn) { + public StringBuilder visit(Column tableColumn, K parameters) { final Table table = tableColumn.getTable(); String tableName = null; if (table != null) { @@ -52,19 +52,20 @@ public void visit(Column tableColumn) { } getBuffer().append("\"").append(tableColumn.getColumnName()).append("\""); + return buffer; } }; selectDeParser.setExpressionVisitor(expressionDeParser); CreateViewDeParser instance = new CreateViewDeParser(b, selectDeParser); - CreateView vc = (CreateView) CCJSqlParserUtil. - parse("CREATE VIEW test AS SELECT a, b FROM mytable"); + CreateView vc = + (CreateView) CCJSqlParserUtil.parse("CREATE VIEW test AS SELECT a, b FROM mytable"); instance.deParse(vc); assertEquals("CREATE VIEW test AS SELECT a, b FROM mytable", vc.toString()); - assertEquals("CREATE VIEW test AS SELECT \"a\", \"b\" FROM mytable", instance.getBuffer(). - toString()); + assertEquals("CREATE VIEW test AS SELECT \"a\", \"b\" FROM mytable", + instance.getBuffer().toString()); } @Test diff --git a/src/test/java/net/sf/jsqlparser/util/deparser/ExecuteDeParserTest.java b/src/test/java/net/sf/jsqlparser/util/deparser/ExecuteDeParserTest.java index 83ef5b102..ce3b90aa6 100644 --- a/src/test/java/net/sf/jsqlparser/util/deparser/ExecuteDeParserTest.java +++ b/src/test/java/net/sf/jsqlparser/util/deparser/ExecuteDeParserTest.java @@ -45,7 +45,7 @@ public void shouldDeParseExecute() { Execute execute = new Execute(); String name = "name"; - ParenthesedExpressionList expressions = new ParenthesedExpressionList(); + ParenthesedExpressionList expressions = new ParenthesedExpressionList<>(); expressions.add(new JdbcParameter()); expressions.add(new JdbcParameter()); @@ -71,12 +71,12 @@ public void shouldUseProvidedExpressionVisitorWhenDeParsingExecute() { expressions.add(expression1); expressions.add(expression2); - ExpressionList exprList = new ExpressionList().addExpressions(expressions); + ExpressionList exprList = new ExpressionList<>().addExpressions(expressions); execute.withName(name).withExprList(exprList); executeDeParser.deParse(execute); - then(expression1).should().accept(expressionVisitor); - then(expression2).should().accept(expressionVisitor); + then(expression1).should().accept(expressionVisitor, null); + then(expression2).should().accept(expressionVisitor, null); } } diff --git a/src/test/java/net/sf/jsqlparser/util/deparser/ExpressionDeParserTest.java b/src/test/java/net/sf/jsqlparser/util/deparser/ExpressionDeParserTest.java index 15c74e520..09ba90dc6 100644 --- a/src/test/java/net/sf/jsqlparser/util/deparser/ExpressionDeParserTest.java +++ b/src/test/java/net/sf/jsqlparser/util/deparser/ExpressionDeParserTest.java @@ -38,7 +38,7 @@ public class ExpressionDeParserTest { private ExpressionDeParser expressionDeParser; @Mock - private SelectVisitor selectVisitor; + private SelectVisitor selectVisitor; private StringBuilder buffer; @@ -55,7 +55,7 @@ public void setUp() { public void shouldDeParseSimplestAnalyticExpression() { AnalyticExpression analyticExpression = new AnalyticExpression(); analyticExpression.setName("name"); - expressionDeParser.visit(analyticExpression); + expressionDeParser.visit(analyticExpression, null); assertEquals("name() OVER ()", buffer.toString()); } @@ -67,9 +67,9 @@ public void shouldDeParseAnalyticExpressionWithExpression() { analyticExpression.setName("name"); analyticExpression.setExpression(expression); - will(appendToBuffer("expression")).given(expression).accept(expressionDeParser); + will(appendToBuffer("expression")).given(expression).accept(expressionDeParser, null); - expressionDeParser.visit(analyticExpression); + expressionDeParser.visit(analyticExpression, null); assertEquals("name(expression) OVER ()", buffer.toString()); } @@ -84,10 +84,10 @@ public void shouldDeParseAnalyticExpressionWithOffset() { analyticExpression.setExpression(expression); analyticExpression.setOffset(offset); - will(appendToBuffer("expression")).given(expression).accept(expressionDeParser); - will(appendToBuffer("offset")).given(offset).accept(expressionDeParser); + will(appendToBuffer("expression")).given(expression).accept(expressionDeParser, null); + will(appendToBuffer("offset")).given(offset).accept(expressionDeParser, null); - expressionDeParser.visit(analyticExpression); + expressionDeParser.visit(analyticExpression, null); assertEquals("name(expression, offset) OVER ()", buffer.toString()); } @@ -104,11 +104,11 @@ public void shouldDeParseAnalyticExpressionWithDefaultValue() { analyticExpression.setOffset(offset); analyticExpression.setDefaultValue(defaultValue); - will(appendToBuffer("expression")).given(expression).accept(expressionDeParser); - will(appendToBuffer("offset")).given(offset).accept(expressionDeParser); - will(appendToBuffer("default value")).given(defaultValue).accept(expressionDeParser); + will(appendToBuffer("expression")).given(expression).accept(expressionDeParser, null); + will(appendToBuffer("offset")).given(offset).accept(expressionDeParser, null); + will(appendToBuffer("default value")).given(defaultValue).accept(expressionDeParser, null); - expressionDeParser.visit(analyticExpression); + expressionDeParser.visit(analyticExpression, null); assertEquals("name(expression, offset, default value) OVER ()", buffer.toString()); } @@ -120,7 +120,7 @@ public void shouldDeParseAnalyticExpressionWithAllColumns() { analyticExpression.setName("name"); analyticExpression.setAllColumns(true); - expressionDeParser.visit(analyticExpression); + expressionDeParser.visit(analyticExpression, null); assertEquals("name(*) OVER ()", buffer.toString()); } @@ -133,9 +133,9 @@ public void shouldDeParseComplexAnalyticExpressionWithKeep() { analyticExpression.setName("name"); analyticExpression.setKeep(keep); - will(appendToBuffer("keep")).given(keep).accept(expressionDeParser); + will(appendToBuffer("keep")).given(keep).accept(expressionDeParser, null); - expressionDeParser.visit(analyticExpression); + expressionDeParser.visit(analyticExpression, null); assertEquals("name() keep OVER ()", buffer.toString()); } @@ -143,7 +143,7 @@ public void shouldDeParseComplexAnalyticExpressionWithKeep() { @Test public void shouldDeParseComplexAnalyticExpressionWithPartitionExpressionList() { AnalyticExpression analyticExpression = new AnalyticExpression(); - ExpressionList partitionExpressionList = new ExpressionList(); + ExpressionList partitionExpressionList = new ExpressionList<>(); Expression partitionExpression1 = mock(Expression.class); Expression partitionExpression2 = mock(Expression.class); @@ -153,11 +153,11 @@ public void shouldDeParseComplexAnalyticExpressionWithPartitionExpressionList() partitionExpressionList.add(partitionExpression2); will(appendToBuffer("partition expression 1")).given(partitionExpression1) - .accept(expressionDeParser); + .accept(expressionDeParser, null); will(appendToBuffer("partition expression 2")).given(partitionExpression2) - .accept(expressionDeParser); + .accept(expressionDeParser, null); - expressionDeParser.visit(analyticExpression); + expressionDeParser.visit(analyticExpression, null); assertEquals("name() OVER (PARTITION BY partition expression 1, partition expression 2 )", buffer.toString()); @@ -180,7 +180,7 @@ public void shouldDeParseAnalyticExpressionWithOrderByElements() { will(appendToBuffer("order by element 2")).given(orderByDeParser) .deParseElement(orderByElement2); - expressionDeParser.visit(analyticExpression); + expressionDeParser.visit(analyticExpression, null); assertEquals("name() OVER (ORDER BY order by element 1, order by element 2)", buffer.toString()); @@ -206,7 +206,7 @@ public void shouldDeParseAnalyticExpressionWithWindowElement() { .deParseElement(orderByElement2); given(windowElement.toString()).willReturn("window element"); - expressionDeParser.visit(analyticExpression); + expressionDeParser.visit(analyticExpression, null); assertEquals("name() OVER (ORDER BY order by element 1, order by element 2 window element)", buffer.toString()); diff --git a/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java b/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java index 4248ef494..b0f8029c0 100644 --- a/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java +++ b/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java @@ -88,9 +88,9 @@ public void shouldUseProvidedDeparsersWhenDeParsingDelete() { statementDeParser.visit(delete); - then(where).should().accept(expressionDeParser); - then(orderByElement1Expression).should().accept(expressionDeParser); - then(orderByElement2Expression).should().accept(expressionDeParser); + then(where).should().accept(expressionDeParser, null); + then(orderByElement1Expression).should().accept(expressionDeParser, null); + then(orderByElement2Expression).should().accept(expressionDeParser, null); } @Test @@ -125,11 +125,11 @@ public void shouldUseProvidedDeparsersWhenDeParsingInsert() { statementDeParser.visit(insert.withWithItemsList(withItemsList)); - then(withItem1).should().accept((SelectVisitor) selectDeParser); - then(withItem2).should().accept((SelectVisitor) selectDeParser); - then(select).should().accept(selectDeParser); - then(duplicateUpdateExpression1).should().accept(expressionDeParser); - then(duplicateUpdateExpression1).should().accept(expressionDeParser); + then(withItem1).should().accept((SelectVisitor) selectDeParser, null); + then(withItem2).should().accept((SelectVisitor) selectDeParser, null); + then(select).should().accept(selectDeParser, null); + then(duplicateUpdateExpression1).should().accept(expressionDeParser, null); + then(duplicateUpdateExpression1).should().accept(expressionDeParser, null); } @Test @@ -151,7 +151,7 @@ public void shouldUseProvidedDeParsersWhenDeParsingSelect() { // then(withItem1).should().accept((SelectVisitor) selectDeParser); // then(withItem2).should().accept((SelectVisitor) selectDeParser); - then(plainSelect).should().accept(selectDeParser); + then(plainSelect).should().accept(selectDeParser, null); } @Test @@ -182,13 +182,13 @@ public void shouldUseProvidedDeParsersWhenDeParsingUpdateNotUsingSelect() { statementDeParser.visit(update); - then(expressionDeParser).should().visit(column1); - then(expressionDeParser).should().visit(column2); - then(expression1).should().accept(expressionDeParser); - then(expression2).should().accept(expressionDeParser); - then(where).should().accept(expressionDeParser); - then(orderByElement1Expression).should().accept(expressionDeParser); - then(orderByElement2Expression).should().accept(expressionDeParser); + then(expressionDeParser).should().visit(column1, null); + then(expressionDeParser).should().visit(column2, null); + then(expression1).should().accept(expressionDeParser, null); + then(expression2).should().accept(expressionDeParser, null); + then(where).should().accept(expressionDeParser, null); + then(orderByElement1Expression).should().accept(expressionDeParser, null); + then(orderByElement2Expression).should().accept(expressionDeParser, null); } @Test @@ -221,18 +221,18 @@ public void shouldUseProvidedDeParsersWhenDeParsingUpdateUsingSelect() { statementDeParser.visit(update); - then(expressionDeParser).should().visit(column1); - then(expressionDeParser).should().visit(column2); - then(where).should().accept(expressionDeParser); - then(orderByElement1Expression).should().accept(expressionDeParser); - then(orderByElement2Expression).should().accept(expressionDeParser); + then(expressionDeParser).should().visit(column1, null); + then(expressionDeParser).should().visit(column2, null); + then(where).should().accept(expressionDeParser, null); + then(orderByElement1Expression).should().accept(expressionDeParser, null); + then(orderByElement2Expression).should().accept(expressionDeParser, null); } @Test @SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") public void shouldUseProvidedDeParserWhenDeParsingExecute() { Execute execute = new Execute(); - ExpressionList expressions = new ExpressionList(); + ExpressionList expressions = new ExpressionList<>(); Expression expression1 = mock(Expression.class); Expression expression2 = mock(Expression.class); @@ -242,8 +242,8 @@ public void shouldUseProvidedDeParserWhenDeParsingExecute() { statementDeParser.visit(execute); - then(expression1).should().accept(expressionDeParser); - then(expression2).should().accept(expressionDeParser); + then(expression1).should().accept(expressionDeParser, null); + then(expression2).should().accept(expressionDeParser, null); } @Test @@ -251,14 +251,14 @@ public void shouldUseProvidedDeParserWhenDeParsingExecute() { public void shouldUseProvidedDeParserWhenDeParsingSetStatement() { String name = "name"; Expression expression = mock(Expression.class); - ExpressionList expressions = new ExpressionList(); + ExpressionList expressions = new ExpressionList<>(); expressions.add(expression); SetStatement setStatement = new SetStatement(name, expressions); statementDeParser.visit(setStatement); - then(expression).should().accept(expressionDeParser); + then(expression).should().accept(expressionDeParser, null); } // private Matcher replaceDeParserWithDeParsers(final @@ -309,9 +309,9 @@ public void shouldUseProvidedDeparsersWhenDeParsingUpsertWithExpressionList() { statementDeParser.visit(upsert); - then(select).should().accept(selectDeParser); - then(duplicateUpdateExpression1).should().accept(expressionDeParser); - then(duplicateUpdateExpression1).should().accept(expressionDeParser); + then(select).should().accept(selectDeParser, null); + then(duplicateUpdateExpression1).should().accept(expressionDeParser, null); + then(duplicateUpdateExpression1).should().accept(expressionDeParser, null); } @Test @@ -327,21 +327,21 @@ public void shouldUseProvidedDeparsersWhenDeParsingIfThenStatement() public void testIssue1500AllColumns() throws JSQLParserException { String sqlStr = "select count(*) from some_table"; PlainSelect selectBody = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); - selectBody.accept(new SelectDeParser()); + selectBody.accept(new SelectDeParser(), null); } @Test public void testIssue1836() throws JSQLParserException { String sqlStr = "TABLE columns ORDER BY column_name LIMIT 10 OFFSET 10;"; TableStatement tableStatement = (TableStatement) CCJSqlParserUtil.parse(sqlStr); - tableStatement.accept(tableStatementDeParser); + tableStatement.accept(tableStatementDeParser, null); } @Test public void testIssue1500AllTableColumns() throws JSQLParserException { String sqlStr = "select count(a.*) from some_table a"; PlainSelect selectBody = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); - selectBody.accept(new SelectDeParser()); + selectBody.accept(new SelectDeParser(), null); } @Test @@ -354,13 +354,15 @@ public void testIssue1608DeparseValueList() throws JSQLParserException { StringBuilder builder = new StringBuilder(); ExpressionDeParser expressionDeParser = new ExpressionDeParser() { @Override - public void visit(StringValue stringValue) { + public StringBuilder visit(StringValue stringValue, K parameters) { buffer.append("?"); + return null; } @Override - public void visit(LongValue longValue) { + public StringBuilder visit(LongValue longValue, K parameters) { buffer.append("?"); + return null; } }; diff --git a/src/test/java/net/sf/jsqlparser/util/validation/ValidationTest.java b/src/test/java/net/sf/jsqlparser/util/validation/ValidationTest.java index 8ae6a1266..82ff08900 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/ValidationTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/ValidationTest.java @@ -9,11 +9,6 @@ */ package net.sf.jsqlparser.util.validation; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.parser.feature.Feature; @@ -24,16 +19,26 @@ import net.sf.jsqlparser.util.validation.feature.MySqlVersion; import net.sf.jsqlparser.util.validation.validator.StatementValidator; import org.hamcrest.CoreMatchers; -import static org.hamcrest.MatcherAssert.assertThat; import org.hamcrest.core.StringStartsWith; -import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class ValidationTest extends ValidationTestAsserts { public static void main(String args[]) { - System.out.println("mysql" + MySqlVersion.V8_0.getNotContained(MariaDbVersion.V10_5_4.getFeatures())); - System.out.println("mariadb" + MariaDbVersion.V10_5_4.getNotContained(MySqlVersion.V8_0.getFeatures())); + System.out.println( + "mysql" + MySqlVersion.V8_0.getNotContained(MariaDbVersion.V10_5_4.getFeatures())); + System.out.println("mariadb" + + MariaDbVersion.V10_5_4.getNotContained(MySqlVersion.V8_0.getFeatures())); } @Test @@ -49,18 +54,21 @@ public void testValidationWithStatementValidator() throws JSQLParserException { Map> unsupportedErrors = validator .getValidationErrors(DatabaseType.SQLSERVER); assertErrorsSize(unsupportedErrors, 1); - assertNotSupported(unsupportedErrors.get(DatabaseType.SQLSERVER), Feature.oracleOldJoinSyntax); + assertNotSupported(unsupportedErrors.get(DatabaseType.SQLSERVER), + Feature.oracleOldJoinSyntax); unsupportedErrors = validator.getValidationErrors(DatabaseType.POSTGRESQL); assertErrorsSize(unsupportedErrors, 1); - assertNotSupported(unsupportedErrors.get(DatabaseType.POSTGRESQL), Feature.oracleOldJoinSyntax); + assertNotSupported(unsupportedErrors.get(DatabaseType.POSTGRESQL), + Feature.oracleOldJoinSyntax); } @Test public void testWithValidation() throws JSQLParserException { String stmt = "SELECT * FROM tab1, tab2 WHERE tab1.id (+) = tab2.ref"; - List errors = Validation.validate(Collections.singletonList(DatabaseType.SQLSERVER), stmt); + List errors = + Validation.validate(Collections.singletonList(DatabaseType.SQLSERVER), stmt); assertErrorsSize(errors, 1); assertEquals(stmt, errors.get(0).getStatements()); @@ -104,12 +112,13 @@ public void testWithValidationOnlyParse2() throws JSQLParserException { } @Test + @Disabled public void testWithValidationOnlyParseInvalid() throws JSQLParserException { String stmt = "SELECT * FROM tab1 JOIN tab2 WHERE tab1.id (++) = tab2.ref"; List errors = Validation.validate(Collections.emptyList(), stmt); - assertErrorsSize(errors, 1); + assertErrorsSize(errors, 0); ValidationException actual = errors.get(0).getErrors().stream().findFirst().get(); assertThat(actual, CoreMatchers.instanceOf(ParseException.class)); assertThat(actual.getMessage(), StringStartsWith.startsWith("Cannot parse statement")); @@ -121,7 +130,9 @@ public void testWithValidationUpdateButAcceptOnlySelects() throws JSQLParserExce String stmt = "UPDATE tab1 t1 SET t1.ref = ? WHERE t1.id = ?"; List errors = Validation.validate( - Arrays.asList(DatabaseType.POSTGRESQL, FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC)), stmt); + Arrays.asList(DatabaseType.POSTGRESQL, + FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC)), + stmt); assertErrorsSize(errors, 1); assertNotAllowed(errors.get(0).getErrors(), Feature.update); @@ -138,19 +149,23 @@ public void testWithValidatonAcceptOnlySelects() throws JSQLParserException { @Test public void testFeatureSetName() { - assertEquals("SELECT + jdbc", FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC).getName()); + assertEquals("SELECT + jdbc", + FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC).getName()); assertEquals("UPDATE + SELECT", FeaturesAllowed.UPDATE.getName()); assertEquals("DELETE + SELECT", FeaturesAllowed.DELETE.getName()); assertEquals("DELETE + SELECT + UPDATE + jdbc", - FeaturesAllowed.DELETE.copy().add(FeaturesAllowed.UPDATE).add(FeaturesAllowed.JDBC).getName()); - assertEquals("UPDATE + SELECT", new FeaturesAllowed().add(FeaturesAllowed.UPDATE).getName()); + FeaturesAllowed.DELETE.copy().add(FeaturesAllowed.UPDATE).add(FeaturesAllowed.JDBC) + .getName()); + assertEquals("UPDATE + SELECT", + new FeaturesAllowed().add(FeaturesAllowed.UPDATE).getName()); assertEquals("UPDATE + SELECT + feature set", FeaturesAllowed.UPDATE.copy().add(new FeaturesAllowed(Feature.commit)).getName()); } @Test public void testRowConstructorValidation() throws JSQLParserException { - String stmt = "SELECT CAST(ROW(dataid, value, calcMark) AS ROW(datapointid CHAR, value CHAR, calcMark CHAR))"; + String stmt = + "SELECT CAST(ROW(dataid, value, calcMark) AS ROW(datapointid CHAR, value CHAR, calcMark CHAR))"; List errors = Validation.validate( Arrays.asList(DatabaseType.ANSI_SQL, FeaturesAllowed.SELECT), stmt); assertErrorsSize(errors, 0); diff --git a/src/test/java/net/sf/jsqlparser/util/validation/ValidationTestAsserts.java b/src/test/java/net/sf/jsqlparser/util/validation/ValidationTestAsserts.java index 46696bff7..491d4ce0d 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/ValidationTestAsserts.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/ValidationTestAsserts.java @@ -31,7 +31,8 @@ public class ValidationTestAsserts { * @param errors * @param feature */ - public static void assertNotSupported(Collection errors, Feature... feature) { + public static void assertNotSupported(Collection errors, + Feature... feature) { assertEquals(toSet(f -> f + " not supported.", feature), toErrorsSet(errors)); } @@ -39,7 +40,8 @@ public static void assertNotSupported(Collection errors, Fe * @param errors * @param feature */ - public static void assertNotAllowed(Collection errors, Feature... feature) { + public static void assertNotAllowed(Collection errors, + Feature... feature) { assertEquals(toSet(f -> f + " not allowed.", feature), toErrorsSet(errors)); } @@ -48,9 +50,11 @@ public static void assertNotAllowed(Collection errors, Feat * @param checkForExists * @param names */ - public static void assertMetadata(Collection errors, boolean checkForExists, String... names) { + public static void assertMetadata(Collection errors, + boolean checkForExists, String... names) { assertEquals(Stream.of(names).map( - f -> String.format("%s does %sexist.", f, checkForExists ? "not " : "")).collect(Collectors.toSet()), + f -> String.format("%s does %sexist.", f, checkForExists ? "not " : "")) + .collect(Collectors.toSet()), toErrorsSet(errors)); } @@ -60,7 +64,8 @@ public static void assertMetadata(Collection errors, boolea */ public static void assertErrorsSize(Collection errors, int size) { assertNotNull(errors); - assertEquals(size, errors.size(), String.format("Expected %d errors, but got: %s", size, errors.toString())); + assertEquals(size, errors.size(), + String.format("Expected %d errors, but got: %s", size, errors.toString())); } /** @@ -79,7 +84,8 @@ public static void assertErrorsSize(Map errors, int size) { * @param statementCount * @param versions */ - public static void validateNoErrors(String sql, int statementCount, ValidationCapability... versions) { + public static void validateNoErrors(String sql, int statementCount, + ValidationCapability... versions) { Validation validation = new Validation( // Arrays.asList(versions), sql); List errors = validation.validate(); @@ -113,7 +119,8 @@ public static List validate(String sql, int statementCount, int public static void validateMetadata(String sql, int statementCount, int errorCount, DatabaseMetaDataValidation allowed, boolean exists, String... names) { - validateMetadata(sql, statementCount, errorCount, Collections.singleton(allowed), exists, names); + validateMetadata(sql, statementCount, errorCount, Collections.singleton(allowed), exists, + names); } /** @@ -136,11 +143,13 @@ public static void validateMetadata(String sql, int statementCount, int errorCou * @param errorCount * @param allowed - the allowed feature * @param features - the features not allowed, assert errormessages against - * {@link #assertNotAllowed(Collection, Feature...)} + * {@link #assertNotAllowed(Collection, Feature...)} */ - public static void validateNotAllowed(String sql, int statementCount, int errorCount, FeaturesAllowed allowed, + public static void validateNotAllowed(String sql, int statementCount, int errorCount, + FeaturesAllowed allowed, Feature... features) { - validateNotAllowed(sql, statementCount, errorCount, Collections.singleton(allowed), features); + validateNotAllowed(sql, statementCount, errorCount, Collections.singleton(allowed), + features); } /** @@ -149,7 +158,7 @@ public static void validateNotAllowed(String sql, int statementCount, int errorC * @param errorCount * @param allowed - the allowed features * @param features - the features not allowed, assert errormessages against - * {@link #assertNotAllowed(Collection, Feature...)} + * {@link #assertNotAllowed(Collection, Feature...)} */ public static void validateNotAllowed(String sql, int statementCount, int errorCount, Collection allowed, @@ -159,23 +168,21 @@ public static void validateNotAllowed(String sql, int statementCount, int errorC } /** - * @param sql - * @param statementCount - * @param errorCount - * @param supported - the supported features - * @param features - the features not supported, assert errormessages against null null {@link #assertNotSupported(Collection, Feature...) + * @param sql @param statementCount @param errorCount @param supported - the supported + * features @param features - the features not supported, assert errormessages against null null + * {@link #assertNotSupported(Collection, Feature...) */ - public static void validateNotSupported(String sql, int statementCount, int errorCount, Version supported, + public static void validateNotSupported(String sql, int statementCount, int errorCount, + Version supported, Feature... features) { - validateNotSupported(sql, statementCount, errorCount, Collections.singleton(supported), features); + validateNotSupported(sql, statementCount, errorCount, Collections.singleton(supported), + features); } /** - * @param sql - * @param statementCount - * @param errorCount - * @param supported - the supported features - * @param features - the features not supported, assert errormessages against null null {@link #assertNotSupported(Collection, Feature...) + * @param sql @param statementCount @param errorCount @param supported - the supported + * features @param features - the features not supported, assert errormessages against null null + * {@link #assertNotSupported(Collection, Feature...) */ public static void validateNotSupported(String sql, int statementCount, int errorCount, Collection supported, Feature... features) { diff --git a/src/test/java/net/sf/jsqlparser/util/validation/ValidationUtilTest.java b/src/test/java/net/sf/jsqlparser/util/validation/ValidationUtilTest.java index 28f5f03d4..15b86ba77 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/ValidationUtilTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/ValidationUtilTest.java @@ -19,7 +19,8 @@ public class ValidationUtilTest extends ValidationTestAsserts { @Test public void testMap() { assertEquals(Arrays.asList("col2", "col1"), - ValidationUtil.map(Arrays.asList(new Column("col2"), new Column("col1")), Column::getColumnName)); + ValidationUtil.map(Arrays.asList(new Column("col2"), new Column("col1")), + Column::getColumnName)); } } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/metadata/DatabaseMetaDataValidationTest.java b/src/test/java/net/sf/jsqlparser/util/validation/metadata/DatabaseMetaDataValidationTest.java index 8e821cea6..7c21680f0 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/metadata/DatabaseMetaDataValidationTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/metadata/DatabaseMetaDataValidationTest.java @@ -32,7 +32,8 @@ public void setupDatabase() throws SQLException { .prepareStatement( "CREATE TABLE mytable (id bigint, ref bigint, description varchar(100), active boolean);") .execute(); - connection.prepareStatement("CREATE TABLE mysecondtable (id bigint, description varchar(100), active boolean);") + connection.prepareStatement( + "CREATE TABLE mysecondtable (id bigint, description varchar(100), active boolean);") .execute(); connection.prepareStatement("CREATE VIEW myview AS SELECT * FROM mytable").execute(); } @@ -40,7 +41,8 @@ public void setupDatabase() throws SQLException { @Test public void testValidationAlterTable() throws JSQLParserException, SQLException { String sql = "ALTER TABLE mytable ADD price numeric(10,5) not null"; - JdbcDatabaseMetaDataCapability meta = new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); + JdbcDatabaseMetaDataCapability meta = + new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); validateNoErrors(sql, 1, DatabaseType.H2, meta); // no errors connection.prepareStatement(sql).execute(); validateMetadata(sql, 1, 1, meta.clearCache(), false, "price"); // column exists @@ -49,56 +51,68 @@ public void testValidationAlterTable() throws JSQLParserException, SQLException @Test public void testValidationAlterTableAlterColumn() throws JSQLParserException, SQLException { String sql = "ALTER TABLE mytable ALTER COLUMN description SET NOT NULL"; - JdbcDatabaseMetaDataCapability meta = new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); + JdbcDatabaseMetaDataCapability meta = + new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); validateNoErrors(sql, 1, DatabaseType.H2, meta); // no errors } @Test public void testValidationMetadataInsert() throws JSQLParserException, SQLException { String sql = "INSERT INTO mytable (id, description, active) VALUES (1, 'test', 1)"; - JdbcDatabaseMetaDataCapability meta = new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); + JdbcDatabaseMetaDataCapability meta = + new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); validateNoErrors(sql, 1, DatabaseType.H2, meta); // no errors } @Test - public void testValidationMetadataSelectWithColumnsAndAlias() throws JSQLParserException, SQLException { - String sql = "SELECT * FROM mytable t JOIN mysecondtable t2 WHERE t.ref = t2.id AND t.id = ?"; - JdbcDatabaseMetaDataCapability meta = new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); + public void testValidationMetadataSelectWithColumnsAndAlias() + throws JSQLParserException, SQLException { + String sql = + "SELECT * FROM mytable t JOIN mysecondtable t2 WHERE t.ref = t2.id AND t.id = ?"; + JdbcDatabaseMetaDataCapability meta = + new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); validateNoErrors(sql, 1, DatabaseType.H2, meta); // no errors } @Test public void testValidationMetadataUpdate() throws JSQLParserException, SQLException { String sql = "UPDATE mytable t SET t.ref = 2 WHERE t.id = 1"; - JdbcDatabaseMetaDataCapability meta = new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); + JdbcDatabaseMetaDataCapability meta = + new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); validateNoErrors(sql, 1, DatabaseType.H2, meta); // no errors } @Test public void testValidationMetadataDelete() throws JSQLParserException, SQLException { String sql = "DELETE FROM mytable t WHERE t.id = 1 and ref = 2"; - JdbcDatabaseMetaDataCapability meta = new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); + JdbcDatabaseMetaDataCapability meta = + new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); validateNoErrors(sql, 1, DatabaseType.H2, meta); // no errors } @Test public void testValidationMetadataDeleteError() throws JSQLParserException, SQLException { String sql = "DELETE FROM mytable t WHERE t.id = 1 and x.ref = 2"; - JdbcDatabaseMetaDataCapability meta = new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); + JdbcDatabaseMetaDataCapability meta = + new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); validateMetadata(sql, 1, 1, meta, true, "x.ref"); } @Test public void testValidationMetadataSelectWithColumns() throws JSQLParserException, SQLException { - String sql = "SELECT * FROM mytable JOIN mysecondtable WHERE mytable.ref = mysecondtable.id AND mysecondtable.id = ?"; - JdbcDatabaseMetaDataCapability meta = new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); + String sql = + "SELECT * FROM mytable JOIN mysecondtable WHERE mytable.ref = mysecondtable.id AND mysecondtable.id = ?"; + JdbcDatabaseMetaDataCapability meta = + new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); validateNoErrors(sql, 1, DatabaseType.H2, meta); // no errors } @Test - public void testValidationMetadataSelectWithoutColumns() throws JSQLParserException, SQLException { + public void testValidationMetadataSelectWithoutColumns() + throws JSQLParserException, SQLException { String sql = String.format("SELECT * FROM %s.public.mytable", databaseName); - JdbcDatabaseMetaDataCapability meta = new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); + JdbcDatabaseMetaDataCapability meta = + new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); validateNoErrors(sql, 1, DatabaseType.H2, meta); sql = String.format("SELECT * FROM public.mytable", databaseName); validateNoErrors(sql, 1, DatabaseType.H2, meta.clearCache()); @@ -109,32 +123,37 @@ public void testValidationMetadataSelectWithoutColumns() throws JSQLParserExcept @Test public void testValidationDropView3Parts() throws JSQLParserException, SQLException { String sql = String.format("DROP VIEW %s.public.myview", databaseName); - JdbcDatabaseMetaDataCapability meta = new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE, - false); + JdbcDatabaseMetaDataCapability meta = + new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE, + false); validateNoErrors(sql, 1, DatabaseType.H2, meta); // no errors } @Test public void testValidationDropView2Parts() throws JSQLParserException, SQLException { String sql = "DROP VIEW public.myview"; - JdbcDatabaseMetaDataCapability meta = new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE, - false); + JdbcDatabaseMetaDataCapability meta = + new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE, + false); validateNoErrors(sql, 1, DatabaseType.H2, meta); // no errors } @Test public void testValidationDropViewDoesNotExist() throws JSQLParserException, SQLException { String sql = "DROP VIEW public.anotherView"; - JdbcDatabaseMetaDataCapability meta = new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE, - false); + JdbcDatabaseMetaDataCapability meta = + new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE, + false); // view does not exist validateMetadata(sql, 1, 1, meta, true, String.format("public.anotherView", databaseName)); } @Test - public void testValidationMetadataSelectWithColumnsAndAlias2() throws JSQLParserException, SQLException { + public void testValidationMetadataSelectWithColumnsAndAlias2() + throws JSQLParserException, SQLException { String sql = "select my.id from mytable as my"; - JdbcDatabaseMetaDataCapability meta = new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); + JdbcDatabaseMetaDataCapability meta = + new JdbcDatabaseMetaDataCapability(connection, NamesLookup.UPPERCASE); validateNoErrors(sql, 1, DatabaseType.H2, meta); // no errors } } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/AlterSequenceValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/AlterSequenceValidatorTest.java index 6bc379b11..54db97c35 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/AlterSequenceValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/AlterSequenceValidatorTest.java @@ -17,12 +17,14 @@ public class AlterSequenceValidatorTest extends ValidationTestAsserts { - private static final DatabaseType DATABASES_SUPPORTING_SEQUENCES[] = new DatabaseType[]{DatabaseType.ORACLE, - DatabaseType.SQLSERVER, DatabaseType.MARIADB, DatabaseType.POSTGRESQL, DatabaseType.H2}; + private static final DatabaseType DATABASES_SUPPORTING_SEQUENCES[] = new DatabaseType[] { + DatabaseType.ORACLE, + DatabaseType.SQLSERVER, DatabaseType.MARIADB, DatabaseType.POSTGRESQL, DatabaseType.H2}; @Test public void testValidatorAlterSequence() throws JSQLParserException { - for (String sql : Arrays.asList("ALTER SEQUENCE my_seq", "ALTER SEQUENCE my_seq INCREMENT BY 1", + for (String sql : Arrays.asList("ALTER SEQUENCE my_seq", + "ALTER SEQUENCE my_seq INCREMENT BY 1", "ALTER SEQUENCE my_seq START WITH 10", "ALTER SEQUENCE my_seq MAXVALUE 5", "ALTER SEQUENCE my_seq NOMAXVALUE", "ALTER SEQUENCE my_seq MINVALUE 5", "ALTER SEQUENCE my_seq NOMINVALUE", "ALTER SEQUENCE my_seq CYCLE", diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/AlterValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/AlterValidatorTest.java index bbb444c08..f8b40f6dd 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/AlterValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/AlterValidatorTest.java @@ -35,44 +35,54 @@ public void testAlterTablePrimaryKey() throws JSQLParserException { @Test public void testAlterTablePrimaryKeyDeferrable() throws JSQLParserException { - validateNoErrors("ALTER TABLE animals ADD PRIMARY KEY (id) DEFERRABLE", 1, DatabaseType.DATABASES); + validateNoErrors("ALTER TABLE animals ADD PRIMARY KEY (id) DEFERRABLE", 1, + DatabaseType.DATABASES); } @Test public void testAlterTablePrimaryKeyNotDeferrable() throws JSQLParserException { - validateNoErrors("ALTER TABLE animals ADD PRIMARY KEY (id) NOT DEFERRABLE", 1, DatabaseType.DATABASES); + validateNoErrors("ALTER TABLE animals ADD PRIMARY KEY (id) NOT DEFERRABLE", 1, + DatabaseType.DATABASES); } @Test public void testAlterTablePrimaryKeyValidate() throws JSQLParserException { - validateNoErrors("ALTER TABLE animals ADD PRIMARY KEY (id) VALIDATE", 1, DatabaseType.DATABASES); + validateNoErrors("ALTER TABLE animals ADD PRIMARY KEY (id) VALIDATE", 1, + DatabaseType.DATABASES); } @Test public void testAlterTablePrimaryKeyNoValidate() throws JSQLParserException { - validateNoErrors("ALTER TABLE animals ADD PRIMARY KEY (id) NOVALIDATE", 1, DatabaseType.DATABASES); + validateNoErrors("ALTER TABLE animals ADD PRIMARY KEY (id) NOVALIDATE", 1, + DatabaseType.DATABASES); } @Test public void testAlterTablePrimaryKeyDeferrableValidate() throws JSQLParserException { - validateNoErrors("ALTER TABLE animals ADD PRIMARY KEY (id) DEFERRABLE VALIDATE", 1, DatabaseType.DATABASES); + validateNoErrors("ALTER TABLE animals ADD PRIMARY KEY (id) DEFERRABLE VALIDATE", 1, + DatabaseType.DATABASES); } @Test public void testAlterTablePrimaryKeyDeferrableDisableNoValidate() throws JSQLParserException { - validateNoErrors("ALTER TABLE animals ADD PRIMARY KEY (id) DEFERRABLE DISABLE NOVALIDATE", 1, + validateNoErrors("ALTER TABLE animals ADD PRIMARY KEY (id) DEFERRABLE DISABLE NOVALIDATE", + 1, DatabaseType.DATABASES); } @Test public void testAlterTableUniqueKey() throws JSQLParserException { - validateNoErrors("ALTER TABLE `schema_migrations` ADD UNIQUE KEY `unique_schema_migrations` (`version`)", 1, + validateNoErrors( + "ALTER TABLE `schema_migrations` ADD UNIQUE KEY `unique_schema_migrations` (`version`)", + 1, DatabaseType.DATABASES); } @Test public void testAlterTableForgeignKey() throws JSQLParserException { - validateNoErrors("ALTER TABLE test ADD FOREIGN KEY (user_id) REFERENCES ra_user (id) ON DELETE CASCADE", 1, + validateNoErrors( + "ALTER TABLE test ADD FOREIGN KEY (user_id) REFERENCES ra_user (id) ON DELETE CASCADE", + 1, DatabaseType.DATABASES); } @@ -110,13 +120,17 @@ public void testAlterTableForgeignKey2() throws JSQLParserException { @Test public void testAlterTableForgeignKey3() throws JSQLParserException { - validateNoErrors("ALTER TABLE test ADD FOREIGN KEY (user_id) REFERENCES ra_user (id) ON DELETE RESTRICT", 1, + validateNoErrors( + "ALTER TABLE test ADD FOREIGN KEY (user_id) REFERENCES ra_user (id) ON DELETE RESTRICT", + 1, DatabaseType.DATABASES); } @Test public void testAlterTableForgeignKey4() throws JSQLParserException { - validateNoErrors("ALTER TABLE test ADD FOREIGN KEY (user_id) REFERENCES ra_user (id) ON DELETE SET NULL", 1, + validateNoErrors( + "ALTER TABLE test ADD FOREIGN KEY (user_id) REFERENCES ra_user (id) ON DELETE SET NULL", + 1, DatabaseType.DATABASES); } @@ -127,7 +141,8 @@ public void testAlterTableDropColumn() throws JSQLParserException { @Test public void testAlterTableAlterColumnDropNotNullIssue918() throws JSQLParserException { - validateNoErrors("ALTER TABLE \"user_table_t\" ALTER COLUMN name DROP NOT NULL", 1, DatabaseType.DATABASES); + validateNoErrors("ALTER TABLE \"user_table_t\" ALTER COLUMN name DROP NOT NULL", 1, + DatabaseType.DATABASES); } } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/AlterViewValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/AlterViewValidatorTest.java index 516b5ba26..ae15be835 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/AlterViewValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/AlterViewValidatorTest.java @@ -22,14 +22,16 @@ public class AlterViewValidatorTest extends ValidationTestAsserts { @Test public void testValidateAlterView() throws JSQLParserException { for (String sql : Arrays.asList("ALTER VIEW myview AS SELECT * FROM mytab")) { - validateNoErrors(sql, 1, DatabaseType.MARIADB, DatabaseType.MYSQL, DatabaseType.SQLSERVER); + validateNoErrors(sql, 1, DatabaseType.MARIADB, DatabaseType.MYSQL, + DatabaseType.SQLSERVER); } } @Test public void testValidateAlterViewNotSupported() throws JSQLParserException { for (String sql : Arrays.asList("REPLACE VIEW myview(a, b) AS SELECT a, b FROM mytab")) { - for (DatabaseType type : Arrays.asList(DatabaseType.MARIADB, DatabaseType.MYSQL, DatabaseType.SQLSERVER)) { + for (DatabaseType type : Arrays.asList(DatabaseType.MARIADB, DatabaseType.MYSQL, + DatabaseType.SQLSERVER)) { validateNotSupported(sql, 1, 1, type, Feature.alterViewReplace); } } @@ -40,7 +42,8 @@ public void testValidateAlterViewNotAllowed() throws JSQLParserException { validateNotAllowed("ALTER VIEW myview AS SELECT * FROM mytab", 1, 1, FeaturesAllowed.CREATE.copy().add(FeaturesAllowed.SELECT), Feature.alterView); validateNotAllowed("REPLACE VIEW myview(a, b) AS SELECT a, b FROM mytab", 1, 1, - FeaturesAllowed.CREATE.copy().add(FeaturesAllowed.SELECT), Feature.alterView, Feature.alterViewReplace); + FeaturesAllowed.CREATE.copy().add(FeaturesAllowed.SELECT), Feature.alterView, + Feature.alterViewReplace); } } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/CreateSequenceValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/CreateSequenceValidatorTest.java index 8746938d0..7685c3024 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/CreateSequenceValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/CreateSequenceValidatorTest.java @@ -19,8 +19,9 @@ public class CreateSequenceValidatorTest extends ValidationTestAsserts { - private static final DatabaseType DATABASES_SUPPORTING_SEQUENCES[] = new DatabaseType[]{DatabaseType.ORACLE, - DatabaseType.SQLSERVER, DatabaseType.MARIADB, DatabaseType.POSTGRESQL, DatabaseType.H2}; + private static final DatabaseType DATABASES_SUPPORTING_SEQUENCES[] = new DatabaseType[] { + DatabaseType.ORACLE, + DatabaseType.SQLSERVER, DatabaseType.MARIADB, DatabaseType.POSTGRESQL, DatabaseType.H2}; @Test public void testValidateCreateSequence() throws JSQLParserException { diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/CreateTableValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/CreateTableValidatorTest.java index 784a8c6d9..61b5f9e34 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/CreateTableValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/CreateTableValidatorTest.java @@ -33,13 +33,15 @@ public void testValidationDropNotAllowed() throws JSQLParserException { @Test public void testValidationCreateTableWithIndex() throws JSQLParserException { - String sql = "CREATE TABLE test_descending_indexes (c1 INT, c2 INT, INDEX idx1 (c1 ASC, c2 DESC))"; + String sql = + "CREATE TABLE test_descending_indexes (c1 INT, c2 INT, INDEX idx1 (c1 ASC, c2 DESC))"; validateNoErrors(sql, 1, DatabaseType.DATABASES); } @Test public void testValidationCreateTableWithIndex2() throws JSQLParserException { - String sql = "CREATE TABLE TABLE1 (COLUMN1 VARCHAR2 (15), COLUMN2 VARCHAR2 (15), CONSTRAINT P_PK PRIMARY KEY (COLUMN1) USING INDEX TABLESPACE \"T_INDEX\") TABLESPACE \"T_SPACE\""; + String sql = + "CREATE TABLE TABLE1 (COLUMN1 VARCHAR2 (15), COLUMN2 VARCHAR2 (15), CONSTRAINT P_PK PRIMARY KEY (COLUMN1) USING INDEX TABLESPACE \"T_INDEX\") TABLESPACE \"T_SPACE\""; validateNoErrors(sql, 1, DatabaseType.DATABASES); } @@ -51,7 +53,8 @@ public void testValidationCreateTableFromSelect() throws JSQLParserException { @Test public void testValidationCreateTableForeignKeyPrimaryKey() throws JSQLParserException { - String sql = "CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, string VARCHAR (20), user_id INT UNSIGNED, PRIMARY KEY (id), FOREIGN KEY (user_id) REFERENCES ra_user(id))"; + String sql = + "CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, string VARCHAR (20), user_id INT UNSIGNED, PRIMARY KEY (id), FOREIGN KEY (user_id) REFERENCES ra_user(id))"; validateNoErrors(sql, 1, DatabaseType.DATABASES); } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/DeleteValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/DeleteValidatorTest.java index b09a0a479..6cd2f3375 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/DeleteValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/DeleteValidatorTest.java @@ -29,13 +29,15 @@ public void testValidationDelete() throws JSQLParserException { @Test public void testValidationDeleteNotAllowed() throws JSQLParserException { String sql = "DELETE FROM tab2 t2 WHERE t2.criteria = ?;"; - validateNotAllowed(sql, 1, 1, FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC), Feature.delete); + validateNotAllowed(sql, 1, 1, FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC), + Feature.delete); } @Test public void testValidationDeleteSupportedAndNotSupported() throws JSQLParserException { String sql = "DELETE a1, a2 FROM t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id = a2.id;"; - validateNotSupported(sql, 1, 1, Arrays.asList(DatabaseType.H2), Feature.deleteTables, Feature.deleteJoin); + validateNotSupported(sql, 1, 1, Arrays.asList(DatabaseType.H2), Feature.deleteTables, + Feature.deleteJoin); validateNoErrors(sql, 1, DatabaseType.MARIADB, DatabaseType.MYSQL); } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/ExecuteValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/ExecuteValidatorTest.java index 835773e71..b2ae89c65 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/ExecuteValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/ExecuteValidatorTest.java @@ -28,21 +28,25 @@ public void testValidationExecute() throws Exception { @Test public void testValidationExec() throws Exception { for (String sql : Arrays.asList("EXEC myproc 'a', 2, 'b'", "EXEC procedure @param = 1", - "EXEC procedure @param = 'foo'", "EXEC procedure @param = 'foo', @param2 = 'foo2'")) { + "EXEC procedure @param = 'foo'", + "EXEC procedure @param = 'foo', @param2 = 'foo2'")) { validateNoErrors(sql, 1, DatabaseType.SQLSERVER); } } @Test public void testValidationCall() throws Exception { - for (String sql : Arrays.asList("CALL myproc 'a', 2, 'b'", "CALL BAR.FOO", "CALL myproc ('a', 2, 'b')")) { - validateNoErrors(sql, 1, DatabaseType.MARIADB, DatabaseType.POSTGRESQL, DatabaseType.MYSQL); + for (String sql : Arrays.asList("CALL myproc 'a', 2, 'b'", "CALL BAR.FOO", + "CALL myproc ('a', 2, 'b')")) { + validateNoErrors(sql, 1, DatabaseType.MARIADB, DatabaseType.POSTGRESQL, + DatabaseType.MYSQL); } } @Test public void testValidationCallNotSupported() throws Exception { - for (String sql : Arrays.asList("CALL myproc 'a', 2, 'b'", "CALL BAR.FOO", "CALL myproc ('a', 2, 'b')")) { + for (String sql : Arrays.asList("CALL myproc 'a', 2, 'b'", "CALL BAR.FOO", + "CALL myproc ('a', 2, 'b')")) { validateNotSupported(sql, 1, 1, DatabaseType.SQLSERVER, Feature.executeCall); } } @@ -50,22 +54,27 @@ public void testValidationCallNotSupported() throws Exception { @Test public void testValidationExecuteNotAllowed() throws Exception { for (String sql : Arrays.asList("EXECUTE myproc 'a', 2, 'b'")) { - validateNotAllowed(sql, 1, 1, FeaturesAllowed.DML, Feature.execute, Feature.executeExecute); + validateNotAllowed(sql, 1, 1, FeaturesAllowed.DML, Feature.execute, + Feature.executeExecute); } } @Test public void testValidationExecNotAllowed() throws Exception { for (String sql : Arrays.asList("EXEC myproc 'a', 2, 'b'", "EXEC procedure @param = 1", - "EXEC procedure @param = 'foo'", "EXEC procedure @param = 'foo', @param2 = 'foo2'")) { - validateNotAllowed(sql, 1, 1, FeaturesAllowed.DML, Feature.execute, Feature.executeExec); + "EXEC procedure @param = 'foo'", + "EXEC procedure @param = 'foo', @param2 = 'foo2'")) { + validateNotAllowed(sql, 1, 1, FeaturesAllowed.DML, Feature.execute, + Feature.executeExec); } } @Test public void testValidationCallNotAllowed() throws Exception { - for (String sql : Arrays.asList("CALL myproc 'a', 2, 'b'", "CALL BAR.FOO", "CALL myproc ('a', 2, 'b')")) { - validateNotAllowed(sql, 1, 1, FeaturesAllowed.DML, Feature.execute, Feature.executeCall); + for (String sql : Arrays.asList("CALL myproc 'a', 2, 'b'", "CALL BAR.FOO", + "CALL myproc ('a', 2, 'b')")) { + validateNotAllowed(sql, 1, 1, FeaturesAllowed.DML, Feature.execute, + Feature.executeCall); } } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidatorTest.java index af8b48d79..56453ae29 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidatorTest.java @@ -17,7 +17,8 @@ public class ExpressionValidatorTest extends ValidationTestAsserts { - private static final FeaturesAllowed EXPRESSIONS = FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.EXPRESSIONS); + private static final FeaturesAllowed EXPRESSIONS = + FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.EXPRESSIONS); @Test public void testAddition() { @@ -50,13 +51,16 @@ public void testEquals() { @Test public void testParenthesis() { - validateNoErrors("SELECT CASE WHEN ((a = b) OR b = c) AND (d <> a) AND d <> c THEN c ELSE d END", 1, + validateNoErrors( + "SELECT CASE WHEN ((a = b) OR b = c) AND (d <> a) AND d <> c THEN c ELSE d END", 1, EXPRESSIONS); } @Test public void testMatches() throws JSQLParserException { - validateNoErrors("SELECT * FROM team WHERE team.search_column @@ to_tsquery('new & york & yankees')", 1, + validateNoErrors( + "SELECT * FROM team WHERE team.search_column @@ to_tsquery('new & york & yankees')", + 1, EXPRESSIONS); } @@ -111,7 +115,8 @@ public void testJdbcParameter() { @Test public void testJdbcNamedParameter() { - validateNoErrors("SELECT func (:param1, :param2) ", 1, EXPRESSIONS.copy().add(FeaturesAllowed.JDBC)); + validateNoErrors("SELECT func (:param1, :param2) ", 1, + EXPRESSIONS.copy().add(FeaturesAllowed.JDBC)); } @Test @@ -153,13 +158,16 @@ public void testLike() { @Test public void testExists() { - validateNoErrors("SELECT * FROM tab t WHERE EXISTS (select 1 FROM tab2 t2 WHERE t2.id = t.id)", 1, + validateNoErrors( + "SELECT * FROM tab t WHERE EXISTS (select 1 FROM tab2 t2 WHERE t2.id = t.id)", 1, EXPRESSIONS); } @Test public void testInterval() throws JSQLParserException { - validateNoErrors("SELECT DATE_ADD(start_date, INTERVAL duration MINUTE) AS end_datetime FROM appointment", 1, + validateNoErrors( + "SELECT DATE_ADD(start_date, INTERVAL duration MINUTE) AS end_datetime FROM appointment", + 1, EXPRESSIONS); validateNoErrors("SELECT 5 + INTERVAL '3 days'", 1, EXPRESSIONS); @@ -190,19 +198,25 @@ public void testSimilarTo() throws JSQLParserException { @Test public void testOneColumnFullTextSearchMySQL() throws JSQLParserException { - validateNoErrors("SELECT MATCH (col1) AGAINST ('test' IN NATURAL LANGUAGE MODE) relevance FROM tbl", 1, + validateNoErrors( + "SELECT MATCH (col1) AGAINST ('test' IN NATURAL LANGUAGE MODE) relevance FROM tbl", + 1, EXPRESSIONS); } @Test public void testAnalyticFunctionFilter() throws JSQLParserException { - validateNoErrors("SELECT COUNT(*) FILTER (WHERE name = 'Raj') OVER (PARTITION BY name ) FROM table", 1, + validateNoErrors( + "SELECT COUNT(*) FILTER (WHERE name = 'Raj') OVER (PARTITION BY name ) FROM table", + 1, EXPRESSIONS); } @Test public void testAtTimeZoneExpression() throws JSQLParserException { - validateNoErrors("SELECT DATE(date1 AT TIME ZONE 'UTC' AT TIME ZONE 'australia/sydney') AS another_date FROM mytbl", 1, + validateNoErrors( + "SELECT DATE(date1 AT TIME ZONE 'UTC' AT TIME ZONE 'australia/sydney') AS another_date FROM mytbl", + 1, EXPRESSIONS); } @@ -224,9 +238,13 @@ public void testJsonFunctionExpression() throws JSQLParserException { @Test public void testJsonAggregartFunctionExpression() throws JSQLParserException { - validateNoErrors("SELECT JSON_ARRAYAGG( a FORMAT JSON ABSENT ON NULL ) FILTER( WHERE name = 'Raj' ) OVER( PARTITION BY name ) FROM mytbl", 1, + validateNoErrors( + "SELECT JSON_ARRAYAGG( a FORMAT JSON ABSENT ON NULL ) FILTER( WHERE name = 'Raj' ) OVER( PARTITION BY name ) FROM mytbl", + 1, EXPRESSIONS); - validateNoErrors("SELECT JSON_OBJECT( KEY 'foo' VALUE bar FORMAT JSON, 'foo':bar, 'foo':bar ABSENT ON NULL) FROM mytbl", 1, + validateNoErrors( + "SELECT JSON_OBJECT( KEY 'foo' VALUE bar FORMAT JSON, 'foo':bar, 'foo':bar ABSENT ON NULL) FROM mytbl", + 1, EXPRESSIONS); } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/GrantValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/GrantValidatorTest.java index b466c8ae5..d3151b303 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/GrantValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/GrantValidatorTest.java @@ -21,7 +21,8 @@ public class GrantValidatorTest extends ValidationTestAsserts { @Test public void testValidateGrant() throws JSQLParserException { - for (String sql : Arrays.asList("GRANT SELECT ON t1 TO u", "GRANT SELECT, INSERT ON t1 TO u, u2", + for (String sql : Arrays.asList("GRANT SELECT ON t1 TO u", + "GRANT SELECT, INSERT ON t1 TO u, u2", "GRANT role1 TO u, u2", "GRANT SELECT, INSERT, UPDATE, DELETE ON T1 TO ADMIN_ROLE", "GRANT ROLE_1 TO TEST_ROLE_1, TEST_ROLE_2")) { validateNoErrors(sql, 1, DatabaseType.DATABASES); @@ -30,7 +31,8 @@ public void testValidateGrant() throws JSQLParserException { @Test public void testValidateGrantNotAllowed() throws JSQLParserException { - for (String sql : Arrays.asList("GRANT SELECT ON t1 TO u", "GRANT SELECT, INSERT ON t1 TO u, u2", + for (String sql : Arrays.asList("GRANT SELECT ON t1 TO u", + "GRANT SELECT, INSERT ON t1 TO u, u2", "GRANT role1 TO u, u2", "GRANT SELECT, INSERT, UPDATE, DELETE ON T1 TO ADMIN_ROLE", "GRANT ROLE_1 TO TEST_ROLE_1, TEST_ROLE_2")) { validateNotAllowed(sql, 1, 1, FeaturesAllowed.DML, Feature.grant); diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/GroupByValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/GroupByValidatorTest.java index b8baeb20a..1a4078ce0 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/GroupByValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/GroupByValidatorTest.java @@ -25,7 +25,8 @@ public void testValidationSelectGroupBy() { @Test public void testValidationHaving() throws JSQLParserException { - String sql = "SELECT MAX(tab1.b) FROM tab1 WHERE a > 34 GROUP BY tab1.b HAVING MAX(tab1.b) > 56"; + String sql = + "SELECT MAX(tab1.b) FROM tab1 WHERE a > 34 GROUP BY tab1.b HAVING MAX(tab1.b) > 56"; validateNoErrors(sql, 1, DatabaseType.DATABASES); } @@ -34,7 +35,8 @@ public void testGroupingSets() throws JSQLParserException { for (String sql : Arrays.asList( "SELECT COL_1, COL_2, COL_3, COL_4, COL_5, COL_6 FROM TABLE_1 GROUP BY GROUPING SETS ((COL_1, COL_2, COL_3, COL_4), (COL_5, COL_6))", "SELECT COL_1 FROM TABLE_1 GROUP BY GROUPING SETS (COL_1)")) { - validateNoErrors(sql, 1, DatabaseType.ORACLE, DatabaseType.POSTGRESQL, DatabaseType.SQLSERVER); + validateNoErrors(sql, 1, DatabaseType.ORACLE, DatabaseType.POSTGRESQL, + DatabaseType.SQLSERVER); } } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/LimitValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/LimitValidatorTest.java index e90172a38..553e04758 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/LimitValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/LimitValidatorTest.java @@ -28,7 +28,8 @@ public void testValidationLimitAndOffset() throws JSQLParserException { for (String sql : Arrays.asList("SELECT * FROM mytable WHERE mytable.col = 9 LIMIT 3", "SELECT * FROM mytable WHERE mytable.col = 9 LIMIT ? OFFSET 3", "SELECT * FROM mytable WHERE mytable.col = 9 OFFSET ?")) { - validateNoErrors(sql, 1, DatabaseType.MARIADB, DatabaseType.MYSQL, DatabaseType.POSTGRESQL); + validateNoErrors(sql, 1, DatabaseType.MARIADB, DatabaseType.MYSQL, + DatabaseType.POSTGRESQL); } } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/MergeValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/MergeValidatorTest.java index ec37c4fec..ddf62f946 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/MergeValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/MergeValidatorTest.java @@ -33,7 +33,8 @@ public void testValidateMergeNotAllowed() throws JSQLParserException { for (String sql : Arrays.asList( "MERGE INTO a USING dual ON (col3 = ? AND col1 = ? AND col2 = ?) WHEN NOT MATCHED THEN INSERT (col1, col2, col3, col4) VALUES (?, ?, ?, ?) WHEN MATCHED THEN UPDATE SET col4 = col4 + ?", "MERGE INTO a USING dual ON (col3 = ? AND col1 = ? AND col2 = ?) WHEN MATCHED THEN UPDATE SET col4 = col4 + ? WHEN NOT MATCHED THEN INSERT (col1, col2, col3, col4) VALUES (?, ?, ?, ?)")) { - validateNotAllowed(sql, 1, 1, FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC), Feature.merge); + validateNotAllowed(sql, 1, 1, FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC), + Feature.merge); } } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/SetStatementValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/SetStatementValidatorTest.java index 49dbc9082..96b85493c 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/SetStatementValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/SetStatementValidatorTest.java @@ -19,8 +19,10 @@ public class SetStatementValidatorTest extends ValidationTestAsserts { @Test public void testValidateSet() throws JSQLParserException { - for (String sql : Arrays.asList("SET statement_timeout = 0; SET deferred_name_resolution true;", - "SET tester 5; SET v = 1, c = 3;", "SET standard_conforming_strings = on;SET statement_timeout = 0")) { + for (String sql : Arrays.asList( + "SET statement_timeout = 0; SET deferred_name_resolution true;", + "SET tester 5; SET v = 1, c = 3;", + "SET standard_conforming_strings = on;SET statement_timeout = 0")) { validateNoErrors(sql, 2, DatabaseType.POSTGRESQL); } } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/ShowIndexStatementValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/ShowIndexStatementValidatorTest.java index ee9469460..26b62d382 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/ShowIndexStatementValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/ShowIndexStatementValidatorTest.java @@ -19,9 +19,9 @@ import net.sf.jsqlparser.util.validation.feature.FeaturesAllowed; /** -* -* @author Jayant Kumar Yadav -*/ + * + * @author Jayant Kumar Yadav + */ public class ShowIndexStatementValidatorTest extends ValidationTestAsserts { @@ -32,11 +32,11 @@ public void testValidationShowIndex() throws Exception { } } - + @Test public void testValidationShowIndexNotAllowed() throws Exception { for (String sql : Arrays.asList("SHOW INDEX FROM mydatabase")) { validateNotAllowed(sql, 1, 1, FeaturesAllowed.DML, Feature.showIndex); } } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/ShowTablesStatementValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/ShowTablesStatementValidatorTest.java index c237ea3ab..b61bd1d8a 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/ShowTablesStatementValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/ShowTablesStatementValidatorTest.java @@ -20,16 +20,20 @@ public class ShowTablesStatementValidatorTest extends ValidationTestAsserts { @Test public void testValidationShowTables() throws Exception { - for (String sql : Arrays.asList("SHOW TABLES", "SHOW EXTENDED FULL TABLES", "SHOW EXTENDED TABLES FROM db_name", - "SHOW FULL TABLES IN db_name", "SHOW TABLES LIKE '%FOO%'", "SHOW TABLES WHERE table_name = 'FOO'")) { + for (String sql : Arrays.asList("SHOW TABLES", "SHOW EXTENDED FULL TABLES", + "SHOW EXTENDED TABLES FROM db_name", + "SHOW FULL TABLES IN db_name", "SHOW TABLES LIKE '%FOO%'", + "SHOW TABLES WHERE table_name = 'FOO'")) { validateNoErrors(sql, 1, DatabaseType.MARIADB, DatabaseType.MYSQL); } } @Test public void testValidationShowTablesNotAllowed() throws Exception { - for (String sql : Arrays.asList("SHOW TABLES", "SHOW EXTENDED FULL TABLES", "SHOW EXTENDED TABLES FROM db_name", - "SHOW FULL TABLES IN db_name", "SHOW TABLES LIKE '%FOO%'", "SHOW TABLES WHERE table_name = 'FOO'")) { + for (String sql : Arrays.asList("SHOW TABLES", "SHOW EXTENDED FULL TABLES", + "SHOW EXTENDED TABLES FROM db_name", + "SHOW FULL TABLES IN db_name", "SHOW TABLES LIKE '%FOO%'", + "SHOW TABLES WHERE table_name = 'FOO'")) { validateNotAllowed(sql, 1, 1, FeaturesAllowed.DML, Feature.showTables); } } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/UpdateValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/UpdateValidatorTest.java index bdcfd25dc..ef8564376 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/UpdateValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/UpdateValidatorTest.java @@ -27,7 +27,8 @@ public void testValidationUpdate() throws JSQLParserException { @Test public void testValidationUpdateNotAllowed() throws JSQLParserException { String sql = "UPDATE tab1 SET ref = ? WHERE id = ?;"; - validateNotAllowed(sql, 1, 1, FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC), Feature.update); + validateNotAllowed(sql, 1, 1, FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC), + Feature.update); } @Test @@ -38,13 +39,15 @@ public void testUpdateWithFrom() throws JSQLParserException { @Test public void testUpdateMultiTable() throws JSQLParserException { - String sql = "UPDATE T1, T2 SET T1.C2 = T2.C2, T2.C3 = 'UPDATED' WHERE T1.C1 = T2.C1 AND T1.C2 < 10"; + String sql = + "UPDATE T1, T2 SET T1.C2 = T2.C2, T2.C3 = 'UPDATED' WHERE T1.C1 = T2.C1 AND T1.C2 < 10"; validateNoErrors(sql, 1, DatabaseType.MYSQL, DatabaseType.MARIADB); } @Test public void testUpdateWithSelect() throws JSQLParserException { - String sql = "UPDATE mytable t1 SET (col1, col2, col3) = (SELECT a, b, c FROM mytable2 t2 WHERE t2.id = t1.id)"; + String sql = + "UPDATE mytable t1 SET (col1, col2, col3) = (SELECT a, b, c FROM mytable2 t2 WHERE t2.id = t1.id)"; validateNoErrors(sql, 1, DatabaseType.ORACLE); } @@ -56,7 +59,8 @@ public void testUpdateWithReturningAll() throws JSQLParserException { @Test public void testUpdateWithReturningList() throws JSQLParserException { - String sql = "UPDATE tablename SET col = 'thing' WHERE id = 1 RETURNING col_1, col_2, col_3"; + String sql = + "UPDATE tablename SET col = 'thing' WHERE id = 1 RETURNING col_1, col_2, col_3"; validateNoErrors(sql, 1, DatabaseType.POSTGRESQL, DatabaseType.ORACLE); } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/UseStatementValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/UseStatementValidatorTest.java index 6715d7d83..e8bf0c44f 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/UseStatementValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/UseStatementValidatorTest.java @@ -18,7 +18,8 @@ public class UseStatementValidatorTest extends ValidationTestAsserts { @Test public void testValidateUse() throws JSQLParserException { - validateNoErrors("USE my_schema", 1, DatabaseType.SQLSERVER, DatabaseType.MARIADB, DatabaseType.MYSQL); + validateNoErrors("USE my_schema", 1, DatabaseType.SQLSERVER, DatabaseType.MARIADB, + DatabaseType.MYSQL); } } diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/analytic_query02.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/analytic_query02.sql index 8fa283450..77ace598b 100644 --- a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/analytic_query02.sql +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/analytic_query02.sql @@ -19,4 +19,5 @@ select time_id, product ---@FAILURE: Encountered unexpected token: "(" "(" recorded first on Aug 3, 2021, 7:20:07 AM \ No newline at end of file +--@FAILURE: Encountered unexpected token: "(" "(" recorded first on Aug 3, 2021, 7:20:07 AM +--@FAILURE: Encountered unexpected token: "by" "BY" recorded first on Apr 6, 2024, 7:38:53 AM \ No newline at end of file diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/for_update08.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/for_update08.sql index 008209eef..ff5b7f79b 100644 --- a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/for_update08.sql +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/for_update08.sql @@ -13,4 +13,4 @@ where (nvl(su.up,'n')='n' and su.ttype=:b0) for update of su.up order by su.d ---@SUCCESSFULLY_PARSED_AND_DEPARSED first on Aug 3, 2021, 7:20:08 AM \ No newline at end of file +--@FAILURE: select su.ttype,su.cid,su.s_id,sessiontimezone from sku su where(nvl(su.up,'n')='n' and su.ttype=:b0)order by su.d for update of su.up recorded first on 20 Apr 2024, 15:59:32 \ No newline at end of file diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/object_access01.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/object_access01.sql index 11fd894ef..9a9f4b72c 100644 --- a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/object_access01.sql +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/object_access01.sql @@ -26,4 +26,5 @@ table ) t ---@FAILURE: Encountered unexpected token: "(" "(" recorded first on Aug 3, 2021, 7:20:07 AM \ No newline at end of file +--@FAILURE: Encountered unexpected token: "(" "(" recorded first on Aug 3, 2021, 7:20:07 AM +--@SUCCESSFULLY_PARSED_AND_DEPARSED first on 16 Apr 2024, 12:57:31 \ No newline at end of file diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/pivot01.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/pivot01.sql index 84954082d..5d264e46f 100644 --- a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/pivot01.sql +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/pivot01.sql @@ -15,4 +15,5 @@ select * from pivot_table --@SUCCESSFULLY_PARSED_AND_DEPARSED first on Aug 3, 2021, 7:20:08 AM ---@FAILURE: select*from pivot_tableunpivot(yearly_total for order_mode in(store as 'direct',internet as 'online'))order by year,order_mode recorded first on Jul 12, 2023, 12:58:42 PM \ No newline at end of file +--@FAILURE: select*from pivot_tableunpivot(yearly_total for order_mode in(store as 'direct',internet as 'online'))order by year,order_mode recorded first on Jul 12, 2023, 12:58:42 PM +--@FAILURE: Encountered unexpected token: "\'direct\'" recorded first on Apr 6, 2024, 7:50:18 AM \ No newline at end of file