diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000000..658fdf42de1 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @nvoxland diff --git a/.github/util/re-version.sh b/.github/util/re-version.sh index e0ce494adba..16bcaecee6f 100755 --- a/.github/util/re-version.sh +++ b/.github/util/re-version.sh @@ -43,7 +43,7 @@ mkdir -p $outdir (cd $scriptDir && javac ManifestReversion.java) #### Update jars -declare -a jars=("liquibase-0-SNAPSHOT.jar" "liquibase-0-SNAPSHOT-sources.jar" "liquibase-cdi-0-SNAPSHOT.jar" "liquibase-cdi-0-SNAPSHOT-sources.jar" "liquibase-maven-plugin-0-SNAPSHOT.jar" "liquibase-maven-plugin-0-SNAPSHOT-sources.jar") +declare -a jars=("liquibase-core-0-SNAPSHOT.jar" "liquibase-core-0-SNAPSHOT-sources.jar" "liquibase-commercial-0-SNAPSHOT.jar" "liquibase-cdi-0-SNAPSHOT.jar" "liquibase-cdi-0-SNAPSHOT-sources.jar" "liquibase-maven-plugin-0-SNAPSHOT.jar" "liquibase-maven-plugin-0-SNAPSHOT-sources.jar") for jar in "${jars[@]}" do @@ -51,14 +51,14 @@ do unzip -q $workdir/$jar META-INF/* -d $workdir java -cp $scriptDir ManifestReversion $workdir/META-INF/MANIFEST.MF $version - find $workdir/META-INF -name pom.xml -exec sed -i -e "s/0-SNAPSHOT<\/version>/$version<\/version>/" {} \; - find $workdir/META-INF -name pom.properties -exec sed -i -e "s/0-SNAPSHOT/$version/" {} \; - find $workdir/META-INF -name plugin*.xml -exec sed -i -e "s/0-SNAPSHOT<\/version>/$version<\/version>/" {} \; + find $workdir/META-INF -name pom.xml -exec sed -i -e "s/0-SNAPSHOT<\/version>/$version<\/version>/g" {} \; + find $workdir/META-INF -name pom.properties -exec sed -i -e "s/0-SNAPSHOT/$version/g" {} \; + find $workdir/META-INF -name plugin*.xml -exec sed -i -e "s/0-SNAPSHOT<\/version>/$version<\/version>/g" {} \; (cd $workdir && jar -uMf $jar META-INF) rm -rf $workdir/META-INF ## Fix up liquibase.build.properties - if [ $jar == "liquibase-0-SNAPSHOT.jar" ]; then + if [[ $jar == "liquibase-core-0-SNAPSHOT.jar" || $jar == "liquibase-commercial-0-SNAPSHOT.jar" ]]; then unzip -q $workdir/$jar liquibase.build.properties -d $workdir sed -i -e "s/build.version=.*/build.version=$version/" $workdir/liquibase.build.properties (cd $workdir && jar -uf $jar liquibase.build.properties) @@ -79,15 +79,15 @@ do done #### Update javadoc jars -declare -a javadocJars=("liquibase-0-SNAPSHOT-javadoc.jar" "liquibase-cdi-0-SNAPSHOT-javadoc.jar" "liquibase-maven-plugin-0-SNAPSHOT-javadoc.jar") +declare -a javadocJars=("liquibase-core-0-SNAPSHOT-javadoc.jar" "liquibase-cdi-0-SNAPSHOT-javadoc.jar" "liquibase-maven-plugin-0-SNAPSHOT-javadoc.jar") for jar in "${javadocJars[@]}" do mkdir $workdir/rebuild unzip -q $workdir/$jar -d $workdir/rebuild - find $workdir/rebuild -name "*.html" -exec sed -i -e "s/0-SNAPSHOT/$version/" {} \; - find $workdir/rebuild -name "*.xml" -exec sed -i -e "s/0-SNAPSHOT<\/version>/$version<\/version>/" {} \; + find $workdir/rebuild -name "*.html" -exec sed -i -e "s/0-SNAPSHOT/$version/g" {} \; + find $workdir/rebuild -name "*.xml" -exec sed -i -e "s/0-SNAPSHOT<\/version>/$version<\/version>/g" {} \; (cd $workdir/rebuild && jar -uf ../$jar *) rm -rf $workdir/rebuild @@ -132,12 +132,15 @@ done ##### update zip/tar files -cp $outdir/liquibase-$version.jar $workdir/liquibase.jar ##save versioned jar as unversioned to include in zip/tar +mkdir -p $workdir/internal/lib +cp $outdir/liquibase-core-$version.jar $workdir/internal/lib/liquibase-core.jar ##save versioned jar as unversioned to include in zip/tar +cp $outdir/liquibase-commercial-$version.jar $workdir/internal/lib/liquibase-commercial.jar ##save versioned jar as unversioned to include in zip/tar ## Extract tar.gz and rebuild it back into the tar.gz and zip mkdir $workdir/tgz-repackage (cd $workdir/tgz-repackage && tar -xzf $workdir/liquibase-0-SNAPSHOT.tar.gz) -cp $workdir/liquibase.jar $workdir/tgz-repackage/liquibase.jar +cp $workdir/internal/lib/liquibase-core.jar $workdir/tgz-repackage/internal/lib/liquibase-core.jar +cp $workdir/internal/lib/liquibase-commercial.jar $workdir/tgz-repackage/internal/lib/liquibase-commercial.jar find $workdir/tgz-repackage -name "*.txt" -exec sed -i -e "s/0-SNAPSHOT/$version/" {} \; (cd $workdir/tgz-repackage && tar -czf $outdir/liquibase-$version.tar.gz *) (cd $workdir/tgz-repackage && zip -qr $outdir/liquibase-$version.zip *) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 41009e94382..efe86711229 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -164,7 +164,7 @@ jobs: ref: ${{ github.event.pull_request.head.sha || github.event.after}} - name: Built Code Cache if: ${{ matrix.java == 8}} - uses: actions/cache@v3.0.4 + uses: actions/cache@v3.0.5 with: key: built-code-${{ github.run_number }}-${{ github.run_attempt }} path: ./**/target @@ -216,7 +216,7 @@ jobs: distribution: 'adopt' cache: 'maven' - name: Cache SonarCloud packages - uses: actions/cache@v3.0.4 + uses: actions/cache@v3.0.5 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar @@ -264,7 +264,7 @@ jobs: distribution: 'temurin' cache: 'maven' - name: Restore Built Code Cache - uses: actions/cache@v3.0.4 + uses: actions/cache@v3.0.5 with: key: built-code-${{ github.run_number }}-${{ github.run_attempt }} path: ./**/target @@ -297,14 +297,14 @@ jobs: ref: ${{ github.event.pull_request.head.sha || github.event.after}} - name: Built Code Cache - uses: actions/cache@v3.0.4 + uses: actions/cache@v3.0.5 with: key: built-code-${{ github.run_number }}-${{ github.run_attempt }} path: ./**/target ##Cache based on install4j file, since changes to JVM is seen in there. If install4j version changes without changing the file, change the prefix letter before hashFiles to force a new cache - name: Install4j Cache - uses: actions/cache@v3.0.4 + uses: actions/cache@v3.0.5 with: key: install4j-A${{ hashFiles('liquibase-dist/src/main/install4j/liquibase.install4j') }} path: ~/.install4j8/** @@ -320,22 +320,22 @@ jobs: env: GPG_PASSWORD: ${{ secrets.GPG_PASSPHRASE }} - - name: Download liquibase-pro + - name: Download liquibase-commercial uses: liquibase/action-download-artifact@v2-liquibase with: github_token: ${{ secrets.BOT_TOKEN }} workflow: build.yml workflow_conclusion: success branch: "${{ needs.setup.outputs.proBranchName }}" - name: liquibase-pro-modules - path: download/liquibase-pro + name: liquibase-commercial-modules + path: download/liquibase-commercial repo: liquibase/liquibase-pro - name: Install Built Modules run: | (find . -name *-SNAPSHOT.jar -exec mvn -B org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile={} \;) (find . -name *-SNAPSHOT-sources.jar -exec mvn -B org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dclassifier=sources -Dfile={} \;) - mvn -B org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=download/liquibase-pro/liquibase-pro-0-SNAPSHOT.jar + mvn -B org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=download/liquibase-commercial/liquibase-commercial-0-SNAPSHOT.jar - name: Build & Sign Artifacts env: @@ -355,7 +355,7 @@ jobs: echo "Saving windows key" echo "$INSTALL4J_WINDOWS_KEY" | base64 -d > liquibase-dist/target/keys/datical_windows.pfx - mvn -B -pl liquibase-dist -P liquibase-pro source:jar package + mvn -B -pl liquibase-dist -P liquibase-commercial source:jar package ## extract tar content for other artifacts mkdir -p liquibase-dist/target/liquibase-0-SNAPSHOT @@ -372,8 +372,11 @@ jobs: mkdir -p artifacts cp liquibase-dist/target/liquibase-0-SNAPSHOT.tar.gz artifacts cp liquibase-dist/target/liquibase-0-SNAPSHOT.zip artifacts - cp liquibase-dist/target/liquibase-0-SNAPSHOT.jar artifacts - cp liquibase-dist/target/liquibase-0-SNAPSHOT-sources.jar artifacts + + cp liquibase-dist/target/liquibase-0-SNAPSHOT.jar artifacts/liquibase-core-0-SNAPSHOT.jar + cp liquibase-dist/target/liquibase-0-SNAPSHOT-sources.jar artifacts/liquibase-core-0-SNAPSHOT-sources.jar + cp target/liquibase-0-SNAPSHOT-javadoc.jar artifacts/liquibase-core-0-SNAPSHOT-javadoc.jar + cp liquibase-dist/target/liquibase-*-installer-* artifacts cp liquibase-maven-plugin/target/liquibase-maven-plugin-0-SNAPSHOT.jar artifacts @@ -383,19 +386,29 @@ jobs: cp liquibase-cdi/target/liquibase-cdi-0-SNAPSHOT.jar artifacts cp liquibase-cdi/target/liquibase-cdi-0-SNAPSHOT-sources.jar artifacts cp liquibase-cdi/target/liquibase-cdi-0-SNAPSHOT-javadoc.jar artifacts + + + echo "Source code not available for liquibase-commercial" > /tmp/readme.source.txt + (cd /tmp && jar cf liquibase-commercial-0-SNAPSHOT-sources.jar readme.source.txt) - cp target/liquibase-0-SNAPSHOT-javadoc.jar artifacts + echo "Javadocs not available for liquibase-commercial" > /tmp/readme.javadocs.txt + (cd /tmp && jar cf liquibase-commercial-0-SNAPSHOT-javadoc.jar readme.javadocs.txt) + + cp download/liquibase-commercial/liquibase-commercial-0-SNAPSHOT.jar artifacts + cp /tmp/liquibase-commercial-0-SNAPSHOT-sources.jar artifacts + cp /tmp/liquibase-commercial-0-SNAPSHOT-javadoc.jar artifacts .github/util/sign-artifacts.sh artifacts ##prepare branch-named convenience artifacts directories mkdir artifacts-named cp liquibase-dist/target/liquibase-0-SNAPSHOT.tar.gz artifacts-named/liquibase-${{ needs.setup.outputs.thisBranchFileName }}.tar.gz - cp liquibase-dist/target/liquibase-0-SNAPSHOT.jar artifacts-named/liquibase-${{ needs.setup.outputs.thisBranchFileName }}.jar + cp liquibase-dist/target/liquibase-0-SNAPSHOT.jar artifacts-named/liquibase-core-${{ needs.setup.outputs.thisBranchFileName }}.jar cp liquibase-maven-plugin/target/liquibase-maven-plugin-0-SNAPSHOT.jar artifacts-named/liquibase-maven-plugin-${{ needs.setup.outputs.thisBranchFileName }}.jar cp liquibase-cdi/target/liquibase-cdi-0-SNAPSHOT.jar artifacts-named/liquibase-cdi-${{ needs.setup.outputs.thisBranchFileName }}.jar cp liquibase-extension-testing/target/liquibase-extension-testing-0-SNAPSHOT.jar artifacts-named/liquibase-extension-testing-${{ needs.setup.outputs.thisBranchFileName }}.jar cp liquibase-extension-testing/target/liquibase-extension-testing-0-SNAPSHOT-deps.jar artifacts-named/liquibase-extension-testing-${{ needs.setup.outputs.thisBranchFileName }}-deps.jar + cp download/liquibase-commercial/liquibase-commercial-0-SNAPSHOT.jar artifacts-named/liquibase-commercial-${{ needs.setup.outputs.thisBranchFileName }}.jar - name: Archive Packages uses: actions/upload-artifact@v3 @@ -474,7 +487,7 @@ jobs: } if (failedCheckingUs) { - console.log("Rerun liquibase-pro that was waiting on us"); + console.log("Rerun liquibase-commercial that was waiting on us"); //octokit removed the retryWorkflow function github.request("POST "+currentBranchInfo.runRerunUrl); diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index fc2ac85a069..7e6850d854e 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -73,7 +73,8 @@ jobs: .github/util/sign-artifacts.sh re-version/out mkdir re-version/final - mv re-version/out/liquibase-${{ needs.setup.outputs.version }}.jar re-version/final + mv re-version/out/liquibase-core-${{ needs.setup.outputs.version }}.jar re-version/final + mv re-version/out/liquibase-commercial-${{ needs.setup.outputs.version }}.jar re-version/final mv re-version/out/liquibase-${{ needs.setup.outputs.version }}.tar.gz re-version/final mv re-version/out/liquibase-${{ needs.setup.outputs.version }}.zip re-version/final @@ -81,7 +82,7 @@ jobs: mv re-version/out/liquibase-additional-${{ needs.setup.outputs.version }}.zip re-version/final - name: Cache Completed Artifacts - uses: actions/cache@v3.0.4 + uses: actions/cache@v3.0.5 with: key: completed-artifacts-${{ github.run_number }}-${{ github.run_attempt }} path: re-version/final @@ -102,7 +103,7 @@ jobs: - uses: actions/checkout@v3 - name: Restore Completed Artifacts - uses: actions/cache@v3.0.4 + uses: actions/cache@v3.0.5 with: key: completed-artifacts-${{ github.run_number }}-${{ github.run_attempt }} path: re-version/final diff --git a/.github/workflows/release-published.yml b/.github/workflows/release-published.yml index 29624390e0b..64d47baefec 100644 --- a/.github/workflows/release-published.yml +++ b/.github/workflows/release-published.yml @@ -73,13 +73,12 @@ jobs: unzip liquibase-additional-*.zip ##extracts and sign poms - unzip -j liquibase-${version}.jar META-INF/maven/org.liquibase/liquibase-core/pom.xml - mv pom.xml liquibase-${version}.pom - gpg --batch --pinentry-mode=loopback --passphrase "$GPG_PASSWORD" -ab liquibase-${version}.pom + unzip -j liquibase-core-${version}.jar META-INF/maven/org.liquibase/liquibase-core/pom.xml + mv pom.xml liquibase-core-${version}.pom + gpg --batch --pinentry-mode=loopback --passphrase "$GPG_PASSWORD" -ab liquibase-core-${version}.pom unzip -j liquibase-maven-plugin-${version}.jar META-INF/maven/org.liquibase/liquibase-maven-plugin/pom.xml mv pom.xml liquibase-maven-plugin-${version}.pom - sed -i -e "s//Liquibase Maven Plugin<\/name>/" liquibase-maven-plugin-${version}.pom ## name didn't end up in pom. Hack it in for now gpg --batch --pinentry-mode=loopback --passphrase "$GPG_PASSWORD" -ab liquibase-maven-plugin-${version}.pom unzip -j liquibase-cdi-${version}.jar META-INF/maven/org.liquibase/liquibase-cdi/pom.xml @@ -87,15 +86,32 @@ jobs: sed -i -e "s//Liquibase CDI Plugin<\/name>/" liquibase-cdi-${version}.pom ## name didn't end up in pom. Hack it in for now gpg --batch --pinentry-mode=loopback --passphrase "$GPG_PASSWORD" -ab liquibase-cdi-${version}.pom + unzip -j liquibase-commercial-${version}.jar META-INF/maven/org.liquibase/liquibase-commercial/pom.xml + mv pom.xml liquibase-commercial-${version}.pom + sed -i -e "s/<\/licenses>/<\/licenses>private<\/connection>private<\/developerConnection>private<\/url><\/scm>/" liquibase-commercial-${version}.pom ## scm info not in the pom + gpg --batch --pinentry-mode=loopback --passphrase "$GPG_PASSWORD" -ab liquibase-commercial-${version}.pom + mvn -B org.apache.maven.plugins:maven-deploy-plugin:3.0.0-M1:deploy-file \ -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ \ -DrepositoryId=sonatype-nexus-staging \ - -DpomFile=liquibase-${version}.pom \ + -DpomFile=liquibase-core-${version}.pom \ -DgeneratePom=false \ - -Dfile=liquibase-${version}.jar \ - -Dsources=liquibase-${version}-sources.jar \ - -Djavadoc=liquibase-${version}-javadoc.jar \ - -Dfiles=liquibase-${version}.jar.asc,liquibase-${version}-sources.jar.asc,liquibase-${version}-javadoc.jar.asc,liquibase-${version}.pom.asc \ + -Dfile=liquibase-core-${version}.jar \ + -Dsources=liquibase-core-${version}-sources.jar \ + -Djavadoc=liquibase-core-${version}-javadoc.jar \ + -Dfiles=liquibase-core-${version}.jar.asc,liquibase-core-${version}-sources.jar.asc,liquibase-core-${version}-javadoc.jar.asc,liquibase-core-${version}.pom.asc \ + -Dtypes=jar.asc,jar.asc,jar.asc,pom.asc \ + -Dclassifiers=,sources,javadoc, + + mvn -B org.apache.maven.plugins:maven-deploy-plugin:3.0.0-M1:deploy-file \ + -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ \ + -DrepositoryId=sonatype-nexus-staging \ + -DpomFile=liquibase-commercial-${version}.pom \ + -DgeneratePom=false \ + -Dfile=liquibase-commercial-${version}.jar \ + -Dsources=liquibase-commercial-${version}-sources.jar \ + -Djavadoc=liquibase-commercial-${version}-javadoc.jar \ + -Dfiles=liquibase-commercial-${version}.jar.asc,liquibase-commercial-${version}-sources.jar.asc,liquibase-commercial-${version}-javadoc.jar.asc,liquibase-commercial-${version}.pom.asc \ -Dtypes=jar.asc,jar.asc,jar.asc,pom.asc \ -Dclassifiers=,sources,javadoc, diff --git a/changelog.txt b/changelog.txt index 408aae6f067..d42f8a57e9b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,68 @@ Liquibase Core Changelog =========================================== +Changes in version 4.14.0 (2022.07.26) + +## Notable Changes +* Split liquibase-core and liquibase-commercial jar files by @nvoxland in https://github.com/liquibase/liquibase/pull/3050 +* Added liquibase.changelogParseMode setting by @nvoxland in https://github.com/liquibase/liquibase/pull/3057 + +## Enhancements +* Warn if XSD version does not match build version in validate command (DAT-9874) by @StevenMassaro in https://github.com/liquibase/liquibase/pull/3016 +* Allow use of pro-only objects for filtering with generateChangeLog (DAT-9542) by @StevenMassaro in https://github.com/liquibase/liquibase/pull/3068 +* Improve connection exception by including underlying driver exception trace by @hessjcg in https://github.com/liquibase/liquibase/pull/3033 +* Add Closeable/AutoCloseable interface to liquibase.database.Database by @zorglube in https://github.com/liquibase/liquibase/pull/2990 + +## Fixes + +* Fixed Formatted SQL "property" parsing by @nvoxland in https://github.com/liquibase/liquibase/pull/3037 +* Ensure Postgresql search_path entries are quoted correctly by @nvoxland in https://github.com/liquibase/liquibase/pull/3009 +* Updated "Change Set" wording to "Changeset" by @kataggart in https://github.com/liquibase/liquibase/pull/3042 +* Improved error when JAVA_HOME is set to invalid value (DAT-10545) by @StevenMassaro in https://github.com/liquibase/liquibase/pull/3074 +* Fixed autoIncrement incrementBy/startWith support in MySQL, H2, HSQLDB, and MariaDB by @tozogabee in https://github.com/liquibase/liquibase/pull/3026 +* Improve renameColumn generated SQL on mssql by @mide25 in https://github.com/liquibase/liquibase/pull/783 + +### JDBC Driver and Third-Party Library Updates + +* Upgraded mariadb-java-client from 3.0.5 to 3.0.6 by @dependabot in https://github.com/liquibase/liquibase/pull/3021 +* Upgraded testcontainers-bom from 1.17.2 to 1.17.3 by @dependabot in https://github.com/liquibase/liquibase/pull/3020 +* Upgraded postgresql from 42.3.4 to 42.4.0 by @dependabot in https://github.com/liquibase/liquibase/pull/2935 +* Bump jaxb-runtime from 2.3.6 to 4.0.0 by @dependabot in https://github.com/liquibase/liquibase/pull/2964 + +Changes in version 4.13.0 (2022.07.07) + +## Enhancements +* Added new liquibase.duplicateFileMode setting by @nvoxland in https://github.com/liquibase/liquibase/pull/3006 +* Add additional info in CLI's --version output by @nvoxland in https://github.com/liquibase/liquibase/pull/2942 +* Added support for new "searchPath" global configuration by @nvoxland in https://github.com/liquibase/liquibase/pull/2917 + +## Fixes +* Hide CommandFailedException stacktrace when thrown to set exit code (DAT-9608) by @StevenMassaro in https://github.com/liquibase/liquibase/pull/2938 +* Update copyright year in txt files; also update links in txt files (DAT-10261) by @StevenMassaro in https://github.com/liquibase/liquibase/pull/2955 +* add support for default-catalog-name in SQL Server (DAT-10484) by @StevenMassaro in https://github.com/liquibase/liquibase/pull/2940 +* Make additional query for more column information for MariaDB DAT-8693 by @wwillard7800 in https://github.com/liquibase/liquibase/pull/2898 +* Include should fail if a parser cannot be found for the specified file by @nvoxland in https://github.com/liquibase/liquibase/pull/2972 +* Improved postgresql prepared statement performance by @nvoxland in https://github.com/liquibase/liquibase/pull/2914 +* Cleanup relative paths preventing sql files being found by the class loader by @marcsowen in https://github.com/liquibase/liquibase/pull/2932 +* Fix missing attributes in serialization by @tms-91 in https://github.com/liquibase/liquibase/pull/2585 +* Improved parsing of single-quoted strings by @nvoxland in https://github.com/liquibase/liquibase/pull/2949 +* DAT-10260: add outputFile argument in maven plugin for checks.run target by @StevenMassaro in https://github.com/liquibase/liquibase/pull/2975 +* Formatted SQL files with uppercase in the liquibase attributes (DAT-10531) by @abrackx in https://github.com/liquibase/liquibase/pull/2985 +* handle empty or null input to stripComments method (DAT-10296) by @StevenMassaro in https://github.com/liquibase/liquibase/pull/2970 +* Fixed issue with parameter expression parsing by @nvoxland in https://github.com/liquibase/liquibase/pull/2984 +* Fixed before/after/at column arguments in addColumn by @nvoxland in https://github.com/liquibase/liquibase/pull/2943 +* Adds liquibase.psql.conf example (DAT-10303) by @abrackx in https://github.com/liquibase/liquibase/pull/2939 +* [DAT-10093] added schema escaping to getColumns call to jdbc metadata classes by @KushnirykOleh in https://github.com/liquibase/liquibase/pull/2895 +* Use "numeric" (without parameters) data type in PostgreSQL by @LonwoLonwo in https://github.com/liquibase/liquibase/pull/1906 +* Force "json" resultset formats in Snowflake when running Java 17+ by @nvoxland in https://github.com/liquibase/liquibase/pull/3019 + +## JDBC Driver and Third-Party Library Updates +* Upgraded jaxb-core from 2.3.0.1 to 4.0.0 by @dependabot in https://github.com/liquibase/liquibase/pull/2962 +* Upgraded snowflake-jdbc from 3.13.19 to 3.13.20 by @dependabot in https://github.com/liquibase/liquibase/pull/3001 +* Upgraded mariadb-java-client from 3.0.4 to 3.0.5 by @dependabot in https://github.com/liquibase/liquibase/pull/2881 +* Upgraded ojdbc8 from 21.5.0.0 to 21.6.0.0.1 by @dependabot in https://github.com/liquibase/liquibase/pull/2987 +* Upgraded h2 from 2.1.212 to 2.1.214 by @dependabot in https://github.com/liquibase/liquibase/pull/2944 + Changes in version 4.12.0 (2022.06.16) ## Enhancements diff --git a/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseCommandLine.java b/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseCommandLine.java index 2cfe6f1311d..fabe9375e3f 100644 --- a/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseCommandLine.java +++ b/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseCommandLine.java @@ -1142,7 +1142,7 @@ public String[] getVersion() throws Exception { continue; } final File file = new File(url.toURI()); - if (file.getName().equals("liquibase.jar")) { + if (file.getName().equals("liquibase-core.jar")) { continue; } if (file.exists() && file.getName().toLowerCase().endsWith(".jar")) { @@ -1195,9 +1195,11 @@ private LibraryInfo getLibraryInfo(File pathEntryFile) throws IOException { libraryInfo.file = pathEntryFile; final Manifest manifest = jarFile.getManifest(); - libraryInfo.name = getValue(manifest, "Bundle-Name", "Implementation-Title", "Specification-Title"); - libraryInfo.version = getValue(manifest, "Bundle-Version", "Implementation-Version", "Specification-Version"); - libraryInfo.vendor = getValue(manifest, "Bundle-Vendor", "Implementation-Vendor", "Specification-Vendor"); + if (manifest != null) { + libraryInfo.name = getValue(manifest, "Bundle-Name", "Implementation-Title", "Specification-Title"); + libraryInfo.version = getValue(manifest, "Bundle-Version", "Implementation-Version", "Specification-Version"); + libraryInfo.vendor = getValue(manifest, "Bundle-Vendor", "Implementation-Vendor", "Specification-Vendor"); + } if (libraryInfo.name == null) { libraryInfo.name = pathEntryFile.getName().replace(".jar", ""); diff --git a/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseLauncher.java b/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseLauncher.java index ac56d997914..2783e7fd216 100644 --- a/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseLauncher.java +++ b/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseLauncher.java @@ -24,6 +24,12 @@ public static void main(final String[] args) throws Exception { debug("Debug mode enabled because LIQUIBASE_LAUNCHER_DEBUG is set to " + debugSetting); } + String parentLoaderSetting = System.getenv("LIQUIBASE_LAUNCHER_PARENT_CLASSLOADER"); + if (parentLoaderSetting == null) { + parentLoaderSetting = "system"; + } + debug("LIQUIBASE_LAUNCHER_PARENT_CLASSLOADER is set to " + parentLoaderSetting); + final String liquibaseHomeEnv = System.getenv("LIQUIBASE_HOME"); debug("LIQUIBASE_HOME: " + liquibaseHomeEnv); if (liquibaseHomeEnv == null || liquibaseHomeEnv.equals("")) { @@ -32,7 +38,7 @@ public static void main(final String[] args) throws Exception { File liquibaseHome = new File(liquibaseHomeEnv); List urls = new ArrayList<>(); - urls.add(new File(liquibaseHome, "liquibase.jar").toURI().toURL()); + urls.add(new File(liquibaseHome, "internal/lib/liquibase-core.jar").toURI().toURL()); //make sure liquibase-core.jar is first in the list File[] libDirs = new File[]{ new File("./liquibase_libs"), @@ -54,7 +60,7 @@ public static void main(final String[] args) throws Exception { } for (File lib : files) { - if (lib.getName().toLowerCase(Locale.US).endsWith(".jar")) { + if (lib.getName().toLowerCase(Locale.US).endsWith(".jar") && !lib.getName().toLowerCase(Locale.US).equals("liquibase-core.jar")) { try { urls.add(lib.toURI().toURL()); debug("Added " + lib.getAbsolutePath() + " to classpath"); @@ -80,10 +86,20 @@ public static void main(final String[] args) throws Exception { } } - //loading with the regular system classloader includes liquibase.jar in the parent. - //That causes the parent classloader to load LiqiuabaseCommandLine which makes it not able to access files in the child classloader - //The system classloader's parent is the boot classloader, which keeps the only classloader with liquibase.jar the same as the rest of the classes it needs to access. - final URLClassLoader classloader = new URLClassLoader(urls.toArray(new URL[0]), ClassLoader.getSystemClassLoader().getParent()); + ClassLoader parentLoader; + if (parentLoaderSetting.equalsIgnoreCase("system")) { + //loading with the regular system classloader includes liquibase.jar in the parent. + //That causes the parent classloader to load LiquibaseCommandLine which makes it not able to access files in the child classloader + //The system classloader's parent is the boot classloader, which keeps the only classloader with liquibase-core.jar the same as the rest of the classes it needs to access. + parentLoader = ClassLoader.getSystemClassLoader().getParent(); + + } else if (parentLoaderSetting.equalsIgnoreCase("thread")) { + parentLoader = Thread.currentThread().getContextClassLoader(); + } else { + throw new RuntimeException("Unknown LIQUIBASE_LAUNCHER_PARENT_CLASSLOADER value: "+parentLoaderSetting); + } + + final URLClassLoader classloader = new URLClassLoader(urls.toArray(new URL[0]), parentLoader); Thread.currentThread().setContextClassLoader(classloader); final Class cli = classloader.loadClass(LiquibaseCommandLine.class.getName()); diff --git a/liquibase-core/pom.xml b/liquibase-core/pom.xml index f87331372b3..a7a2226f57c 100644 --- a/liquibase-core/pom.xml +++ b/liquibase-core/pom.xml @@ -132,7 +132,7 @@ net.java.dev.javacc javacc - 7.0.11 + 7.0.12 diff --git a/liquibase-core/src/main/java/liquibase/Liquibase.java b/liquibase-core/src/main/java/liquibase/Liquibase.java index 46d6e6bbf6b..a7259aae140 100644 --- a/liquibase-core/src/main/java/liquibase/Liquibase.java +++ b/liquibase-core/src/main/java/liquibase/Liquibase.java @@ -33,6 +33,7 @@ import liquibase.logging.core.CompositeLogService; import liquibase.parser.ChangeLogParser; import liquibase.parser.ChangeLogParserFactory; +import liquibase.parser.core.xml.XMLChangeLogSAXParser; import liquibase.resource.InputStreamList; import liquibase.resource.ResourceAccessor; import liquibase.serializer.ChangeLogSerializer; @@ -361,8 +362,21 @@ public Connection getConnection(DatabaseChangeLog changeLog) throws LiquibaseHub public DatabaseChangeLog getDatabaseChangeLog() throws LiquibaseException { + return getDatabaseChangeLog(false); + } + + /** + * @param shouldWarnOnMismatchedXsdVersion When set to true, a warning will be printed to the console if the XSD + * version used does not match the version of Liquibase. If "latest" is used + * as the XSD version, no warning is printed. If the changelog is not xml + * format, no warning is printed. + */ + private DatabaseChangeLog getDatabaseChangeLog(boolean shouldWarnOnMismatchedXsdVersion) throws LiquibaseException { if (databaseChangeLog == null && changeLogFile != null) { ChangeLogParser parser = ChangeLogParserFactory.getInstance().getParser(changeLogFile, resourceAccessor); + if (parser instanceof XMLChangeLogSAXParser) { + ((XMLChangeLogSAXParser) parser).setShouldWarnOnMismatchedXsdVersion(shouldWarnOnMismatchedXsdVersion); + } databaseChangeLog = parser.parse(changeLogFile, changeLogParameters, resourceAccessor); } @@ -495,7 +509,7 @@ public void run() throws Exception { // // Create an iterator which will be used with a ListVisitor - // to grab the list of change sets for the update + // to grab the list of changesets for the update // ChangeLogIterator listLogIterator = new ChangeLogIterator(changeLog, new ShouldRunChangeSetFilter(database), @@ -612,7 +626,7 @@ public void run() throws Exception { // // Create an iterator which will be used with a ListVisitor - // to grab the list of change sets for the update + // to grab the list of changesets for the update // List ranChangeSetList = database.getRanChangeSetList(); ChangeLogIterator listLogIterator = new ChangeLogIterator(changeLog, @@ -691,7 +705,7 @@ public void run() throws Exception { /* We have no other choice than to save the current Executer here. */ @SuppressWarnings("squid:S1941") Executor oldTemplate = getAndReplaceJdbcExecutor(output); - outputHeader("Update " + changesToApply + " Change Sets Database Script"); + outputHeader("Update " + changesToApply + " Changesets Database Script"); update(changesToApply, contexts, labelExpression); @@ -868,7 +882,7 @@ public void run() throws Exception { // // Create an iterator which will be used with a ListVisitor - // to grab the list of change sets for the update + // to grab the list of changesets for the update // ChangeLogIterator listLogIterator = new ChangeLogIterator(database.getRanChangeSetList(), changeLog, new AlreadyRanChangeSetFilter(database.getRanChangeSetList()), @@ -1140,7 +1154,7 @@ public void run() throws Exception { // // Create an iterator which will be used with a ListVisitor - // to grab the list of change sets for the update + // to grab the list of changesets for the update // List ranChangeSetList = database.getRanChangeSetList(); ChangeLogIterator listLogIterator = new ChangeLogIterator(ranChangeSetList, changeLog, @@ -1308,7 +1322,7 @@ public void run() throws Exception { // // Create an iterator which will be used with a ListVisitor - // to grab the list of change sets for the update + // to grab the list of changesets for the update // List ranChangeSetList = database.getRanChangeSetList(); ChangeLogIterator listLogIterator = new ChangeLogIterator(ranChangeSetList, changeLog, @@ -1466,7 +1480,7 @@ public void run() throws Exception { // // Create an iterator which will be used with a ListVisitor - // to grab the list of change sets for the update + // to grab the list of changesets for the update // ChangeLogIterator listLogIterator = buildChangeLogIterator(tag, changeLog, contexts, labelExpression); @@ -2056,7 +2070,7 @@ public void reportStatus(boolean verbose, Contexts contexts, LabelExpression lab out.append(StreamUtil.getLineSeparator()); } else { out.append(String.valueOf(unrunChangeSets.size())); - out.append(" change sets have not been applied to "); + out.append(" changesets have not been applied to "); out.append(getDatabase().getConnection().getConnectionUserName()); out.append("@"); out.append(getDatabase().getConnection().getURL()); @@ -2273,7 +2287,7 @@ public DiffResult diff(Database referenceDatabase, Database targetDatabase, Comp */ public void validate() throws LiquibaseException { - DatabaseChangeLog changeLog = getDatabaseChangeLog(); + DatabaseChangeLog changeLog = getDatabaseChangeLog(true); changeLog.validate(database); } diff --git a/liquibase-core/src/main/java/liquibase/change/core/CreateProcedureChange.java b/liquibase-core/src/main/java/liquibase/change/core/CreateProcedureChange.java index 5ec926372be..893000016ad 100644 --- a/liquibase-core/src/main/java/liquibase/change/core/CreateProcedureChange.java +++ b/liquibase-core/src/main/java/liquibase/change/core/CreateProcedureChange.java @@ -7,6 +7,7 @@ import liquibase.database.Database; import liquibase.database.DatabaseList; import liquibase.database.core.*; +import liquibase.exception.DatabaseException; import liquibase.exception.UnexpectedLiquibaseException; import liquibase.exception.ValidationErrors; import liquibase.statement.SqlStatement; @@ -344,6 +345,7 @@ public String getSerializedObjectNamespace() { return STANDARD_CHANGELOG_NAMESPACE; } + @SuppressWarnings("java:S2095") @Override protected Map createExampleValueMetaData( String parameterName, DatabaseChangeProperty changePropertyAnnotation) { diff --git a/liquibase-core/src/main/java/liquibase/change/core/LoadDataChange.java b/liquibase-core/src/main/java/liquibase/change/core/LoadDataChange.java index 253f68a7720..19ccb310650 100644 --- a/liquibase-core/src/main/java/liquibase/change/core/LoadDataChange.java +++ b/liquibase-core/src/main/java/liquibase/change/core/LoadDataChange.java @@ -484,7 +484,7 @@ public SqlStatement[] generateStatements(Database database) { } catch (UnexpectedLiquibaseException ule) { if ((getChangeSet() != null) && (getChangeSet().getFailOnError() != null) && !getChangeSet() .getFailOnError()) { - LOG.info("Change set " + getChangeSet().toString(false) + + LOG.info("Changeset " + getChangeSet().toString(false) + " failed, but failOnError was false. Error: " + ule.getMessage()); return new SqlStatement[0]; } else { diff --git a/liquibase-core/src/main/java/liquibase/change/custom/CustomChange.java b/liquibase-core/src/main/java/liquibase/change/custom/CustomChange.java index 0a0f03fa953..d45fba550f9 100644 --- a/liquibase-core/src/main/java/liquibase/change/custom/CustomChange.java +++ b/liquibase-core/src/main/java/liquibase/change/custom/CustomChange.java @@ -9,7 +9,7 @@ * Interface to implement when creating a custom change. Actual custom changes implementations need to * implement CustomSqlChange or CustomTaskChange. *

- * See http://www.liquibase.org/documentation/changes/custom_change.html for more information. + * See https://docs.liquibase.com/change-types/custom-change.html for more information. */ public interface CustomChange { diff --git a/liquibase-core/src/main/java/liquibase/change/custom/CustomChangeWrapper.java b/liquibase-core/src/main/java/liquibase/change/custom/CustomChangeWrapper.java index 59a6696660f..555ff3e6140 100644 --- a/liquibase-core/src/main/java/liquibase/change/custom/CustomChangeWrapper.java +++ b/liquibase-core/src/main/java/liquibase/change/custom/CustomChangeWrapper.java @@ -28,7 +28,7 @@ " want to create your own custom refactoring class.\n" + "\n" + "To create your own custom refactoring, simply create a class that implements the liquibase.change.custom.CustomSqlChange " + - "or liquibase.change.custom.CustomTaskChange interface and use the tag in your change set.\n" + + "or liquibase.change.custom.CustomTaskChange interface and use the tag in your changeset.\n" + "\n" + "If your change can be rolled back, implement the liquibase.change.custom.CustomSqlRollback interface as well.\n" + "\n" + diff --git a/liquibase-core/src/main/java/liquibase/change/custom/CustomSqlChange.java b/liquibase-core/src/main/java/liquibase/change/custom/CustomSqlChange.java index a46a4349f0c..c5b7fbd787a 100644 --- a/liquibase-core/src/main/java/liquibase/change/custom/CustomSqlChange.java +++ b/liquibase-core/src/main/java/liquibase/change/custom/CustomSqlChange.java @@ -9,7 +9,7 @@ * implementing this interface is preferred over CustomTaskChange because the SQL can either be executed * directly or saved to a text file for later use depending on the migration mode used. To allow * the change to be rolled back, also implement the CustomSqlRollback interface. If your change requires sql-based - * logic and non-sql-based logic, it is best to create a change set that contains a mix of CustomSqlChange and CustomTaskChange calls. + * logic and non-sql-based logic, it is best to create a changeset that contains a mix of CustomSqlChange and CustomTaskChange calls. * * @see liquibase.change.custom.CustomSqlRollback * @see liquibase.change.custom.CustomTaskChange diff --git a/liquibase-core/src/main/java/liquibase/change/custom/CustomTaskChange.java b/liquibase-core/src/main/java/liquibase/change/custom/CustomTaskChange.java index eabf50d148b..230e57bc44c 100644 --- a/liquibase-core/src/main/java/liquibase/change/custom/CustomTaskChange.java +++ b/liquibase-core/src/main/java/liquibase/change/custom/CustomTaskChange.java @@ -8,7 +8,7 @@ * If you are updating a database through SQL, implementing CustomSqlChange is preferred because the SQL can either be executed * directly or saved to a text file for later use depending on the migration mode used. * To allow the change to be rolled back, also implement the CustomTaskRollback interface. - * If your change requires sql-based logic and non-sql-based logic, it is best to create a change set that contains a mix of CustomSqlChange and CustomTaskChange calls. + * If your change requires sql-based logic and non-sql-based logic, it is best to create a changeset that contains a mix of CustomSqlChange and CustomTaskChange calls. * * @see liquibase.change.custom.CustomTaskRollback * @see liquibase.change.custom.CustomSqlChange diff --git a/liquibase-core/src/main/java/liquibase/change/custom/package-info.java b/liquibase-core/src/main/java/liquibase/change/custom/package-info.java index 05260d67ab8..405c92b17de 100644 --- a/liquibase-core/src/main/java/liquibase/change/custom/package-info.java +++ b/liquibase-core/src/main/java/liquibase/change/custom/package-info.java @@ -4,7 +4,7 @@ *

* To create your own custom refactoring, simply create a class that implements the * {@link liquibase.change.custom.CustomSqlChange} or {@link liquibase.change.custom.CustomTaskChange} interface and - * use the <custom> tag in your change set.

+ * use the <custom> tag in your changeset.

*

* If your change can be rolled back, implement the {@link liquibase.change.custom.CustomSqlRollback} interface as * well.

diff --git a/liquibase-core/src/main/java/liquibase/changelog/AbstractChangeLogHistoryService.java b/liquibase-core/src/main/java/liquibase/changelog/AbstractChangeLogHistoryService.java index 1e3313e78fb..944d4ea93eb 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/AbstractChangeLogHistoryService.java +++ b/liquibase-core/src/main/java/liquibase/changelog/AbstractChangeLogHistoryService.java @@ -100,7 +100,7 @@ public Date getRanDate(ChangeSet changeSet) throws DatabaseException, DatabaseHi /** * - * Return the last deployment ID from the change sets that have been run or null + * Return the last deployment ID from the changesets that have been run or null * * @return String * @throws DatabaseException diff --git a/liquibase-core/src/main/java/liquibase/changelog/ChangeLogIterator.java b/liquibase-core/src/main/java/liquibase/changelog/ChangeLogIterator.java index 99eff31804a..8c5addba7a5 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/ChangeLogIterator.java +++ b/liquibase-core/src/main/java/liquibase/changelog/ChangeLogIterator.java @@ -93,7 +93,7 @@ public void run() throws Exception { Scope.child(Scope.Attr.changeSet.name(), changeSet, () -> { if (finalShouldVisit && !alreadySaw(changeSet)) { // - // Go validate any change sets with an Executor if + // Go validate any changesets with an Executor if // we are using a ValidatingVisitor // if (visitor instanceof ValidatingVisitor) { @@ -103,7 +103,7 @@ public void run() throws Exception { // // Execute the visit call in its own scope with a new // CompositeLogService and BufferLogService in order - // to capture the logging for just this change set. The + // to capture the logging for just this changeset. The // log is sent to Hub if available // Map values = new HashMap<>(); @@ -131,8 +131,8 @@ public void run() throws Exception { // - // Make sure that any change set which has a runWith= setting - // has a valid Executor, and that the changes in the change set + // Make sure that any changeset which has a runWith= setting + // has a valid Executor, and that the changes in the changeset // are eligible for execution by this Executor // private void validateChangeSetExecutor(ChangeSet changeSet, RuntimeEnvironment env) throws LiquibaseException { diff --git a/liquibase-core/src/main/java/liquibase/changelog/ChangeSet.java b/liquibase-core/src/main/java/liquibase/changelog/ChangeSet.java index c653415aaad..c62849f8845 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/ChangeSet.java +++ b/liquibase-core/src/main/java/liquibase/changelog/ChangeSet.java @@ -1,6 +1,7 @@ package liquibase.changelog; import liquibase.ContextExpression; +import liquibase.GlobalConfiguration; import liquibase.Labels; import liquibase.Scope; import liquibase.change.*; @@ -16,6 +17,7 @@ import liquibase.executor.ExecutorService; import liquibase.executor.LoggingExecutor; import liquibase.logging.Logger; +import liquibase.parser.ChangeLogParserConfiguration; import liquibase.parser.core.ParsedNode; import liquibase.parser.core.ParsedNodeException; import liquibase.precondition.Conditional; @@ -194,7 +196,7 @@ public String toString() { */ private PreconditionContainer preconditions; - /** + /** * ChangeSet level attribute to specify an Executor */ private String runWith; @@ -276,6 +278,7 @@ public String getFilePath() { /** * The logical file path defined directly on this node. Return null if not set. + * * @return */ public String getLogicalFilePath() { @@ -367,7 +370,7 @@ public void load(ParsedNode node, ResourceAccessor resourceAccessor) throws Pars } } else { filePath = filePath.replaceAll("\\\\", "/") - .replaceFirst("^/", ""); + .replaceFirst("^/", ""); } @@ -440,11 +443,7 @@ protected void handleChildNode(ParsedNode child, ResourceAccessor resourceAccess break; case "preConditions": this.preconditions = new PreconditionContainer(); - try { - this.preconditions.load(child, resourceAccessor); - } catch (ParsedNodeException e) { - e.printStackTrace(); - } + this.preconditions.load(child, resourceAccessor); break; case "changes": for (ParsedNode changeNode : child.getChildren()) { @@ -477,7 +476,7 @@ protected void handleRollbackNode(ParsedNode rollbackNode, ResourceAccessor reso } } if (changeSet == null) { - throw new ParsedNodeException("Change set " + new ChangeSet(changeSetId, changeSetAuthor, false, false, changeSetPath, null, null, null).toString(false) + " does not exist"); + throw new ParsedNodeException("Changeset " + new ChangeSet(changeSetId, changeSetAuthor, false, false, changeSetPath, null, null, null).toString(false) + " does not exist"); } for (Change change : changeSet.getChanges()) { rollback.getChanges().add(change); @@ -517,6 +516,14 @@ protected void handleRollbackNode(ParsedNode rollbackNode, ResourceAccessor reso protected Change toChange(ParsedNode value, ResourceAccessor resourceAccessor) throws ParsedNodeException { Change change = Scope.getCurrentScope().getSingleton(ChangeFactory.class).create(value.getName()); if (change == null) { + if (value.getChildren().size() > 0 && ChangeLogParserConfiguration.CHANGELOG_PARSE_MODE.getCurrentValue().equals(ChangeLogParserConfiguration.ChangelogParseMode.STRICT)) { + String message = ""; + if (this.getChangeLog() != null && this.getChangeLog().getPhysicalFilePath() != null) { + message = "Error parsing " + this.getChangeLog().getPhysicalFilePath() + ": "; + } + message += "Unknown change type '" + value.getName() + "'. Check for spelling or capitalization errors and missing extensions such as liquibase-commercial."; + throw new ParsedNodeException(message); + } return null; } else { change.load(value, resourceAccessor); @@ -539,7 +546,7 @@ public ExecType execute(DatabaseChangeLog databaseChangeLog, Database database) * This method will actually execute each of the changes in the list against the * specified database. * - * @return should change set be marked as ran + * @return should changeset be marked as ran */ public ExecType execute(DatabaseChangeLog databaseChangeLog, ChangeExecListener listener, Database database) throws MigrationFailedException { @@ -691,7 +698,7 @@ public ExecType execute(DatabaseChangeLog databaseChangeLog, ChangeExecListener throw new MigrationFailedException(this, e); } if ((getFailOnError() != null) && !getFailOnError()) { - log.info("Change set " + toString(false) + " failed, but failOnError was false. Error: " + e.getMessage()); + log.info("Changeset " + toString(false) + " failed, but failOnError was false. Error: " + e.getMessage()); log.fine("Failure Stacktrace", e); execType = ExecType.FAILED; } else { @@ -730,7 +737,7 @@ private Executor setupCustomExecutorIfNecessary(Database database) { Scope.getCurrentScope().getSingleton(ExecutorService.class).setExecutor("jdbc", database, customExecutor); List changes = getChanges(); for (Change change : changes) { - if (! (change instanceof AbstractChange)) { + if (!(change instanceof AbstractChange)) { continue; } final ResourceAccessor resourceAccessor = ((AbstractChange) change).getResourceAccessor(); @@ -743,13 +750,11 @@ private Executor setupCustomExecutorIfNecessary(Database database) { } /** - * * Look for a configuration property that matches liquibase..executor * and if found, return its value as the executor name * - * @param executorName The value from the input changeset runWith attribute - * @return String The mapped value - * + * @param executorName The value from the input changeset runWith attribute + * @return String The mapped value */ public static String lookupExecutor(String executorName) { if (StringUtil.isEmpty(executorName)) { @@ -757,7 +762,7 @@ public static String lookupExecutor(String executorName) { } String key = "liquibase." + executorName.toLowerCase() + ".executor"; String replacementExecutorName = - (String)Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class).getCurrentConfiguredValue(null, null, key).getValue(); + (String) Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class).getCurrentConfiguredValue(null, null, key).getValue(); if (replacementExecutorName != null) { Scope.getCurrentScope().getLog(ChangeSet.class).info("Mapped '" + executorName + "' to executor '" + replacementExecutorName + "'"); return replacementExecutorName; @@ -906,7 +911,7 @@ public void setIgnore(boolean ignore) { } public boolean isInheritableIgnore() { - DatabaseChangeLog changeLog = getChangeLog(); + DatabaseChangeLog changeLog = getChangeLog(); if (changeLog == null) { return false; } @@ -945,11 +950,9 @@ public Collection getInheritableLabels() { } /** + * Build and return a string which contains both the changeset and inherited context * - * Build and return a string which contains both the change set and inherited context - * - * @return String - * + * @return String */ public String buildFullContext() { StringBuilder contextExpression = new StringBuilder(); @@ -966,11 +969,9 @@ public String buildFullContext() { } /** + * Build and return a string which contains both the changeset and inherited labels * - * Build and return a string which contains both the change set and inherited labels - * - * @return String - * + * @return String */ public String buildFullLabels() { StringBuilder labels = new StringBuilder(); @@ -1219,11 +1220,11 @@ public String getSerializedObjectName() { @Override public Set getSerializableFields() { return new LinkedHashSet<>( - Arrays.asList( - "id", "author", "runAlways", "runOnChange", "failOnError", "context", "labels", "dbms", - "objectQuotingStrategy", "comment", "preconditions", "changes", "rollback", "labels", - "logicalFilePath", "created", "runInTransaction", "runOrder", "ignore" - ) + Arrays.asList( + "id", "author", "runAlways", "runOnChange", "failOnError", "context", "labels", "dbms", + "objectQuotingStrategy", "comment", "preconditions", "changes", "rollback", "labels", + "logicalFilePath", "created", "runInTransaction", "runOrder", "ignore" + ) ); } @@ -1308,7 +1309,7 @@ public Object getSerializableFieldValue(String field) { } if ("logicalFilePath".equals(field)) { - return getLogicalFilePath(); + return getLogicalFilePath(); } if ("rollback".equals(field)) { diff --git a/liquibase-core/src/main/java/liquibase/changelog/ChangeSetStatus.java b/liquibase-core/src/main/java/liquibase/changelog/ChangeSetStatus.java index fb6077ad7c1..4f12bfa37af 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/ChangeSetStatus.java +++ b/liquibase-core/src/main/java/liquibase/changelog/ChangeSetStatus.java @@ -66,7 +66,7 @@ public void setComments(String comments) { } /** - * Will the change set run next time. + * Will the changeset run next time. */ public boolean getWillRun() { return willRun; @@ -77,7 +77,7 @@ public void setWillRun(boolean willRun) { } /** - * Reasons the change set will or will not run next time. Returns empty set if no reasons were given + * Reasons the changeset will or will not run next time. Returns empty set if no reasons were given */ public Set getFilterResults() { return filterResults; @@ -88,7 +88,7 @@ public void setFilterResults(Set filterResults) { } /** - * Convenience method to check wither a given ChangeSetFilter type is a reason for running the change set or not. + * Convenience method to check wither a given ChangeSetFilter type is a reason for running the changeset or not. */ public boolean isFilteredBy(Class filterType) { if (!willRun) { @@ -108,7 +108,7 @@ public boolean isFilteredBy(Class filterType) { } /** - * Return the checksum stored from the last execution of the change set. Returns null if it has not ran before + * Return the checksum stored from the last execution of the changeset. Returns null if it has not ran before */ public CheckSum getStoredCheckSum() { return storedCheckSum; @@ -119,7 +119,7 @@ public void setStoredCheckSum(CheckSum storedCheckSum) { } /** - * Return the date the change set was last executed. Returns null if it has not ran before + * Return the date the changeset was last executed. Returns null if it has not ran before */ public Date getDateLastExecuted() { return dateLastExecuted; @@ -130,7 +130,7 @@ public void setDateLastExecuted(Date dateLastExecuted) { } /** - * Returns true if the change set was ran previously. + * Returns true if the changeset was ran previously. */ public boolean getPreviouslyRan() { return previouslyRan; diff --git a/liquibase-core/src/main/java/liquibase/changelog/DatabaseChangeLog.java b/liquibase-core/src/main/java/liquibase/changelog/DatabaseChangeLog.java index d51e3512483..c21e846ba82 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/DatabaseChangeLog.java +++ b/liquibase-core/src/main/java/liquibase/changelog/DatabaseChangeLog.java @@ -426,13 +426,9 @@ protected void handleChildNode(ParsedNode node, ResourceAccessor resourceAccesso } case "preConditions": { PreconditionContainer parsedContainer = new PreconditionContainer(); - try { - parsedContainer.load(node, resourceAccessor); - this.preconditionContainer.addNestedPrecondition(parsedContainer); + parsedContainer.load(node, resourceAccessor); + this.preconditionContainer.addNestedPrecondition(parsedContainer); - } catch (ParsedNodeException e) { - e.printStackTrace(); - } break; } case "property": { diff --git a/liquibase-core/src/main/java/liquibase/changelog/RanChangeSet.java b/liquibase-core/src/main/java/liquibase/changelog/RanChangeSet.java index da037be2a8a..ba79b8cd9ab 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/RanChangeSet.java +++ b/liquibase-core/src/main/java/liquibase/changelog/RanChangeSet.java @@ -7,7 +7,7 @@ import java.util.Date; /** - * Encapsulates information about a previously-ran change set. Used to build rollback statements. + * Encapsulates information about a previously-ran changeset. Used to build rollback statements. */ public class RanChangeSet { private final String changeLog; diff --git a/liquibase-core/src/main/java/liquibase/changelog/filter/ActuallyExecutedChangeSetFilter.java b/liquibase-core/src/main/java/liquibase/changelog/filter/ActuallyExecutedChangeSetFilter.java index a66f0ceae32..bd1a86710be 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/filter/ActuallyExecutedChangeSetFilter.java +++ b/liquibase-core/src/main/java/liquibase/changelog/filter/ActuallyExecutedChangeSetFilter.java @@ -16,9 +16,9 @@ public ChangeSetFilterResult accepts(ChangeSet changeSet) { RanChangeSet ranChangeSet = getRanChangeSet(changeSet); if ((ranChangeSet != null) && ((ranChangeSet.getExecType() == null) || ranChangeSet.getExecType().equals (ChangeSet.ExecType.EXECUTED) || ranChangeSet.getExecType().equals(ChangeSet.ExecType.RERAN))) { - return new ChangeSetFilterResult(true, "Change set was executed previously", this.getClass()); + return new ChangeSetFilterResult(true, "Changeset was executed previously", this.getClass()); } else { - return new ChangeSetFilterResult(false, "Change set was not previously executed", this.getClass()); + return new ChangeSetFilterResult(false, "Changeset was not previously executed", this.getClass()); } } } diff --git a/liquibase-core/src/main/java/liquibase/changelog/filter/AfterTagChangeSetFilter.java b/liquibase-core/src/main/java/liquibase/changelog/filter/AfterTagChangeSetFilter.java index 0efea75e4de..b7a52b5c9be 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/filter/AfterTagChangeSetFilter.java +++ b/liquibase-core/src/main/java/liquibase/changelog/filter/AfterTagChangeSetFilter.java @@ -42,9 +42,9 @@ private String changeLogToString(String id, String author, String changeLog) { @Override public ChangeSetFilterResult accepts(ChangeSet changeSet) { if (changeLogsAfterTag.contains(changeLogToString(changeSet.getId(), changeSet.getAuthor(), changeSet.getFilePath()))) { - return new ChangeSetFilterResult(true, "Change set is before tag '"+tag+"'", this.getClass()); + return new ChangeSetFilterResult(true, "Changeset is before tag '"+tag+"'", this.getClass()); } else { - return new ChangeSetFilterResult(false, "Change set after tag '"+tag+"'", this.getClass()); + return new ChangeSetFilterResult(false, "Changeset after tag '"+tag+"'", this.getClass()); } } } diff --git a/liquibase-core/src/main/java/liquibase/changelog/filter/AlreadyRanChangeSetFilter.java b/liquibase-core/src/main/java/liquibase/changelog/filter/AlreadyRanChangeSetFilter.java index 611876c3ca8..312fc07569b 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/filter/AlreadyRanChangeSetFilter.java +++ b/liquibase-core/src/main/java/liquibase/changelog/filter/AlreadyRanChangeSetFilter.java @@ -14,9 +14,9 @@ public AlreadyRanChangeSetFilter(List ranChangeSets) { @Override public ChangeSetFilterResult accepts(ChangeSet changeSet) { if (getRanChangeSet(changeSet) != null) { - return new ChangeSetFilterResult(true, "Change set already ran", this.getClass()); + return new ChangeSetFilterResult(true, "Changeset already ran", this.getClass()); } else { - return new ChangeSetFilterResult(false, "Change set has not ran", this.getClass()); + return new ChangeSetFilterResult(false, "Changeset has not ran", this.getClass()); } } diff --git a/liquibase-core/src/main/java/liquibase/changelog/filter/ChangeSetFilterResult.java b/liquibase-core/src/main/java/liquibase/changelog/filter/ChangeSetFilterResult.java index 82cc23728fd..586221fde81 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/filter/ChangeSetFilterResult.java +++ b/liquibase-core/src/main/java/liquibase/changelog/filter/ChangeSetFilterResult.java @@ -18,7 +18,7 @@ public ChangeSetFilterResult(boolean accepted, String message, Class getFilter() { return filter; diff --git a/liquibase-core/src/main/java/liquibase/changelog/filter/ContextChangeSetFilter.java b/liquibase-core/src/main/java/liquibase/changelog/filter/ContextChangeSetFilter.java index 4c70797e91b..f21192e4c08 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/filter/ContextChangeSetFilter.java +++ b/liquibase-core/src/main/java/liquibase/changelog/filter/ContextChangeSetFilter.java @@ -36,7 +36,7 @@ public ChangeSetFilterResult accepts(ChangeSet changeSet) { Collection inheritableContexts = changeSet.getInheritableContexts(); if (changeSet.getContexts().isEmpty() && inheritableContexts.isEmpty()) { - return new ChangeSetFilterResult(true, "Change set runs under all contexts", this.getClass()); + return new ChangeSetFilterResult(true, "Changeset runs under all contexts", this.getClass()); } if (changeSet.getContexts().matches(contexts) && ContextExpression.matchesAll(inheritableContexts, contexts)) { diff --git a/liquibase-core/src/main/java/liquibase/changelog/filter/CountChangeSetFilter.java b/liquibase-core/src/main/java/liquibase/changelog/filter/CountChangeSetFilter.java index 4504dbac4a2..1b0977619eb 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/filter/CountChangeSetFilter.java +++ b/liquibase-core/src/main/java/liquibase/changelog/filter/CountChangeSetFilter.java @@ -16,9 +16,9 @@ public ChangeSetFilterResult accepts(ChangeSet changeSet) { changeSetsSeen++; if (changeSetsSeen <= changeSetsToAllow) { - return new ChangeSetFilterResult(true, "One of "+changeSetsToAllow+" change sets to run", this.getClass()); + return new ChangeSetFilterResult(true, "One of "+changeSetsToAllow+" changesets to run", this.getClass()); } else { - return new ChangeSetFilterResult(false, "Only running "+changeSetsToAllow+" change sets", this.getClass()); + return new ChangeSetFilterResult(false, "Only running "+changeSetsToAllow+" changesets", this.getClass()); } } } diff --git a/liquibase-core/src/main/java/liquibase/changelog/filter/ExecutedAfterChangeSetFilter.java b/liquibase-core/src/main/java/liquibase/changelog/filter/ExecutedAfterChangeSetFilter.java index 9911c7ef0f0..5c6ee4fd7f6 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/filter/ExecutedAfterChangeSetFilter.java +++ b/liquibase-core/src/main/java/liquibase/changelog/filter/ExecutedAfterChangeSetFilter.java @@ -30,9 +30,9 @@ private String changeLogToString(String id, String author, String changeLog) { @Override public ChangeSetFilterResult accepts(ChangeSet changeSet) { if (changeLogsAfterDate.contains(changeLogToString(changeSet.getId(), changeSet.getAuthor(), changeSet.getFilePath()))) { - return new ChangeSetFilterResult(true, "Change set ran after "+ new ISODateFormat().format(new java.sql.Timestamp(date.getTime())), this.getClass()); + return new ChangeSetFilterResult(true, "Changeset ran after "+ new ISODateFormat().format(new java.sql.Timestamp(date.getTime())), this.getClass()); } else { - return new ChangeSetFilterResult(false, "Change set ran before "+ new ISODateFormat().format(new java.sql.Timestamp(date.getTime())), this.getClass()); + return new ChangeSetFilterResult(false, "Changeset ran before "+ new ISODateFormat().format(new java.sql.Timestamp(date.getTime())), this.getClass()); } } -} \ No newline at end of file +} diff --git a/liquibase-core/src/main/java/liquibase/changelog/filter/IgnoreChangeSetFilter.java b/liquibase-core/src/main/java/liquibase/changelog/filter/IgnoreChangeSetFilter.java index 1b63af616d1..8d5de72665a 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/filter/IgnoreChangeSetFilter.java +++ b/liquibase-core/src/main/java/liquibase/changelog/filter/IgnoreChangeSetFilter.java @@ -5,13 +5,13 @@ public class IgnoreChangeSetFilter implements ChangeSetFilter { public ChangeSetFilterResult accepts(ChangeSet changeSet) { if (changeSet.isIgnore()) { - return new ChangeSetFilterResult(false, "Change set is ignored", this.getClass()); + return new ChangeSetFilterResult(false, "Changeset is ignored", this.getClass()); } else { if (changeSet.isInheritableIgnore()) { - return new ChangeSetFilterResult(false, "Change set is ignored", this.getClass()); + return new ChangeSetFilterResult(false, "Changeset is ignored", this.getClass()); } } - return new ChangeSetFilterResult(true, "Change set is not ignored", this.getClass()); + return new ChangeSetFilterResult(true, "Changeset is not ignored", this.getClass()); } } diff --git a/liquibase-core/src/main/java/liquibase/changelog/filter/LabelChangeSetFilter.java b/liquibase-core/src/main/java/liquibase/changelog/filter/LabelChangeSetFilter.java index 524bf1f566f..7be857a1825 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/filter/LabelChangeSetFilter.java +++ b/liquibase-core/src/main/java/liquibase/changelog/filter/LabelChangeSetFilter.java @@ -39,7 +39,7 @@ public ChangeSetFilterResult accepts(ChangeSet changeSet) { Collection inheritableLabels = changeSet.getInheritableLabels(); if ((changeSet.getLabels() == null || changeSet.getLabels().isEmpty()) && (inheritableLabels == null || inheritableLabels.isEmpty())) { - return new ChangeSetFilterResult(true, "Change set runs under all labels", this.getClass()); + return new ChangeSetFilterResult(true, "Changeset runs under all labels", this.getClass()); } if (labelExpression.matches(changeSet.getLabels()) && LabelExpression.matchesAll(inheritableLabels, labelExpression)) { diff --git a/liquibase-core/src/main/java/liquibase/changelog/filter/NotInChangeLogChangeSetFilter.java b/liquibase-core/src/main/java/liquibase/changelog/filter/NotInChangeLogChangeSetFilter.java index e6fff13b840..5d9314841f5 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/filter/NotInChangeLogChangeSetFilter.java +++ b/liquibase-core/src/main/java/liquibase/changelog/filter/NotInChangeLogChangeSetFilter.java @@ -17,9 +17,9 @@ public NotInChangeLogChangeSetFilter(DatabaseChangeLog databaseChangeLog) { @Override public ChangeSetFilterResult accepts(ChangeSet changeSet) { if (changeSets.contains(changeSet)) { - return new ChangeSetFilterResult(false, "Change set is in change log", this.getClass()); + return new ChangeSetFilterResult(false, "Changeset is in change log", this.getClass()); } else { - return new ChangeSetFilterResult(true, "Change set is not in change log", this.getClass()); + return new ChangeSetFilterResult(true, "Changeset is not in change log", this.getClass()); } } } diff --git a/liquibase-core/src/main/java/liquibase/changelog/filter/NotRanChangeSetFilter.java b/liquibase-core/src/main/java/liquibase/changelog/filter/NotRanChangeSetFilter.java index 1bf7ada57a1..9877c8533c6 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/filter/NotRanChangeSetFilter.java +++ b/liquibase-core/src/main/java/liquibase/changelog/filter/NotRanChangeSetFilter.java @@ -21,9 +21,9 @@ public ChangeSetFilterResult accepts(ChangeSet changeSet) { if (ranChangeSet.getId().equalsIgnoreCase(changeSet.getId()) && ranChangeSet.getAuthor().equalsIgnoreCase(changeSet.getAuthor()) && DatabaseChangeLog.normalizePath(ranChangeSet.getChangeLog()).equalsIgnoreCase(DatabaseChangeLog.normalizePath(changeSet.getFilePath()))) { - return new ChangeSetFilterResult(false, "Change set already ran", this.getClass()); + return new ChangeSetFilterResult(false, "Changeset already ran", this.getClass()); } } - return new ChangeSetFilterResult(true, "Change set not yet ran", this.getClass()); + return new ChangeSetFilterResult(true, "Changeset not yet ran", this.getClass()); } } diff --git a/liquibase-core/src/main/java/liquibase/changelog/filter/ShouldRunChangeSetFilter.java b/liquibase-core/src/main/java/liquibase/changelog/filter/ShouldRunChangeSetFilter.java index 1386de46830..745005abd82 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/filter/ShouldRunChangeSetFilter.java +++ b/liquibase-core/src/main/java/liquibase/changelog/filter/ShouldRunChangeSetFilter.java @@ -58,15 +58,15 @@ public ChangeSetFilterResult accepts(ChangeSet changeSet) { for (RanChangeSet ranChangeSet : this.ranChangeSets.values()) { if (changeSetsMatch(changeSet, ranChangeSet)) { if (changeSet.shouldAlwaysRun()) { - return new ChangeSetFilterResult(true, "Change set always runs", this.getClass()); + return new ChangeSetFilterResult(true, "Changeset always runs", this.getClass()); } if (changeSet.shouldRunOnChange() && checksumChanged(changeSet, ranChangeSet)) { - return new ChangeSetFilterResult(true, "Change set checksum changed", this.getClass()); + return new ChangeSetFilterResult(true, "Changeset checksum changed", this.getClass()); } - return new ChangeSetFilterResult(false, "Change set already ran", this.getClass()); + return new ChangeSetFilterResult(false, "Changeset already ran", this.getClass()); } } - return new ChangeSetFilterResult(true, "Change set has not ran yet", this.getClass()); + return new ChangeSetFilterResult(true, "Changeset has not ran yet", this.getClass()); } protected boolean changeSetsMatch(ChangeSet changeSet, RanChangeSet ranChangeSet) { diff --git a/liquibase-core/src/main/java/liquibase/changelog/filter/UpToTagChangeSetFilter.java b/liquibase-core/src/main/java/liquibase/changelog/filter/UpToTagChangeSetFilter.java index 8156b2b140e..5edbd6c1c3e 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/filter/UpToTagChangeSetFilter.java +++ b/liquibase-core/src/main/java/liquibase/changelog/filter/UpToTagChangeSetFilter.java @@ -28,7 +28,7 @@ public boolean isSeenTag() { @Override public ChangeSetFilterResult accepts(ChangeSet changeSet) { if (seenTag) { - return new ChangeSetFilterResult(false, "Change set is after tag '" + this.tag + "'", this.getClass()); + return new ChangeSetFilterResult(false, "Changeset is after tag '" + this.tag + "'", this.getClass()); } String tag = null; @@ -42,6 +42,6 @@ public ChangeSetFilterResult accepts(ChangeSet changeSet) { seenTag = true; } - return new ChangeSetFilterResult(true, "Change set is at or before tag '" + this.tag + "'", this.getClass()); + return new ChangeSetFilterResult(true, "Changeset is at or before tag '" + this.tag + "'", this.getClass()); } } diff --git a/liquibase-core/src/main/java/liquibase/changelog/visitor/StatusVisitor.java b/liquibase-core/src/main/java/liquibase/changelog/visitor/StatusVisitor.java index a29827b0d6e..c8f453bb1f3 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/visitor/StatusVisitor.java +++ b/liquibase-core/src/main/java/liquibase/changelog/visitor/StatusVisitor.java @@ -74,7 +74,7 @@ public ChangeSetStatus getStatus(ChangeSet changeSet) { /** * Return the status of all changeSets, in the order they exist in the databasechangelog. - * Any change sets not in the current change log but previously ran against the database will be at the front of the List + * Any changesets not in the current change log but previously ran against the database will be at the front of the List * with a not run reason type of {@link liquibase.changelog.filter.NotInChangeLogChangeSetFilter} */ public List getStatuses() { @@ -88,7 +88,7 @@ public List getStatuses() { status.setComments(changeSet.getComments()); status.setDescription(changeSet.getDescription()); status.setWillRun(false); - status.setFilterResults(new HashSet<>(Arrays.asList(new ChangeSetFilterResult(false, "Change set is not in change log", NotInChangeLogChangeSetFilter.class)))); + status.setFilterResults(new HashSet<>(Arrays.asList(new ChangeSetFilterResult(false, "Changeset is not in change log", NotInChangeLogChangeSetFilter.class)))); status.setRanChangeSet(changeSet); returnList.add(status); @@ -100,7 +100,7 @@ public List getStatuses() { } /** - * Return the change sets that will execute + * Return the changesets that will execute */ public List getChangeSetsToRun() { ArrayList returnList = new ArrayList<>(); @@ -114,7 +114,7 @@ public List getChangeSetsToRun() { } /** - * Return the change sets that will NOT execute + * Return the changesets that will NOT execute */ public List getChangeSetsToSkip() { ArrayList returnList = new ArrayList<>(); diff --git a/liquibase-core/src/main/java/liquibase/changelog/visitor/ValidatingVisitor.java b/liquibase-core/src/main/java/liquibase/changelog/visitor/ValidatingVisitor.java index 61dcb582db7..e49ec64061f 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/visitor/ValidatingVisitor.java +++ b/liquibase-core/src/main/java/liquibase/changelog/visitor/ValidatingVisitor.java @@ -115,13 +115,13 @@ public void visit(ChangeSet changeSet, DatabaseChangeLog databaseChangeLog, Data if (foundErrors.hasErrors() && (changeSet.getOnValidationFail().equals (ChangeSet.ValidationFailOption.MARK_RAN))) { Scope.getCurrentScope().getLog(getClass()).info( - "Skipping change set " + changeSet + " due to validation error(s): " + + "Skipping changeset " + changeSet + " due to validation error(s): " + StringUtil.join(foundErrors.getErrorMessages(), ", ")); changeSet.setValidationFailed(true); } else { if (!foundErrors.getWarningMessages().isEmpty()) Scope.getCurrentScope().getLog(getClass()).warning( - "Change set " + changeSet + ": " + + "Changeset " + changeSet + ": " + StringUtil.join(foundErrors.getWarningMessages(), ", ")); validationErrors.addAll(foundErrors, changeSet); } diff --git a/liquibase-core/src/main/java/liquibase/command/core/CalculateChecksumCommandStep.java b/liquibase-core/src/main/java/liquibase/command/core/CalculateChecksumCommandStep.java index f65b66e3852..b5198726cce 100644 --- a/liquibase-core/src/main/java/liquibase/command/core/CalculateChecksumCommandStep.java +++ b/liquibase-core/src/main/java/liquibase/command/core/CalculateChecksumCommandStep.java @@ -39,7 +39,7 @@ public class CalculateChecksumCommandStep extends AbstractCliWrapperCommandStep .setValueObfuscator(ConfigurationValueObfuscator.STANDARD) .build(); CHANGESET_IDENTIFIER_ARG = builder.argument("changesetIdentifier", String.class).required() - .description("Change set ID identifier of form filepath::id::author").build(); + .description("Changeset ID identifier of form filepath::id::author").build(); } @Override diff --git a/liquibase-core/src/main/java/liquibase/command/core/FutureRollbackCountSqlCommandStep.java b/liquibase-core/src/main/java/liquibase/command/core/FutureRollbackCountSqlCommandStep.java index 52a55a3116f..f9f7f22ec58 100644 --- a/liquibase-core/src/main/java/liquibase/command/core/FutureRollbackCountSqlCommandStep.java +++ b/liquibase-core/src/main/java/liquibase/command/core/FutureRollbackCountSqlCommandStep.java @@ -47,7 +47,7 @@ public class FutureRollbackCountSqlCommandStep extends AbstractCliWrapperCommand CONTEXTS_ARG = builder.argument("contexts", String.class) .description("Changeset contexts to match").build(); COUNT_ARG = builder.argument("count", Integer.class).required() - .description("Number of change sets to generate rollback SQL for").build(); + .description("Number of changesets to generate rollback SQL for").build(); OUTPUT_DEFAULT_SCHEMA_ARG = builder.argument("outputDefaultSchema", Boolean.class) .description("Control whether names of objects in the default schema are fully qualified or not. If true they are. If false, only objects outside the default schema are fully qualified") .defaultValue(true) diff --git a/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java b/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java index 1487dbfaed8..368c4946c49 100644 --- a/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java @@ -1,6 +1,24 @@ package liquibase.database; +import static liquibase.util.StringUtil.join; +import java.io.IOException; +import java.io.Writer; +import java.math.BigInteger; +import java.sql.SQLException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; import liquibase.CatalogAndSchema; +import liquibase.GlobalConfiguration; import liquibase.Scope; import liquibase.change.Change; import liquibase.change.core.DropTableChange; @@ -9,7 +27,6 @@ import liquibase.changelog.DatabaseChangeLog; import liquibase.changelog.RanChangeSet; import liquibase.changelog.StandardChangeLogHistoryService; -import liquibase.GlobalConfiguration; import liquibase.configuration.ConfiguredValue; import liquibase.database.core.OracleDatabase; import liquibase.database.core.PostgresDatabase; @@ -60,25 +77,6 @@ import liquibase.util.StreamUtil; import liquibase.util.StringUtil; -import java.io.IOException; -import java.io.Writer; -import java.math.BigInteger; -import java.sql.SQLException; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; - -import static liquibase.util.StringUtil.join; - /** * AbstractJdbcDatabase is extended by all supported databases as a facade to the underlying database. @@ -310,7 +308,7 @@ public String correctObjectName(final String objectName, final Class objectType) { return objectType.equals(Catalog.class) || objectType.equals(Schema.class); } + private CatalogAndSchema.CatalogAndSchemaCase preserveCaseIfRequested() { if (Boolean.TRUE.equals(GlobalConfiguration.PRESERVE_SCHEMA_CASE.getCurrentValue())) { - return CatalogAndSchema.CatalogAndSchemaCase.ORIGINAL_CASE; + return CatalogAndSchema.CatalogAndSchemaCase.ORIGINAL_CASE; } return getSchemaAndCatalogCase(); } @@ -368,6 +367,7 @@ public void setDefaultSchemaName(final String schemaName) { /** * Overwrite this method to get the default schema name for the connection. * If you only need to change the statement that obtains the current schema then override + * * @see AbstractJdbcDatabase#getConnectionSchemaNameCallStatement() */ protected String getConnectionSchemaName() { @@ -395,9 +395,10 @@ protected String getConnectionSchemaName() { * Used to obtain the connection schema name through a statement * Override this method to change the statement. * Only override this if getConnectionSchemaName is left unchanges or is using this method. + * * @see AbstractJdbcDatabase#getConnectionSchemaName() */ - protected SqlStatement getConnectionSchemaNameCallStatement(){ + protected SqlStatement getConnectionSchemaNameCallStatement() { return new RawCallStatement("call current_schema"); } @@ -485,7 +486,7 @@ public String getDateLiteral(final Date date) { return getTimeLiteral(((java.sql.Time) date)); } else if (date instanceof java.sql.Timestamp) { return getDateTimeLiteral(((java.sql.Timestamp) date)); - } else if(date instanceof java.util.Date) { + } else if (date instanceof java.util.Date) { return getDateTimeLiteral(new java.sql.Timestamp(date.getTime())); } else { throw new RuntimeException("Unexpected type: " + date.getClass().getName()); @@ -581,7 +582,6 @@ public String getAutoIncrementClause(final BigInteger startWith, final BigIntege if (generateStartWith || generateIncrementBy) { autoIncrementClause += getAutoIncrementOpening(); - if (generateStartWith) { autoIncrementClause += String.format(getAutoIncrementStartWithClause(), (startWith == null) ? defaultAutoIncrementStartWith : startWith); } @@ -589,6 +589,7 @@ public String getAutoIncrementClause(final BigInteger startWith, final BigIntege if (generateIncrementBy) { if (generateStartWith) { autoIncrementClause += ", "; + } autoIncrementClause += String.format(getAutoIncrementByClause(), (incrementBy == null) ? defaultAutoIncrementBy : incrementBy); @@ -758,8 +759,8 @@ public boolean isReservedWord(final String string) { } /* - * Check if given string starts with numeric values that may cause problems and should be escaped. - */ + * Check if given string starts with numeric values that may cause problems and should be escaped. + */ protected boolean startsWithNumeric(final String objectName) { return STARTS_WITH_NUMBER_PATTERN.matcher(objectName).matches(); } @@ -797,7 +798,7 @@ public void dropDatabaseObjects(final CatalogAndSchema schemaToDrop) throws Liqu final long changeSetStarted = System.currentTimeMillis(); CompareControl compareControl = new CompareControl( - new CompareControl.SchemaComparison[] { + new CompareControl.SchemaComparison[]{ new CompareControl.SchemaComparison( CatalogAndSchema.DEFAULT, schemaToDrop)}, @@ -849,7 +850,7 @@ public void dropDatabaseObjects(final CatalogAndSchema schemaToDrop) throws Liqu @Override public boolean supportsDropTableCascadeConstraints() { return ((this instanceof SQLiteDatabase) || (this instanceof SybaseDatabase) || (this instanceof - SybaseASADatabase) || (this instanceof PostgresDatabase) || (this instanceof OracleDatabase)); + SybaseASADatabase) || (this instanceof PostgresDatabase) || (this instanceof OracleDatabase)); } @Override @@ -858,7 +859,7 @@ public boolean isSystemObject(final DatabaseObject example) { return false; } if ((example.getSchema() != null) && (example.getSchema().getName() != null) && "information_schema" - .equalsIgnoreCase(example.getSchema().getName())) { + .equalsIgnoreCase(example.getSchema().getName())) { return true; } if ((example instanceof Table) && getSystemTables().contains(example.getName())) { @@ -1221,20 +1222,15 @@ public int hashCode() { @Override public void close() throws DatabaseException { - Scope.getCurrentScope().getSingleton(ExecutorService.class).clearExecutor("jdbc", this); - DatabaseConnection connection = getConnection(); - if (connection != null) { - if (previousAutoCommit != null) { - try { - connection.setAutoCommit(previousAutoCommit); - } catch (DatabaseException e) { - Scope.getCurrentScope().getLog(getClass()).warning("Failed to restore the auto commit to " + previousAutoCommit); - - throw e; - } - } - connection.close(); + Scope.getCurrentScope().getSingleton(ExecutorService.class).clearExecutor("jdbc", this); + try (final DatabaseConnection connection = getConnection();) { + if (connection != null && previousAutoCommit != null) { + connection.setAutoCommit(previousAutoCommit); } + } catch (final DatabaseException e) { + Scope.getCurrentScope().getLog(getClass()).warning("Failed to restore the auto commit to " + previousAutoCommit); + throw e; + } } @Override @@ -1264,7 +1260,6 @@ public void setAutoCommit(final boolean b) throws DatabaseException { * Default implementation, just look for "local" IPs. If the database returns a null URL we return false since we don't know it's safe to run the update. * * @throws liquibase.exception.DatabaseException - * */ @Override public boolean isSafeToRunUpdate() throws DatabaseException { @@ -1304,7 +1299,7 @@ public void execute(final SqlStatement[] statements, final List sqlV Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).execute(statement, sqlVisitors); } catch (DatabaseException e) { if (statement.continueOnError()) { - Scope.getCurrentScope().getLog(getClass()).severe("Error executing statement '"+statement.toString()+"', but continuing", e); + Scope.getCurrentScope().getLog(getClass()).severe("Error executing statement '" + statement.toString() + "', but continuing", e); } else { throw e; } @@ -1314,7 +1309,7 @@ public void execute(final SqlStatement[] statements, final List sqlV @Override public void saveStatements(final Change change, final List sqlVisitors, final Writer writer) throws - IOException { + IOException { SqlStatement[] statements = change.generateStatements(this); for (SqlStatement statement : statements) { for (Sql sql : SqlGeneratorFactory.getInstance().generateSql(statement, this)) { @@ -1471,7 +1466,7 @@ public String generateDatabaseFunctionValue(final DatabaseFunction databaseFunct if (sequenceNextValueFunction.contains("'")) { /* For PostgreSQL, the quotes around dangerous identifiers (e.g. mixed-case) need to stay in place, * or else PostgreSQL will not be able to find the sequence. */ - if (! (this instanceof PostgresDatabase)) { + if (!(this instanceof PostgresDatabase)) { sequenceName = sequenceName.replace("\"", ""); } } @@ -1490,7 +1485,7 @@ public String generateDatabaseFunctionValue(final DatabaseFunction databaseFunct if (sequenceCurrentValueFunction.contains("'")) { /* For PostgreSQL, the quotes around dangerous identifiers (e.g. mixed-case) need to stay in place, * or else PostgreSQL will not be able to find the sequence. */ - if (! (this instanceof PostgresDatabase)) { + if (!(this instanceof PostgresDatabase)) { sequenceName = sequenceName.replace("\"", ""); } } @@ -1572,7 +1567,7 @@ public boolean supportsPrimaryKeyNames() { } @Override - public String getSystemSchema(){ + public String getSystemSchema() { return "information_schema"; } @@ -1643,7 +1638,7 @@ public boolean supportsBatchUpdates() throws DatabaseException { if (connection instanceof OfflineConnection) { return false; } else if (connection instanceof JdbcConnection) { - return ((JdbcConnection)getConnection()).supportsBatchUpdates(); + return ((JdbcConnection) getConnection()).supportsBatchUpdates(); } else { // Normally, the connection can only be one of the two above types. But if, for whatever reason, it is // not, let's err on the safe side. @@ -1664,6 +1659,7 @@ public boolean requiresExplicitNullForColumns() { /** * This logic is used when db support catalogs + * * @return UPPER_CASE by default */ @Override diff --git a/liquibase-core/src/main/java/liquibase/database/Database.java b/liquibase-core/src/main/java/liquibase/database/Database.java index 6290b55fc30..1411b306919 100644 --- a/liquibase-core/src/main/java/liquibase/database/Database.java +++ b/liquibase-core/src/main/java/liquibase/database/Database.java @@ -1,25 +1,28 @@ package liquibase.database; +import java.io.IOException; +import java.io.Writer; +import java.math.BigInteger; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Locale; import liquibase.CatalogAndSchema; import liquibase.change.Change; import liquibase.changelog.ChangeSet; import liquibase.changelog.DatabaseChangeLog; import liquibase.changelog.RanChangeSet; -import liquibase.exception.*; +import liquibase.exception.DatabaseException; +import liquibase.exception.DatabaseHistoryException; +import liquibase.exception.DateParseException; +import liquibase.exception.LiquibaseException; +import liquibase.exception.ValidationErrors; import liquibase.servicelocator.PrioritizedService; import liquibase.sql.visitor.SqlVisitor; import liquibase.statement.DatabaseFunction; import liquibase.statement.SqlStatement; import liquibase.structure.DatabaseObject; -import java.io.IOException; -import java.io.Writer; -import java.math.BigInteger; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Locale; - /** * Interface that every DBMS supported by this software must implement. Most methods belong into ont of these * categories: @@ -29,7 +32,7 @@ *

  • creating strings for use in SQL statements, e.g. literals for dates, time, numerals, etc.
  • * */ -public interface Database extends PrioritizedService { +public interface Database extends PrioritizedService, AutoCloseable { String databaseChangeLogTableName = "DatabaseChangeLog".toUpperCase(Locale.US); String databaseChangeLogLockTableName = "DatabaseChangeLogLock".toUpperCase(Locale.US); @@ -270,7 +273,7 @@ public interface Database extends PrioritizedService { RanChangeSet getRanChangeSet(ChangeSet changeSet) throws DatabaseException, DatabaseHistoryException; /** - * After the change set has been ran against the database this method will update the change log table + * After the changeset has been ran against the database this method will update the change log table * with the information. */ void markChangeSetExecStatus(ChangeSet changeSet, ChangeSet.ExecType execType) throws DatabaseException; @@ -290,6 +293,7 @@ public interface Database extends PrioritizedService { String escapeStringForDatabase(String string); + @Override void close() throws DatabaseException; boolean supportsRestrictForeignKeys(); diff --git a/liquibase-core/src/main/java/liquibase/database/DatabaseConnection.java b/liquibase-core/src/main/java/liquibase/database/DatabaseConnection.java index b1da23fc667..98ce7098267 100644 --- a/liquibase-core/src/main/java/liquibase/database/DatabaseConnection.java +++ b/liquibase-core/src/main/java/liquibase/database/DatabaseConnection.java @@ -1,10 +1,9 @@ package liquibase.database; -import liquibase.exception.DatabaseException; -import liquibase.servicelocator.PrioritizedService; - import java.sql.Driver; import java.util.Properties; +import liquibase.exception.DatabaseException; +import liquibase.servicelocator.PrioritizedService; /** * A liquibase abstraction over the normal Connection that is available in @@ -12,7 +11,7 @@ * connection. * */ -public interface DatabaseConnection extends PrioritizedService { +public interface DatabaseConnection extends PrioritizedService, AutoCloseable { void open(String url, Driver driverObject, Properties driverProperties) throws DatabaseException; @@ -29,6 +28,7 @@ default boolean supports(String url) { return true; } + @Override void close() throws DatabaseException; void commit() throws DatabaseException; diff --git a/liquibase-core/src/main/java/liquibase/database/DatabaseFactory.java b/liquibase-core/src/main/java/liquibase/database/DatabaseFactory.java index a332742bbaa..bdef965276e 100644 --- a/liquibase-core/src/main/java/liquibase/database/DatabaseFactory.java +++ b/liquibase-core/src/main/java/liquibase/database/DatabaseFactory.java @@ -176,6 +176,7 @@ public DatabaseConnection openConnection(String url, return openConnection(url, username, driver, databaseClass, driverProperties, resourceAccessor); } + @SuppressWarnings("java:S2095") public DatabaseConnection openConnection(String url, String username, String driver, diff --git a/liquibase-core/src/main/java/liquibase/database/OfflineConnection.java b/liquibase-core/src/main/java/liquibase/database/OfflineConnection.java index eb498390d64..442b473b3af 100644 --- a/liquibase-core/src/main/java/liquibase/database/OfflineConnection.java +++ b/liquibase-core/src/main/java/liquibase/database/OfflineConnection.java @@ -11,7 +11,6 @@ import liquibase.parser.SnapshotParserFactory; import liquibase.resource.ResourceAccessor; import liquibase.servicelocator.LiquibaseService; -import liquibase.servicelocator.PrioritizedService; import liquibase.snapshot.DatabaseSnapshot; import liquibase.snapshot.EmptyDatabaseSnapshot; import liquibase.snapshot.InvalidExampleException; diff --git a/liquibase-core/src/main/java/liquibase/database/core/DatabaseUtils.java b/liquibase-core/src/main/java/liquibase/database/core/DatabaseUtils.java index 4875aeb8b75..0009d65f0f8 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/DatabaseUtils.java +++ b/liquibase-core/src/main/java/liquibase/database/core/DatabaseUtils.java @@ -1,5 +1,6 @@ package liquibase.database.core; +import liquibase.GlobalConfiguration; import liquibase.Scope; import liquibase.database.Database; import liquibase.database.OfflineConnection; @@ -8,6 +9,7 @@ import liquibase.executor.ExecutorService; import liquibase.statement.core.RawSqlStatement; import liquibase.structure.core.Schema; +import liquibase.util.StringUtil; public class DatabaseUtils { /** @@ -39,11 +41,22 @@ public static void initializeDatabase(String defaultCatalogName, String defaultS String searchPath = executor.queryForObject(new RawSqlStatement("SHOW SEARCH_PATH"), String.class); if (!searchPath.equals(defaultCatalogName) && !searchPath.startsWith(defaultSchemaName + ",") && !searchPath.startsWith("\"" + defaultSchemaName + "\",")) { - if (database instanceof CockroachDatabase) { - // CockroachDB doesn't support unquoted `$user` type values - searchPath = searchPath.replaceAll("(\\$\\w+)", "'$1'"); + String finalSearchPath; + if (GlobalConfiguration.PRESERVE_SCHEMA_CASE.getCurrentValue()) { + finalSearchPath = ((PostgresDatabase) database).quoteObject(defaultSchemaName, Schema.class); + } else { + finalSearchPath = defaultSchemaName; } - executor.execute(new RawSqlStatement("SET SEARCH_PATH TO " + database.escapeObjectName(defaultSchemaName, Schema.class) + ", " + searchPath)); + + //If existing search path entries are not quoted, quote them. Some databases do not show them as quoted even though they need to be (like $user or case sensitive schemas) + finalSearchPath += ", " + StringUtil.join(StringUtil.splitAndTrim(searchPath, ","), ",", (StringUtil.StringUtilFormatter) obj -> { + if (obj.startsWith("\"")) { + return obj; + } + return ((PostgresDatabase) database).quoteObject(obj, Schema.class); + }); + + executor.execute(new RawSqlStatement("SET SEARCH_PATH TO " + finalSearchPath)); } } else if (database instanceof AbstractDb2Database) { diff --git a/liquibase-core/src/main/java/liquibase/database/core/DerbyDatabase.java b/liquibase-core/src/main/java/liquibase/database/core/DerbyDatabase.java index a731d5587fd..b27b960d112 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/DerbyDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/DerbyDatabase.java @@ -29,8 +29,8 @@ public DerbyDatabase() { super.sequenceNextValueFunction = "NEXT VALUE FOR %s"; super.sequenceCurrentValueFunction = "(SELECT currentvalue FROM sys.syssequences WHERE sequencename = upper('%s'))"; determineDriverVersion(); - //add reserved words from http://developer.mimer.com/validator/sql-reserved-words.tml - this.addReservedWords(Arrays.asList("ABSOLUTE", "ACTION", "ADD", "AFTER", "ALL", "ALLOCATE", "ALTER", "AND", "ANY", "ARE", "ARRAY", "AS", "ASC", "ASENSITIVE", "ASSERTION", "ASYMMETRIC", "AT", "ATOMIC", "AUTHORIZATION", "AVG", "BEFORE", "BEGIN", "BETWEEN", "BIGINT", "BINARY", "BIT", "BIT_LENGTH", "BLOB", "BOOLEAN", "BOTH", "BREADTH", "BY", "CALL", "CALLED", "CASCADE", "CASCADED", "CASE", "CAST", "CATALOG", "CHAR", "CHARACTER", "CHARACTER_LENGTH", "CHAR_LENGTH", "CHECK", "CLOB", "CLOSE", "COALESCE", "COLLATE", "COLLATION", "COLUMN", "COMMIT", "CONDITION", "CONNECT", "CONNECTION", "CONSTRAINT", "CONSTRAINTS", "CONSTRUCTOR", "CONTAINS", "CONTINUE", "CONVERT", "CORRESPONDING", "COUNT", "CREATE", "CROSS", "CUBE", "CURRENT", "CURRENT_DATE", "CURRENT_DEFAULT_TRANSFORM_GROUP", "CURRENT_PATH", "CURRENT_ROLE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_TRANSFORM_GROUP_FOR_TYPE", "CURRENT_USER", "CURSOR", "CYCLE", "DATA", "DATE", "DAY", "DEALLOCATE", "DEC", "DECIMAL", "DECLARE", "DEFAULT", "DEFERRABLE", "DEFERRED", "DELETE", "DEPTH", "DEREF", "DESC", "DESCRIBE", "DESCRIPTOR", "DETERMINISTIC", "DIAGNOSTICS", "DISCONNECT", "DISTINCT", "DO", "DOMAIN", "DOUBLE", "DROP", "DYNAMIC", "EACH", "ELEMENT", "ELSE", "ELSEIF", "END", "EQUALS", "ESCAPE", "EXCEPT", "EXCEPTION", "EXEC", "EXECUTE", "EXISTS", "EXIT", "EXTERNAL", "EXTRACT", "FALSE", "FETCH", "FILTER", "FIRST", "FLOAT", "FOR", "FOREIGN", "FOUND", "FREE", "FROM", "FULL", "FUNCTION", "GENERAL", "GET", "GLOBAL", "GO", "GOTO", "GRANT", "GROUP", "GROUPING", "HANDLER", "HAVING", "HOLD", "HOUR", "IDENTITY", "IF", "IMMEDIATE", "IN", "INDICATOR", "INITIALLY", "INNER", "INOUT", "INPUT", "INSENSITIVE", "INSERT", "INT", "INTEGER", "INTERSECT", "INTERVAL", "INTO", "IS", "ISOLATION", "ITERATE", "JOIN", "KEY", "LANGUAGE", "LARGE", "LAST", "LATERAL", "LEADING", "LEAVE", "LEFT", "LEVEL", "LIKE", "LOCAL", "LOCALTIME", "LOCALTIMESTAMP", "LOCATOR", "LOOP", "LOWER", "MAP", "MATCH", "MAX", "MEMBER", "MERGE", "METHOD", "MIN", "MINUTE", "MODIFIES", "MODULE", "MONTH", "MULTISET", "NAMES", "NATIONAL", "NATURAL", "NCHAR", "NCLOB", "NEW", "NEXT", "NO", "NONE", "NOT", "NULL", "NULLIF", "NUMERIC", "OBJECT", "OCTET_LENGTH", "OF", "OLD", "ON", "ONLY", "OPEN", "OPTION", "OR", "ORDER", "ORDINALITY", "OUT", "OUTER", "OUTPUT", "OVER", "OVERLAPS", "PAD", "PARAMETER", "PARTIAL", "PARTITION", "PATH", "POSITION", "PRECISION", "PREPARE", "PRESERVE", "PRIMARY", "PRIOR", "PRIVILEGES", "PROCEDURE", "PUBLIC", "RANGE", "READ", "READS", "REAL", "RECURSIVE", "REF", "REFERENCES", "REFERENCING", "RELATIVE", "RELEASE", "REPEAT", "RESIGNAL", "RESTRICT", "RESULT", "RETURN", "RETURNS", "REVOKE", "RIGHT", "ROLE", "ROLLBACK", "ROLLUP", "ROUTINE", "ROW", "ROWS", "SAVEPOINT", "SCHEMA", "SCOPE", "SCROLL", "SEARCH", "SECOND", "SECTION", "SELECT", "SENSITIVE", "SESSION", "SESSION_USER", "SET", "SETS", "SIGNAL", "SIMILAR", "SIZE", "SMALLINT", "SOME", "SPACE", "SPECIFIC", "SPECIFICTYPE", "SQL", "SQLCODE", "SQLERROR", "SQLEXCEPTION", "SQLSTATE", "SQLWARNING", "START", "STATE", "STATIC", "SUBMULTISET", "SUBSTRING", "SUM", "SYMMETRIC", "SYSTEM", "SYSTEM_USER", "TABLE", "TABLESAMPLE", "TEMPORARY", "THEN", "TIME", "TIMESTAMP", "TIMEZONE_HOUR", "TIMEZONE_MINUTE", "TO", "TRAILING", "TRANSACTION", "TRANSLATE", "TRANSLATION", "TREAT", "TRIGGER", "TRIM", "TRUE", "UNDER", "UNDO", "UNION", "UNIQUE", "UNKNOWN", "UNNEST", "UNTIL", "UPDATE", "UPPER", "USAGE", "USER", "USING", "VALUE", "VALUES", "VARCHAR", "VARYING", "VIEW", "WHEN", "WHENEVER", "WHERE", "WHILE", "WINDOW", "WITH", "WITHIN", "WITHOUT", "WORK", "WRITE", "YEAR", "ZONE")); + //add reserved words from https://db.apache.org/derby/docs/10.2/ref/rrefkeywords29722.html + this.addReservedWords(Arrays.asList("ADD", "ALL", "ALLOCATE", "ALTER", "AND", "ANY", "ARE", "AS", "ASC", "ASSERTION", "AT", "AUTHORIZATION", "AVG", "BEGIN", "BETWEEN", "BIGINT", "BIT", "BOOLEAN", "BOTH", "BY", "CALL", "CASCADE", "CASCADED", "CASE", "CAST", "CHAR", "CHARACTER", "CHECK", "CLOSE", "COALESCE", "COLLATE", "COLLATION", "COLUMN", "COMMIT", "CONNECT", "CONNECTION", "CONSTRAINT", "CONSTRAINTS", "CONTINUE", "CONVERT", "CORRESPONDING", "CREATE", "CURRENT", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", "DEALLOCATE", "DEC", "DECIMAL", "DECLARE", "DEFAULT", "DEFERRABLE", "DEFERRED", "DELETE", "DESC", "DESCRIBE", "DIAGNOSTICS", "DISCONNECT", "DISTINCT", "DOUBLE", "DROP", "ELSE", "END", "END-EXEC", "ESCAPE", "EXCEPT", "EXCEPTION", "EXEC", "EXECUTE", "EXISTS", "EXPLAIN", "EXTERNAL", "FALSE", "FETCH", "FIRST", "FLOAT", "FOR", "FOREIGN", "FOUND", "FROM", "FULL", "FUNCTION", "GET", "GETCURRENTCONNECTION", "GLOBAL", "GO", "GOTO", "GRANT", "GROUP", "HAVING", "HOUR", "IDENTITY", "IMMEDIATE", "IN", "INDICATOR", "INITIALLY", "INNER", "INOUT", "INPUT", "INSENSITIVE", "INSERT", "INT", "INTEGER", "INTERSECT", "INTO", "IS", "ISOLATION", "JOIN", "KEY", "LAST", "LEFT", "LIKE", "LOWER", "LTRIM", "MATCH", "MAX", "MIN", "MINUTE", "NATIONAL", "NATURAL", "NCHAR", "NVARCHAR", "NEXT", "NO", "NOT", "NULL", "NULLIF", "NUMERIC", "OF", "ON", "ONLY", "OPEN", "OPTION", "OR", "ORDER", "OUTER", "OUTPUT", "OVERLAPS", "PAD", "PARTIAL", "PREPARE", "PRESERVE", "PRIMARY", "PRIOR", "PRIVILEGES", "PROCEDURE", "PUBLIC", "READ", "REAL", "REFERENCES", "RELATIVE", "RESTRICT", "REVOKE", "RIGHT", "ROLLBACK", "ROWS", "RTRIM", "SCHEMA", "SCROLL", "SECOND", "SELECT", "SESSION_USER", "SET", "SMALLINT", "SOME", "SPACE", "SQL", "SQLCODE", "SQLERROR", "SQLSTATE", "SUBSTR", "SUBSTRING", "SUM", "SYSTEM_USER", "TABLE", "TEMPORARY", "TIMEZONE_HOUR", "TIMEZONE_MINUTE", "TO", "TRANSACTION", "TRANSLATE", "TRANSLATION", "TRUE", "UNION", "UNIQUE", "UNKNOWN", "UPDATE", "UPPER", "USER", "USING", "VALUES", "VARCHAR", "VARYING", "VIEW", "WHENEVER", "WHERE", "WITH", "WORK", "WRITE", "XML", "XMLEXISTS", "XMLPARSE", "XMLQUERY", "XMLSERIALIZE", "YEAR")); } @Override @@ -59,7 +59,7 @@ public String getDefaultDriver(String url) { } catch (ClassNotFoundException classNotFoundException) { // Return class for newer versions anyway return derbyNewDriverClassName; - } + } } } else if (url.startsWith("jdbc:derby") || url.startsWith("java:derby")) { //Use EmbeddedDriver if using a derby URL but without the `://` in it @@ -153,12 +153,15 @@ public String getViewDefinition(CatalogAndSchema schema, String name) throws Dat @Override public void close() throws DatabaseException { + // FIXME Seems not to be a good way to handle the possibility of getting `getConnection() == null` + if (getConnection() != null) { String url = getConnection().getURL(); String driverName = getDefaultDriver(url); super.close(); - if (getShutdownEmbeddedDerby() && (driverName != null) && driverName.toLowerCase().contains("embedded")) { + if (shutdownEmbeddedDerby && (driverName != null) && driverName.toLowerCase().contains("embedded")) { shutdownDerby(url, driverName); } + } } protected void shutdownDerby(String url, String driverName) throws DatabaseException { @@ -194,7 +197,6 @@ protected void shutdownDerby(String url, String driverName) throws DatabaseExcep /** * Determine Apache Derby driver major/minor version. */ - @SuppressWarnings({"static-access", "unchecked"}) protected void determineDriverVersion() { try { // Locate the Derby sysinfo class and query its version info diff --git a/liquibase-core/src/main/java/liquibase/database/core/H2Database.java b/liquibase-core/src/main/java/liquibase/database/core/H2Database.java index 3d9ee5518ad..fe117dc0054 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/H2Database.java +++ b/liquibase-core/src/main/java/liquibase/database/core/H2Database.java @@ -14,6 +14,7 @@ import liquibase.util.JdbcUtil; import java.lang.reflect.Method; +import java.math.BigInteger; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; @@ -303,13 +304,13 @@ protected String getAutoIncrementClause() { } @Override - protected String getAutoIncrementStartWithClause() { - return "%d"; - } + public String getAutoIncrementClause(BigInteger startWith, BigInteger incrementBy, String generationType, Boolean defaultOnNull) { + final String clause = super.getAutoIncrementClause(startWith, incrementBy, generationType, defaultOnNull); + if (clause.startsWith("AUTO_INCREMENT")) { + return clause; + } - @Override - protected String getAutoIncrementByClause() { - return "%d"; + return clause.replace(",", ""); //h2 doesn't use commas between the values } @Override diff --git a/liquibase-core/src/main/java/liquibase/database/core/HsqlDatabase.java b/liquibase-core/src/main/java/liquibase/database/core/HsqlDatabase.java index ccf56789287..30318dde573 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/HsqlDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/HsqlDatabase.java @@ -17,6 +17,7 @@ import static liquibase.statement.DatabaseFunction.CURRENT_DATE_TIME_PLACE_HOLDER; public class HsqlDatabase extends AbstractJdbcDatabase { + private static final Map> SUPPORTED_DEFAULT_VALUE_COMPUTED_MAP; private static String START_CONCAT = "CONCAT("; private static String END_CONCAT = ")"; @@ -512,4 +513,10 @@ public int getMaxFractionalDigitsForTimestamp() { // this value is derived from tests. return 9; } + + @Override + public String getAutoIncrementClause(BigInteger startWith, BigInteger incrementBy, String generationType, Boolean defaultOnNull) { + final String clause = super.getAutoIncrementClause(startWith, incrementBy, generationType, defaultOnNull); + return clause.replace(",", ""); //sql doesn't use commas between the values + } } diff --git a/liquibase-core/src/main/java/liquibase/database/jvm/JdbcConnection.java b/liquibase-core/src/main/java/liquibase/database/jvm/JdbcConnection.java index b7ceb09eb19..6ecb608b16a 100644 --- a/liquibase-core/src/main/java/liquibase/database/jvm/JdbcConnection.java +++ b/liquibase-core/src/main/java/liquibase/database/jvm/JdbcConnection.java @@ -88,7 +88,7 @@ public void open(String url, Driver driverObject, Properties driverProperties) t if (driverClassName.equals("org.h2.Driver")) { errorMessage += ". Make sure your H2 database is active and accessible by opening a new terminal window, run \"liquibase init start-h2\", and then return to this terminal window to run commands"; } - throw new DatabaseException(errorMessage + ". " + sqle.getMessage()); + throw new DatabaseException(errorMessage + ". " + sqle.getMessage(), sqle); } } diff --git a/liquibase-core/src/main/java/liquibase/dbdoc/HTMLWriter.java b/liquibase-core/src/main/java/liquibase/dbdoc/HTMLWriter.java index cdb738714f2..d072853a0c0 100644 --- a/liquibase-core/src/main/java/liquibase/dbdoc/HTMLWriter.java +++ b/liquibase-core/src/main/java/liquibase/dbdoc/HTMLWriter.java @@ -63,7 +63,7 @@ private void writeFooter(Writer fileWriter, String changeLog) throws IOException fileWriter.append("
    Change Log: "); fileWriter.append(changeLog); fileWriter.append("

    Generated By: "); - fileWriter.append("Liquibase ").append(LiquibaseUtil + fileWriter.append("Liquibase ").append(LiquibaseUtil .getBuildVersionInfo()).append(""); } diff --git a/liquibase-core/src/main/java/liquibase/diff/output/StandardObjectChangeFilter.java b/liquibase-core/src/main/java/liquibase/diff/output/StandardObjectChangeFilter.java index b27649f6f88..2c8f76477b1 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/StandardObjectChangeFilter.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/StandardObjectChangeFilter.java @@ -1,14 +1,17 @@ package liquibase.diff.output; +import liquibase.Scope; import liquibase.database.Database; import liquibase.diff.ObjectDifferences; import liquibase.exception.UnexpectedLiquibaseException; +import liquibase.servicelocator.ServiceLocator; import liquibase.structure.DatabaseObject; import liquibase.structure.core.*; import liquibase.util.StringUtil; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.regex.Pattern; /** @@ -24,13 +27,18 @@ */ public class StandardObjectChangeFilter implements ObjectChangeFilter { - private FilterType filterType; + private final FilterType filterType; - private List filters = new ArrayList<>(); + private final List filters = new ArrayList<>(); + private final static List databaseObjects = new ArrayList<>(); private boolean catalogOrSchemaFilter; public StandardObjectChangeFilter(FilterType type, String filter) { this.filterType = type; + if (databaseObjects.isEmpty()) { + ServiceLocator serviceLocator = Scope.getCurrentScope().getServiceLocator(); + databaseObjects.addAll(serviceLocator.findInstances(DatabaseObject.class)); + } parseFilter(filter); } @@ -47,15 +55,14 @@ protected void parseFilter(String filter) { if (split.length == 1) { filters.add(new Filter(null, Pattern.compile(split[0]))); } else { - String className = StringUtil.upperCaseFirst(split[0]); - className = "liquibase.structure.core."+className; - try { - Class clazz = (Class) Class.forName(className); - filters.add(new Filter(clazz, Pattern.compile(split[1]))); - catalogOrSchemaFilter |= "Catalog".equals(className) || "Schema".equals(className); - } catch (ClassNotFoundException e) { - throw new UnexpectedLiquibaseException(e); + String className = split[0]; + Optional databaseObject = databaseObjects.stream().filter(instance -> instance.getClass().getSimpleName().equalsIgnoreCase(className)).findAny(); + if (databaseObject.isPresent()) { + filters.add(new Filter((Class) databaseObject.get().getClass(), Pattern.compile(split[1]))); + } else { + throw new UnexpectedLiquibaseException(className + " not found"); } + catalogOrSchemaFilter |= "Catalog".equals(className) || "Schema".equals(className); } } } diff --git a/liquibase-core/src/main/java/liquibase/exception/MigrationFailedException.java b/liquibase-core/src/main/java/liquibase/exception/MigrationFailedException.java index 5695362e3d6..3e647cfbb97 100644 --- a/liquibase-core/src/main/java/liquibase/exception/MigrationFailedException.java +++ b/liquibase-core/src/main/java/liquibase/exception/MigrationFailedException.java @@ -31,7 +31,7 @@ public MigrationFailedException(ChangeSet failedChangeSet, Throwable cause) { public String getMessage() { String message = "Migration failed"; if (failedChangeSetName != null) { - message += " for change set "+ failedChangeSetName; + message += " for changeset "+ failedChangeSetName; } message += ":\n Reason: "+super.getMessage(); diff --git a/liquibase-core/src/main/java/liquibase/exception/ValidationFailedException.java b/liquibase-core/src/main/java/liquibase/exception/ValidationFailedException.java index 311c40acfc2..e65a20c118f 100644 --- a/liquibase-core/src/main/java/liquibase/exception/ValidationFailedException.java +++ b/liquibase-core/src/main/java/liquibase/exception/ValidationFailedException.java @@ -126,7 +126,7 @@ public List getInvalidMD5Sums() { public void printDescriptiveError(PrintStream out) { out.println("Validation Error: "); if (!invalidMD5Sums.isEmpty()) { - out.println(INDENT_SPACES +invalidMD5Sums.size()+" change sets have changed since they were ran against the database"); + out.println(INDENT_SPACES +invalidMD5Sums.size()+" changesets have changed since they were ran against the database"); for (String message : invalidMD5Sums) { out.println(" " + message); } @@ -146,7 +146,7 @@ public void printDescriptiveError(PrintStream out) { } if (!duplicateChangeSets.isEmpty()) { - out.println(INDENT_SPACES +duplicateChangeSets.size()+" change sets had duplicate identifiers"); + out.println(INDENT_SPACES +duplicateChangeSets.size()+" changesets had duplicate identifiers"); for (ChangeSet duplicate : duplicateChangeSets) { out.println(" "+duplicate.toString(false)); } diff --git a/liquibase-core/src/main/java/liquibase/executor/AbstractExecutor.java b/liquibase-core/src/main/java/liquibase/executor/AbstractExecutor.java index 75c1d0434b7..b798df38e72 100644 --- a/liquibase-core/src/main/java/liquibase/executor/AbstractExecutor.java +++ b/liquibase-core/src/main/java/liquibase/executor/AbstractExecutor.java @@ -44,9 +44,9 @@ public abstract class AbstractExecutor implements Executor { /** * - * Validate if the change set can be executed by this Executor + * Validate if the changeset can be executed by this Executor * - * @param changeSet The change set to validate + * @param changeSet The changeset to validate * @return boolean Always true for abstract class * */ @@ -57,10 +57,10 @@ public ValidationErrors validate(ChangeSet changeSet) { /** * - * Allow this Executor to make any needed changes to the change set. + * Allow this Executor to make any needed changes to the changeset. * The base class sets splitStatements to 'true' if it is not set * - * @param changeSet The change set to operate on + * @param changeSet The changeset to operate on * */ @Override diff --git a/liquibase-core/src/main/java/liquibase/executor/Executor.java b/liquibase-core/src/main/java/liquibase/executor/Executor.java index 54eb4862f85..14d3a0b1988 100644 --- a/liquibase-core/src/main/java/liquibase/executor/Executor.java +++ b/liquibase-core/src/main/java/liquibase/executor/Executor.java @@ -32,19 +32,19 @@ public interface Executor extends Plugin { int getPriority(); /** - * Validate if the change set can be executed by this Executor + * Validate if the changeset can be executed by this Executor * If the ChangeSet can be executed return an empty ValidationErrors object * otherwise return the errors * - * @param changeSet The change set to validate + * @param changeSet The changeset to validate * @return ValidationErrors Any errors which occur during validation */ ValidationErrors validate(ChangeSet changeSet); /** - * Allow this Executor to make any needed changes to the change set + * Allow this Executor to make any needed changes to the changeset * - * @param changeSet The change set to operate on + * @param changeSet The changeset to operate on */ void modifyChangeSet(ChangeSet changeSet); diff --git a/liquibase-core/src/main/java/liquibase/hub/HubUpdater.java b/liquibase-core/src/main/java/liquibase/hub/HubUpdater.java index bd22297e207..4011177bc2a 100644 --- a/liquibase-core/src/main/java/liquibase/hub/HubUpdater.java +++ b/liquibase-core/src/main/java/liquibase/hub/HubUpdater.java @@ -91,7 +91,7 @@ public Operation preUpdateHub(String operationType, String operationCommand, Con * @param changeLogFile Path to DatabaseChangelog for this operation * @param contexts Contexts to use for filtering * @param labelExpression Labels to use for filtering - * @param changeLogIterator Iterator to use for going through change sets + * @param changeLogIterator Iterator to use for going through changesets * @return Operation Valid Operation object or null * @throws LiquibaseHubException Thrown by HubService * @throws DatabaseException Thrown by Liquibase core diff --git a/liquibase-core/src/main/java/liquibase/hub/listener/HubChangeExecListener.java b/liquibase-core/src/main/java/liquibase/hub/listener/HubChangeExecListener.java index 394da426795..6cf2c434158 100644 --- a/liquibase-core/src/main/java/liquibase/hub/listener/HubChangeExecListener.java +++ b/liquibase-core/src/main/java/liquibase/hub/listener/HubChangeExecListener.java @@ -128,7 +128,7 @@ public void rollbackFailed(ChangeSet changeSet, DatabaseChangeLog databaseChange /** * - * Called which a change set is successfully rolled back + * Called which a changeset is successfully rolled back * * @param changeSet changeSet that was rolled back * @param databaseChangeLog parent change log @@ -183,7 +183,7 @@ public void markedRan(ChangeSet changeSet, DatabaseChangeLog databaseChangeLog, } // - // Send an update message to Hub for this change set rollback + // Send an update message to Hub for this changeset rollback // private void updateHubForRollback(ChangeSet changeSet, DatabaseChangeLog databaseChangeLog, @@ -305,7 +305,7 @@ else if (changeSet.hasCustomRollbackChanges()) { catch (LiquibaseException lbe) { logger.warning(lbe.getMessage(), lbe); logger.warning("Unable to send Operation Change Event for operation '" + operation.getId().toString() + - " change set '" + changeSet.toString(false)); + " changeset '" + changeSet.toString(false)); } } @@ -324,7 +324,7 @@ private String getCurrentLog() { } // - // Send an update message to Hub for this change set + // Send an update message to Hub for this changeset // private void updateHub(ChangeSet changeSet, DatabaseChangeLog databaseChangeLog, @@ -401,7 +401,7 @@ private void updateHub(ChangeSet changeSet, // // Just log message // - logger.warning("Unable to serialize change set '" + changeSet.toString(false) + "' for Hub."); + logger.warning("Unable to serialize changeset '" + changeSet.toString(false) + "' for Hub."); } } @@ -443,7 +443,7 @@ private void updateHub(ChangeSet changeSet, catch (LiquibaseException lbe) { logger.warning(lbe.getMessage(), lbe); logger.warning("Unable to send Operation Change Event for operation '" + operation.getId().toString() + - " change set '" + changeSet.toString(false)); + " changeset '" + changeSet.toString(false)); failedToPostCount++; } } diff --git a/liquibase-core/src/main/java/liquibase/integration/commandline/CommandLineUtils.java b/liquibase-core/src/main/java/liquibase/integration/commandline/CommandLineUtils.java index fb99f9d7c8e..e70d4a226ea 100644 --- a/liquibase-core/src/main/java/liquibase/integration/commandline/CommandLineUtils.java +++ b/liquibase-core/src/main/java/liquibase/integration/commandline/CommandLineUtils.java @@ -65,6 +65,7 @@ public static Database createDatabaseObject(ClassLoader classLoader, databaseChangeLogTableName, databaseChangeLogLockTableName); } + @SuppressWarnings("java:S2095") public static Database createDatabaseObject(ResourceAccessor resourceAccessor, String url, String username, diff --git a/liquibase-core/src/main/java/liquibase/integration/servlet/GenericServletListener.java b/liquibase-core/src/main/java/liquibase/integration/servlet/GenericServletListener.java index 1f686411eea..7c47dd0b510 100644 --- a/liquibase-core/src/main/java/liquibase/integration/servlet/GenericServletListener.java +++ b/liquibase-core/src/main/java/liquibase/integration/servlet/GenericServletListener.java @@ -27,7 +27,7 @@ * Servlet listener than can be added to web.xml to allow Liquibase to run on every application server startup. * Using this listener allows users to know that they always have the most up to date database, although it will * slow down application server startup slightly. - * See the Liquibase documentation for + * See the Liquibase documentation for * more information. * * @see LiquibaseJakartaServletListener diff --git a/liquibase-core/src/main/java/liquibase/parser/ChangeLogParserConfiguration.java b/liquibase-core/src/main/java/liquibase/parser/ChangeLogParserConfiguration.java index f0a6f64ec4b..36afa37be9f 100644 --- a/liquibase-core/src/main/java/liquibase/parser/ChangeLogParserConfiguration.java +++ b/liquibase-core/src/main/java/liquibase/parser/ChangeLogParserConfiguration.java @@ -1,5 +1,6 @@ package liquibase.parser; +import liquibase.GlobalConfiguration; import liquibase.configuration.AutoloadedConfigurations; import liquibase.configuration.ConfigurationDefinition; @@ -12,6 +13,9 @@ public class ChangeLogParserConfiguration implements AutoloadedConfigurations { public static final ConfigurationDefinition USE_PROCEDURE_SCHEMA; public static final ConfigurationDefinition MISSING_PROPERTY_MODE; + public static final ConfigurationDefinition CHANGELOG_PARSE_MODE; + + static { ConfigurationDefinition.Builder builder = new ConfigurationDefinition.Builder("liquibase"); @@ -30,6 +34,13 @@ public class ChangeLogParserConfiguration implements AutoloadedConfigurations { .setDescription("How to handle changelog property expressions where a value is not set. For example, a string '${address}' when no 'address' property was defined. Values can be: 'preserve' which leaves the string as-is, 'empty' which replaces it with an empty string, or 'error' which stops processing with an error.") .setDefaultValue(MissingPropertyMode.PRESERVE) .build(); + + + CHANGELOG_PARSE_MODE = builder.define("changelogParseMode", ChangelogParseMode.class) + .setDescription("Configures how to handle unknown fields in changelog files. Possible values: STRICT which causes parsing to fail, and LAX which continues with the parsing.") + .setDefaultValue(ChangelogParseMode.STRICT) + .build(); + } public enum MissingPropertyMode { @@ -37,4 +48,9 @@ public enum MissingPropertyMode { EMPTY, ERROR, } + + public enum ChangelogParseMode { + STRICT, + LAX, + } } diff --git a/liquibase-core/src/main/java/liquibase/parser/core/formattedsql/FormattedSqlChangeLogParser.java b/liquibase-core/src/main/java/liquibase/parser/core/formattedsql/FormattedSqlChangeLogParser.java index b775bd00056..cce0d441d3a 100644 --- a/liquibase-core/src/main/java/liquibase/parser/core/formattedsql/FormattedSqlChangeLogParser.java +++ b/liquibase-core/src/main/java/liquibase/parser/core/formattedsql/FormattedSqlChangeLogParser.java @@ -83,7 +83,7 @@ public DatabaseChangeLog parse(String physicalChangeLogLocation, ChangeLogParame RawSQLChange change = null; Pattern changeLogPattern = Pattern.compile("\\-\\-\\s*liquibase formatted.*", Pattern.CASE_INSENSITIVE); Pattern propertyPattern = Pattern.compile("\\s*\\-\\-[\\s]*property\\s+(.*:.*)\\s+(.*:.*).*", Pattern.CASE_INSENSITIVE); - Pattern altPropertyOneDashPattern = Pattern.compile("\\s*?[-]+.*property\\s.*", Pattern.CASE_INSENSITIVE); + Pattern altPropertyOneDashPattern = Pattern.compile("\\s*?[-]+\\s*property\\s.*", Pattern.CASE_INSENSITIVE); Pattern changeSetPattern = Pattern.compile("\\s*\\-\\-[\\s]*changeset\\s+(\"[^\"]+\"|[^:]+):\\s*(\"[^\"]+\"|\\S+).*", Pattern.CASE_INSENSITIVE); Pattern altChangeSetOneDashPattern = Pattern.compile("\\-[\\s]*changeset\\s.*", Pattern.CASE_INSENSITIVE); Pattern altChangeSetNoOtherInfoPattern = Pattern.compile("\\s*\\-\\-[\\s]*changeset[\\s]*.*$", Pattern.CASE_INSENSITIVE); @@ -407,7 +407,7 @@ public DatabaseChangeLog parse(String physicalChangeLogLocation, ChangeLogParame } else { if (commentMatcher.matches()) { String message = - String.format("Unexpected formatting at line %d. Formatted SQL changelogs do not allow comment lines outside of change sets. Learn all the options at https://docs.liquibase.com/concepts/changelogs/sql-format.html", count); + String.format("Unexpected formatting at line %d. Formatted SQL changelogs do not allow comment lines outside of changesets. Learn all the options at https://docs.liquibase.com/concepts/changelogs/sql-format.html", count); throw new ChangeLogParseException("\n" + message); } } diff --git a/liquibase-core/src/main/java/liquibase/parser/core/xml/LiquibaseEntityResolver.java b/liquibase-core/src/main/java/liquibase/parser/core/xml/LiquibaseEntityResolver.java index 8419bfa0d6f..5c1de3f7d1d 100644 --- a/liquibase-core/src/main/java/liquibase/parser/core/xml/LiquibaseEntityResolver.java +++ b/liquibase-core/src/main/java/liquibase/parser/core/xml/LiquibaseEntityResolver.java @@ -6,12 +6,15 @@ import liquibase.resource.ClassLoaderResourceAccessor; import liquibase.resource.InputStreamList; import liquibase.resource.ResourceAccessor; +import liquibase.util.LiquibaseUtil; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.ext.EntityResolver2; import java.io.IOException; import java.io.InputStream; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Finds the Liquibase schema from the classpath rather than fetching it over the Internet. @@ -20,6 +23,11 @@ public class LiquibaseEntityResolver implements EntityResolver2 { private static ClassLoaderResourceAccessor fallbackResourceAccessor; + private boolean shouldWarnOnMismatchedXsdVersion = false; + /** + * The warning message should only be printed once. + */ + private static boolean hasWarnedAboutMismatchedXsdVersion = false; @Override @java.lang.SuppressWarnings("squid:S2095") @@ -37,6 +45,10 @@ public InputSource resolveEntity(String name, String publicId, String baseURI, S .replace("http://www.liquibase.org/xml/ns/migrator/", "http://www.liquibase.org/xml/ns/dbchangelog/") .replaceFirst("https?://", ""); + if (shouldWarnOnMismatchedXsdVersion && !hasWarnedAboutMismatchedXsdVersion) { + warnForMismatchedXsdVersion(systemId); + } + ResourceAccessor resourceAccessor = Scope.getCurrentScope().getResourceAccessor(); InputStreamList streams = resourceAccessor.openStreams(null, path); if (streams.isEmpty()) { @@ -44,9 +56,9 @@ public InputSource resolveEntity(String name, String publicId, String baseURI, S if (streams.isEmpty()) { if (GlobalConfiguration.SECURE_PARSING.getCurrentValue()) { - String errorMessage = "Unable to resolve xml entity " + systemId + " locally: " + + String errorMessage = "Unable to resolve xml entity " + systemId + ". " + GlobalConfiguration.SECURE_PARSING.getKey() + " is set to 'true' which does not allow remote lookups. " + - "Set it to 'false' to allow remote lookups of xsd files."; + "Check for spelling or capitalization errors and missing extensions such as liquibase-commercial in your XSD definition. Or, set it to 'false' to allow remote lookups of xsd files."; throw new XSDLookUpException(errorMessage); } else { log.fine("Unable to resolve XML entity locally. Will load from network."); @@ -70,9 +82,35 @@ public InputSource resolveEntity(String name, String publicId, String baseURI, S } + /** + * Print a warning message to the logs and UI if the build version does not match the XSD version. This is a best + * effort check, this method will never throw an exception. + */ + private void warnForMismatchedXsdVersion(String systemId) { + try { + Pattern versionPattern = Pattern.compile("(?:-pro-|-)(?[\\d.]*)\\.xsd"); + Matcher versionMatcher = versionPattern.matcher(systemId); + boolean found = versionMatcher.find(); + if (found) { + String buildVersion = LiquibaseUtil.getBuildVersion(); + if (!buildVersion.equals("DEV")) { + String xsdVersion = versionMatcher.group("version"); + if (!buildVersion.startsWith(xsdVersion)) { + hasWarnedAboutMismatchedXsdVersion = true; + String msg = "INFO: An older version of the XSD is specified in one or more changelog's header. This can lead to unexpected outcomes. If a specific XSD is not required, please replace all XSD version references with \"-latest\". Learn more at https://docs.liquibase.com"; + Scope.getCurrentScope().getLog(getClass()).info(msg); + Scope.getCurrentScope().getUI().sendMessage(msg); + } + } + } + } catch (Exception e) { + Scope.getCurrentScope().getLog(getClass()).fine("Failed to compare XSD version with build version.", e); + } + } + /** * ResourceAccessor to use if the standard one does not have the XSD files in it. - * Returns a ClassLoaderResourceAccessor that checks the system classloader which should include the liquibase.jar. + * Returns a ClassLoaderResourceAccessor that checks the system classloader which should include the liquibase-core.jar. */ protected ResourceAccessor getFallbackResourceAccessor() { if (fallbackResourceAccessor == null) { @@ -91,4 +129,12 @@ public InputSource resolveEntity(String publicId, String systemId) throws SAXExc Scope.getCurrentScope().getLog(getClass()).warning("The current XML parser does not seems to not support EntityResolver2. External entities may not be correctly loaded"); return resolveEntity(null, publicId, null, systemId); } + + /** + * When set to true, a warning will be printed to the console if the XSD version used does not match the version + * of Liquibase. If "latest" is used as the XSD version, no warning is printed. + */ + public void setShouldWarnOnMismatchedXsdVersion(boolean shouldWarnOnMismatchedXsdVersion) { + this.shouldWarnOnMismatchedXsdVersion = shouldWarnOnMismatchedXsdVersion; + } } diff --git a/liquibase-core/src/main/java/liquibase/parser/core/xml/XMLChangeLogSAXParser.java b/liquibase-core/src/main/java/liquibase/parser/core/xml/XMLChangeLogSAXParser.java index 5c4e78467ca..117d2f268ce 100644 --- a/liquibase-core/src/main/java/liquibase/parser/core/xml/XMLChangeLogSAXParser.java +++ b/liquibase-core/src/main/java/liquibase/parser/core/xml/XMLChangeLogSAXParser.java @@ -59,6 +59,14 @@ protected SAXParserFactory getSaxParserFactory() { return saxParserFactory; } + /** + * When set to true, a warning will be printed to the console if the XSD version used does not match the version + * of Liquibase. If "latest" is used as the XSD version, no warning is printed. + */ + public void setShouldWarnOnMismatchedXsdVersion(boolean shouldWarnOnMismatchedXsdVersion) { + resolver.setShouldWarnOnMismatchedXsdVersion(shouldWarnOnMismatchedXsdVersion); + } + @Override protected ParsedNode parseToNode(String physicalChangeLogLocation, ChangeLogParameters changeLogParameters, ResourceAccessor resourceAccessor) throws ChangeLogParseException { try (InputStream inputStream = resourceAccessor.openStream(null, physicalChangeLogLocation)) { @@ -165,7 +173,7 @@ static String computeSchemaVersion(String version) { finalVersion = splitVersion[0] + "." + splitVersion[1]; } if (finalVersion == null) { - finalVersion = "next"; + finalVersion = "latest"; } return finalVersion; } diff --git a/liquibase-core/src/main/java/liquibase/parser/core/yaml/YamlSnapshotParser.java b/liquibase-core/src/main/java/liquibase/parser/core/yaml/YamlSnapshotParser.java index bdd0f63b06f..e79c41caa15 100644 --- a/liquibase-core/src/main/java/liquibase/parser/core/yaml/YamlSnapshotParser.java +++ b/liquibase-core/src/main/java/liquibase/parser/core/yaml/YamlSnapshotParser.java @@ -19,6 +19,7 @@ public class YamlSnapshotParser extends YamlParser implements SnapshotParser { + @SuppressWarnings("java:S2095") @Override public DatabaseSnapshot parse(String path, ResourceAccessor resourceAccessor) throws LiquibaseParseException { Yaml yaml = new Yaml(new SafeConstructor()); diff --git a/liquibase-core/src/main/java/liquibase/precondition/PreconditionLogic.java b/liquibase-core/src/main/java/liquibase/precondition/PreconditionLogic.java index 8c1eff6338e..fc0d41fc532 100644 --- a/liquibase-core/src/main/java/liquibase/precondition/PreconditionLogic.java +++ b/liquibase-core/src/main/java/liquibase/precondition/PreconditionLogic.java @@ -1,7 +1,9 @@ package liquibase.precondition; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.exception.ValidationErrors; +import liquibase.parser.ChangeLogParserConfiguration; import liquibase.parser.core.ParsedNode; import liquibase.parser.core.ParsedNodeException; import liquibase.resource.ResourceAccessor; @@ -47,6 +49,10 @@ public void load(ParsedNode parsedNode, ResourceAccessor resourceAccessor) throw protected Precondition toPrecondition(ParsedNode node, ResourceAccessor resourceAccessor) throws ParsedNodeException { Precondition precondition = PreconditionFactory.getInstance().create(node.getName()); if (precondition == null) { + if (node.getChildren() != null && node.getChildren().size() > 0 && ChangeLogParserConfiguration.CHANGELOG_PARSE_MODE.getCurrentValue().equals(ChangeLogParserConfiguration.ChangelogParseMode.STRICT)) { + throw new ParsedNodeException("Unknown precondition '" + node.getName() + "'. Check for spelling or capitalization errors and missing extensions such as liquibase-commercial."); + } + return null; } diff --git a/liquibase-core/src/main/java/liquibase/precondition/core/ChangeSetExecutedPrecondition.java b/liquibase-core/src/main/java/liquibase/precondition/core/ChangeSetExecutedPrecondition.java index 2bbdae3051c..fe64065c937 100644 --- a/liquibase-core/src/main/java/liquibase/precondition/core/ChangeSetExecutedPrecondition.java +++ b/liquibase-core/src/main/java/liquibase/precondition/core/ChangeSetExecutedPrecondition.java @@ -78,7 +78,7 @@ public void check(Database database, DatabaseChangeLog changeLog, ChangeSet chan throw new PreconditionErrorException(e, changeLog, this); } if ((ranChangeSet == null) || (ranChangeSet.getExecType() == null) || !ranChangeSet.getExecType().ran) { - throw new PreconditionFailedException("Change Set '"+interestedChangeSet.toString(false)+"' has not been run", changeLog, this); + throw new PreconditionFailedException("Changeset '"+interestedChangeSet.toString(false)+"' has not been run", changeLog, this); } } diff --git a/liquibase-core/src/main/java/liquibase/serializer/core/yaml/YamlSerializer.java b/liquibase-core/src/main/java/liquibase/serializer/core/yaml/YamlSerializer.java index 8ef87b11728..0efbebe7888 100644 --- a/liquibase-core/src/main/java/liquibase/serializer/core/yaml/YamlSerializer.java +++ b/liquibase-core/src/main/java/liquibase/serializer/core/yaml/YamlSerializer.java @@ -167,7 +167,8 @@ public int compare(String o1, String o2) { } private String removeClassTypeMarksFromSerializedJson(String json) { - json = json.replaceAll("!!int \"(\\d+)\"", "$1"); + // Handle both negative and positive numbers + json = json.replaceAll("!!int \"(-?\\d+)\"", "$1"); json = json.replaceAll("!!bool \"(\\w+)\"", "$1"); json = json.replaceAll("!!timestamp \"([^\"]*)\"", "$1"); json = json.replaceAll("!!float \"([^\"]*)\"", "$1"); diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/AddAutoIncrementGeneratorMySQL.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/AddAutoIncrementGeneratorMySQL.java index 7cf34d86843..2efb88f7ed4 100644 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/AddAutoIncrementGeneratorMySQL.java +++ b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/AddAutoIncrementGeneratorMySQL.java @@ -2,6 +2,7 @@ import liquibase.database.Database; import liquibase.database.core.MySQLDatabase; +import liquibase.exception.ValidationErrors; import liquibase.sql.Sql; import liquibase.sql.UnparsedSql; import liquibase.sqlgenerator.SqlGeneratorChain; @@ -40,6 +41,13 @@ public Sql[] generateSql(final AddAutoIncrementStatement statement, Database dat return sql; } + @Override + public ValidationErrors validate(AddAutoIncrementStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) { + ValidationErrors validationErrors = super.validate(statement, database, sqlGeneratorChain); + validationErrors.checkDisallowedField("incrementBy", statement.getIncrementBy(), database, MySQLDatabase.class); + return validationErrors; + } + private Sql[] concact(Sql[] origSql, UnparsedSql unparsedSql) { Sql[] changedSql = new Sql[origSql.length+1]; System.arraycopy(origSql, 0, changedSql, 0, origSql.length); @@ -51,4 +59,4 @@ private Sql[] concact(Sql[] origSql, UnparsedSql unparsedSql) { private DatabaseObject getAffectedTable(AddAutoIncrementStatement statement) { return new Table().setName(statement.getTableName()).setSchema(new Schema(statement.getCatalogName(), statement.getSchemaName())); } -} \ No newline at end of file +} diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateTableGenerator.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateTableGenerator.java index 42f023382cc..c3dfe160cab 100644 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateTableGenerator.java +++ b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateTableGenerator.java @@ -43,6 +43,12 @@ public ValidationErrors validate(CreateTableStatement createTableStatement, Data ValidationErrors validationErrors = new ValidationErrors(); validationErrors.checkRequiredField("tableName", createTableStatement.getTableName()); validationErrors.checkRequiredField("columns", createTableStatement.getColumns()); + + if (createTableStatement.getAutoIncrementConstraints() != null) { + for (AutoIncrementConstraint constraint : createTableStatement.getAutoIncrementConstraints()) { + validationErrors.checkDisallowedField("incrementBy", constraint.getIncrementBy(), database, MySQLDatabase.class); + } + } return validationErrors; } diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/RenameColumnGenerator.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/RenameColumnGenerator.java index dd0f7ccc8fa..17ff78f505e 100644 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/RenameColumnGenerator.java +++ b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/RenameColumnGenerator.java @@ -38,7 +38,7 @@ public Sql[] generateSql(RenameColumnStatement statement, Database database, Sql String sql; if (database instanceof MSSQLDatabase) { // do no escape the new column name. Otherwise it produce "exec sp_rename '[dbo].[person].[usernae]', '[username]'" - sql = "exec sp_rename '" + database.escapeTableName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName()) + "." + database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), statement.getOldColumnName()) + "', '" + statement.getNewColumnName() + "'"; + sql = "exec sp_rename '" + database.escapeTableName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName()) + "." + database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), statement.getOldColumnName()) + "', '" + statement.getNewColumnName() + "', 'COLUMN'"; } else if (database instanceof MySQLDatabase) { sql ="ALTER TABLE " + database.escapeTableName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName()) + " CHANGE " + database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), statement.getOldColumnName()) + " " + database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), statement.getNewColumnName()) + " " + DataTypeFactory.getInstance().fromDescription(statement.getColumnDataType(), database).toDatabaseDataType(database); } else if (database instanceof SybaseDatabase) { diff --git a/liquibase-core/src/main/resources/liquibase/examples/json/liquibase.properties b/liquibase-core/src/main/resources/liquibase/examples/json/liquibase.properties index 8a1c624db31..ebe9738b269 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/json/liquibase.properties +++ b/liquibase-core/src/main/resources/liquibase/examples/json/liquibase.properties @@ -10,7 +10,7 @@ ## The liquibase.properties file stores properties which do not change often, ## such as database connection information. Properties stored here save time ## and reduce risk of mistyped command line arguments. -## Learn more: https://www.liquibase.org/documentation/config_properties.html +## Learn more: https://docs.liquibase.com/concepts/connections/creating-config-properties.html #### #### ## Note about relative and absolute paths: diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/blank-changelog.sql b/liquibase-core/src/main/resources/liquibase/examples/sql/blank-changelog.sql index b82062b1789..c1209ac1f8e 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/sql/blank-changelog.sql +++ b/liquibase-core/src/main/resources/liquibase/examples/sql/blank-changelog.sql @@ -1,5 +1,5 @@ --liquibase formatted sql -/* https://www.liquibase.org/documentation/sql_format.html */ +/* https://docs.liquibase.com/concepts/changelogs/sql-format.html */ --changeset authorname:1 /* Insert SQL change objects here */ diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.properties b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.properties index a72a1df3ffd..b48726df41d 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.properties +++ b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.properties @@ -10,7 +10,7 @@ ## The liquibase.properties file stores properties which do not change often, ## such as database connection information. Properties stored here save time ## and reduce risk of mistyped command line arguments. -## Learn more: https://www.liquibase.org/documentation/config_properties.html +## Learn more: https://docs.liquibase.com/concepts/connections/creating-config-properties.html #### #### ## Note about relative and absolute paths: diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.psql.conf b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.psql.conf index 5bebccb6223..775c6768b5d 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.psql.conf +++ b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.psql.conf @@ -9,7 +9,7 @@ ## ## The liquibase.psql.conf file stores properties which are used during the ## execution of the PostgreSQL psql tool. -## Learn more: https://www.liquibase.org/documentation/config_properties.html +## Learn more: https://docs.liquibase.com/concepts/connections/creating-config-properties.html #### # The full path to the psql executable. diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.sqlcmd.conf b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.sqlcmd.conf index 1f9d48ba450..59011979cec 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.sqlcmd.conf +++ b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.sqlcmd.conf @@ -9,7 +9,7 @@ ## ## The liquibase.sqlcmd.conf file stores properties which are used during the ## execution of the Microsoft SQLCMD tool. -## Learn more: https://www.liquibase.org/documentation/config_properties.html +## Learn more: https://docs.liquibase.com/concepts/connections/creating-config-properties.html #### #### ## Note about relative and absolute paths: diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.sqlplus.conf b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.sqlplus.conf index 9a748db4eda..09aed232696 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.sqlplus.conf +++ b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.sqlplus.conf @@ -9,7 +9,7 @@ ## ## The liquibase.sqlplus.conf file stores properties which are used during the ## execution of the Oracle SQLPLUS tool. -## Learn more: https://www.liquibase.org/documentation/config_properties.html +## Learn more: https://docs.liquibase.com/concepts/connections/creating-config-properties.html #### #### ## Note about relative and absolute paths: diff --git a/liquibase-core/src/main/resources/liquibase/examples/start-h2.bat b/liquibase-core/src/main/resources/liquibase/examples/start-h2.bat index ce3cb5aa5b1..6bbfb97c28b 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/start-h2.bat +++ b/liquibase-core/src/main/resources/liquibase/examples/start-h2.bat @@ -6,7 +6,7 @@ setlocal enabledelayedexpansion rem %~dp0 is expanded pathname of the current script under NT rem %~p0 is the directory of the current script -if exist %~p0\..\liquibase.jar SET LIQUIBASE_HOME=%~p0.. +if exist %~p0\..\liquibase.bat SET LIQUIBASE_HOME=%~p0.. if "%LIQUIBASE_HOME%"=="" ( FOR /F "tokens=* USEBACKQ" %%g IN (`where liquibase.bat`) do (SET "LIQUIBASE_HOME=%%~dpg") diff --git a/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.properties b/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.properties index 0be11ecb27d..eb865d68499 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.properties +++ b/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.properties @@ -10,7 +10,7 @@ ## The liquibase.properties file stores properties which do not change often, ## such as database connection information. Properties stored here save time ## and reduce risk of mistyped command line arguments. -## Learn more: https://www.liquibase.org/documentation/config_properties.html +## Learn more: https://docs.liquibase.com/concepts/connections/creating-config-properties.html #### #### ## Note about relative and absolute paths: diff --git a/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.psql.conf b/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.psql.conf index 5bebccb6223..775c6768b5d 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.psql.conf +++ b/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.psql.conf @@ -9,7 +9,7 @@ ## ## The liquibase.psql.conf file stores properties which are used during the ## execution of the PostgreSQL psql tool. -## Learn more: https://www.liquibase.org/documentation/config_properties.html +## Learn more: https://docs.liquibase.com/concepts/connections/creating-config-properties.html #### # The full path to the psql executable. diff --git a/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.sqlcmd.conf b/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.sqlcmd.conf index d27bb25ffa3..d08ceca3440 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.sqlcmd.conf +++ b/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.sqlcmd.conf @@ -9,7 +9,7 @@ ## ## The liquibase.sqlcmd.conf file stores properties which are used during the ## execution of the Microsoft SQLCMD tool. -## Learn more: https://www.liquibase.org/documentation/config_properties.html +## Learn more: https://docs.liquibase.com/concepts/connections/creating-config-properties.html #### #### ## Note about relative and absolute paths: diff --git a/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.sqlplus.conf b/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.sqlplus.conf index 281ea92c7ea..7190e4fa204 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.sqlplus.conf +++ b/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.sqlplus.conf @@ -9,7 +9,7 @@ ## ## The liquibase.sqlplus.conf file stores properties which are used during the ## execution of the Oracle SQLPLUS tool. -## Learn more: https://www.liquibase.org/documentation/config_properties.html +## Learn more: https://docs.liquibase.com/concepts/connections/creating-config-properties.html #### #### ## Note about relative and absolute paths: diff --git a/liquibase-core/src/main/resources/liquibase/examples/yaml/blank-changelog.yaml b/liquibase-core/src/main/resources/liquibase/examples/yaml/blank-changelog.yaml index 771e1911fde..f5e984ab87b 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/yaml/blank-changelog.yaml +++ b/liquibase-core/src/main/resources/liquibase/examples/yaml/blank-changelog.yaml @@ -3,10 +3,10 @@ databaseChangeLog: id: 1 author: your.name changes: - # Insert Yaml change objects here https://www.liquibase.org/documentation/yaml_format.html + # Insert Yaml change objects here https://docs.liquibase.com/concepts/changelogs/yaml-format.html - changeSet: id: 2 author: your.name changes: - # Insert Yaml change objects here https://www.liquibase.org/documentation/yaml_format.html + # Insert Yaml change objects here https://docs.liquibase.com/concepts/changelogs/yaml-format.html diff --git a/liquibase-core/src/main/resources/liquibase/examples/yaml/liquibase.properties b/liquibase-core/src/main/resources/liquibase/examples/yaml/liquibase.properties index 0d0db5f7776..b56a8da9daf 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/yaml/liquibase.properties +++ b/liquibase-core/src/main/resources/liquibase/examples/yaml/liquibase.properties @@ -10,7 +10,7 @@ ## The liquibase.properties file stores properties which do not change often, ## such as database connection information. Properties stored here save time ## and reduce risk of mistyped command line arguments. -## Learn more: https://www.liquibase.org/documentation/config_properties.html +## Learn more: https://docs.liquibase.com/concepts/connections/creating-config-properties.html #### #### ## Note about relative and absolute paths: diff --git a/liquibase-core/src/main/resources/liquibase/i18n/liquibase-core.properties b/liquibase-core/src/main/resources/liquibase/i18n/liquibase-core.properties index b34f0a7e98b..b42e19d6616 100644 --- a/liquibase-core/src/main/resources/liquibase/i18n/liquibase-core.properties +++ b/liquibase-core/src/main/resources/liquibase/i18n/liquibase-core.properties @@ -30,11 +30,11 @@ unexpected.value=Unexpected value '%s' (options must start with a '--') cannot.specify.both=Cannot specify both '%s' and '%s' changelogfile.already.exists=Output ChangeLogFile '%s' already exists! force.option.required=The targeted changeset is followed by %d changesets, so unexpected outcomes may occur.\nTo review the rollback SQL, please run '%s'. This message can be suppressed by\nadding the --force flag. -id.author.path.required=You must specify the change set ID, author, and path +id.author.path.required=You must specify the changeset ID, author, and path no.deployment.ids.found=No deployment IDs were located. No rollbacks were performed. no.change.sets.found.for.deployment.id=No changesets were located matching deployment ID '%s'. No rollbacks were performed. deployment.id.required=You must specify the deployment ID. -no.executor.pro.license.found=The Executor '%s' requires a Liquibase Pro license, available at https://www.liquibase.org/download or sales@liquibase.com. Options include the liquibase.licenseKey in the defaults file, adding a flag in the CLI, and more. Learn more at https://docs.liquibase.com. +no.executor.pro.license.found=The Executor '%s' requires a Liquibase Pro license, available at https://www.liquibase.com/pricing or sales@liquibase.com. Options include the liquibase.licenseKey in the defaults file, adding a flag in the CLI, and more. Learn more at https://docs.liquibase.com. no.parameter.pro.license.found=Using '%s' in the '%s' parameter requires a valid Liquibase Pro license.\nGet a free Pro license key at https://liquibase.com/trial and add liquibase.licenseKey= into your defaults file or\nuse --pro-license-key= before your command in the CLI. no.pro.license.found=Using '%s' requires a valid Liquibase Pro license.\nGet a free Pro license key at https://liquibase.com/trial and add liquibase.licenseKey= into your defaults file or\nuse --pro-license-key= before your command in the CLI. attempt.to.delete.the.file.failed.cannot.continue=Attempt to delete the file '%s' failed. Cannot continue. Sorry. @@ -56,15 +56,15 @@ diff.results=Diff Results: cannot.add.clause.with.key.because.it.is.already.defined=Cannot add clause with key '%s' because it is already defined key.must.be.a.non.null.non.empty.value=key must be a non-null, non-empty value validation.failed=Validation Failed: -check.sum.changed=%d change sets check sum +check.sum.changed=%d changesets check sum preconditions.failed=%d preconditions failed preconditions.generated.error=%d preconditions generated an error -change.sets.duplicate.identifiers=%d change sets had duplicate identifiers +change.sets.duplicate.identifiers=%d changesets had duplicate identifiers changes.have.failures=%d changes have failures changes.have.validation.errors=%d changes have validation errors -no.executor.found=Unable to locate Executor '%s' for change set '%s' +no.executor.found=Unable to locate Executor '%s' for changeset '%s' unable.to.validate.changeset=\n%s.\nA %s changeset with runWith='%s' attribute may only contain SQL or sqlFile change types. Learn more at http://docs.liquibaase.com. -split.statements.not.set=\nUnable to validate change set '%s' with Executor '%s'.\nThe 'splitStatements' attribute must be set to 'true' or 'false'. +split.statements.not.set=\nUnable to validate changeset '%s' with Executor '%s'.\nThe 'splitStatements' attribute must be set to 'true' or 'false'. validation.exception=Validation exception changes.have.validation.failures=%d changes have validation failures jdbc.bind.parameter.unknown.numeric.value.type=The column configuration for '%s' returns a numeric value '%s', but we do not know how to hand over numbers of type '%s' to JDBC. @@ -76,4 +76,4 @@ could.not.snapshot.table.to.get.the.missing.column.type.information=Could not sn could.not.release.lock=Could not release lock unable.to.find.column.in.table=Unable to find column '%s' in table '%s' file.not.found=File '%s' not found -loaddata.successful=Data loaded from '%s' into table '%s' \ No newline at end of file +loaddata.successful=Data loaded from '%s' into table '%s' diff --git a/liquibase-core/src/main/resources/www.liquibase.org/xml/ns/dbchangelog/dbchangelog-next.xsd b/liquibase-core/src/main/resources/www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.13.xsd similarity index 100% rename from liquibase-core/src/main/resources/www.liquibase.org/xml/ns/dbchangelog/dbchangelog-next.xsd rename to liquibase-core/src/main/resources/www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.13.xsd diff --git a/liquibase-core/src/main/resources/www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.14.xsd b/liquibase-core/src/main/resources/www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.14.xsd new file mode 100644 index 00000000000..aa5e3f78214 --- /dev/null +++ b/liquibase-core/src/main/resources/www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.14.xsd @@ -0,0 +1,1403 @@ + + + + + + + + + + + + + + Extension to standard XSD boolean type to allow ${} parameters + + + + + + + + + + + + + + + + Extension to standard XSD integer type to allow ${} parameters + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + onChangeLogPreconditionOnSqlOutput determines what should + happen when evaluating this precondition in updateSQL mode. TEST: Run + precondition, FAIL: Fail precondition, IGNORE: Skip precondition check + [DEFAULT] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Used with valueClobFile to specify file encoding explicitly. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true for a cycling sequence, false for a non-cycling sequence. + Default is false. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/liquibase-core/src/main/resources/www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd b/liquibase-core/src/main/resources/www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd index 4da912d984c..aa5e3f78214 100644 --- a/liquibase-core/src/main/resources/www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd +++ b/liquibase-core/src/main/resources/www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd @@ -203,6 +203,7 @@ + @@ -604,7 +605,7 @@ - + diff --git a/liquibase-core/src/test/groovy/liquibase/changelog/ChangeSetTest.groovy b/liquibase-core/src/test/groovy/liquibase/changelog/ChangeSetTest.groovy index 5c8b3155106..92aac0c246e 100644 --- a/liquibase-core/src/test/groovy/liquibase/changelog/ChangeSetTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/changelog/ChangeSetTest.groovy @@ -1,7 +1,10 @@ package liquibase.changelog + +import liquibase.Scope import liquibase.change.CheckSum import liquibase.change.core.* +import liquibase.parser.ChangeLogParserConfiguration import liquibase.parser.core.ParsedNode import liquibase.parser.core.ParsedNodeException import liquibase.precondition.core.RunningAsPrecondition @@ -187,6 +190,39 @@ public class ChangeSetTest extends Specification { changeSet.changes[1].tableName == "table_2" } + def "load node with unknown change types and strict parsing"() { + when: + def changeSet = new ChangeSet(new DatabaseChangeLog("com/example/test.xml")) + def node = new ParsedNode(null, "changeSet") + .addChildren([id: "1", author: "nvoxland"]) + .addChild(new ParsedNode(null, "createTable").addChild(null, "tableName", "table_1")) + .addChild(new ParsedNode(null, "invalid").addChild(null, "tableName", "table_2")) + changeSet.load(node, resourceSupplier.simpleResourceAccessor) + + then: + def e = thrown(ParsedNodeException) + e.message == "Error parsing com/example/test.xml: Unknown change type 'invalid'. Check for spelling or capitalization errors and missing extensions such as liquibase-commercial." + } + + def "load node with unknown change types and lax parsing"() { + when: + def changeSet = new ChangeSet(new DatabaseChangeLog("com/example/test.xml")) + def node = new ParsedNode(null, "changeSet") + .addChildren([id: "1", author: "nvoxland"]) + .addChild(new ParsedNode(null, "createTable").addChild(null, "tableName", "table_1")) + .addChild(new ParsedNode(null, "invalid").addChild(null, "tableName", "table_2")) + + Scope.child([(ChangeLogParserConfiguration.CHANGELOG_PARSE_MODE.getKey()): ChangeLogParserConfiguration.ChangelogParseMode.LAX], { + -> + changeSet.load(node, resourceSupplier.simpleResourceAccessor) + } as Scope.ScopedRunner) + + + then: + notThrown(ParsedNodeException) + changeSet.getChanges().size() == 1 + } + def "load node with rollback containing sql as value"() { when: def changeSet = new ChangeSet(new DatabaseChangeLog("com/example/test.xml")) diff --git a/liquibase-core/src/test/groovy/liquibase/exception/ValidationFailedExceptionTest.groovy b/liquibase-core/src/test/groovy/liquibase/exception/ValidationFailedExceptionTest.groovy index 93157cc422f..f814be85c03 100644 --- a/liquibase-core/src/test/groovy/liquibase/exception/ValidationFailedExceptionTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/exception/ValidationFailedExceptionTest.groovy @@ -90,7 +90,7 @@ class ValidationFailedExceptionTest extends Specification { exception = new ValidationFailedException(handler) } - def "change set with invalid MD5 sum present in validation error message" () { + def "changeset with invalid MD5 sum present in validation error message" () { when: def message = exception.getMessage() @@ -98,7 +98,7 @@ class ValidationFailedExceptionTest extends Specification { message.contains("invalidMd5SumChangeSet") } - def "duplicate change set present in validation error message" () { + def "duplicate changeset present in validation error message" () { when: def message = exception.getMessage() diff --git a/liquibase-core/src/test/groovy/liquibase/parser/core/formattedsql/FormattedSqlChangeLogParserTest.groovy b/liquibase-core/src/test/groovy/liquibase/parser/core/formattedsql/FormattedSqlChangeLogParserTest.groovy index b497178ff77..a41bcaa240a 100644 --- a/liquibase-core/src/test/groovy/liquibase/parser/core/formattedsql/FormattedSqlChangeLogParserTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/parser/core/formattedsql/FormattedSqlChangeLogParserTest.groovy @@ -368,7 +368,7 @@ CREATE TABLE ALL_CAPS_TABLE_2 ( changeLog.getChangeSets().get(20).getId().equalsIgnoreCase("+the_user+") } - def "parse change set with colon in ID"() throws Exception { + def "parse changeset with colon in ID"() throws Exception { when: String changeLogWithOneGoodOneBad = " \n\n" + "--liquibase formatted sql\n\n" + @@ -387,7 +387,7 @@ CREATE TABLE ALL_CAPS_TABLE_2 ( assert changeSet.getId() == "ID:1" } - def "parse change set with invalid change set attributes"() throws Exception { + def "parse changeset with invalid changeset attributes"() throws Exception { when: String changeLogWithInvalidChangeSetAttributes = "--liquibase formatted sql\n\n" + @@ -405,7 +405,7 @@ CREATE TABLE ALL_CAPS_TABLE_2 ( assert e } - def "parse change set with one good one bad"() throws Exception { + def "parse changeset with one good one bad"() throws Exception { when: String changeLogWithOneGoodOneBad = " \n\n" + "--liquibase formatted sql\n\n" + @@ -424,7 +424,7 @@ CREATE TABLE ALL_CAPS_TABLE_2 ( thrown(ChangeLogParseException) } - def "parse change set with only author"() throws Exception { + def "parse changeset with only author"() throws Exception { when: String changeLogWithOnlyAuthor= " \n\n" + "--liquibase formatted sql\n\n" + @@ -513,6 +513,61 @@ CREATE TABLE ALL_CAPS_TABLE_2 ( assert e.getMessage().toLowerCase().contains("-property name") } + def "parse strings that contain keywords not at the beginning"() throws Exception { + when: + def changeLog = new MockFormattedSqlChangeLogParser(""" +--liquibase formatted sql + +--changeset example:1 +not a property here +- not a property here +-- not a property here +not a changeset here +- not a changeset here +-- not a changeset here +not a rollback here +- not a rollback here +-- not a rollback here +not a precondition here +- not a precondition here +-- not a precondition here +not a comment here +- not a comment here +-- not a comment here +not validCheckSum here +- not validCheckSum here +-- not validCheckSum here +not ignoreLines here +- not ignoreLines here +-- not ignoreLines here +""".trim()).parse("asdf.sql", new ChangeLogParameters(), new JUnitResourceAccessor()) + + then: + StringUtil.standardizeLineEndings(((RawSQLChange) changeLog.getChangeSets()[0].getChanges()[0]).getSql().trim()) == StringUtil.standardizeLineEndings(""" +not a property here +- not a property here +-- not a property here +not a changeset here +- not a changeset here +-- not a changeset here +not a rollback here +- not a rollback here +-- not a rollback here +not a precondition here +- not a precondition here +-- not a precondition here +not a comment here +- not a comment here +-- not a comment here +not validCheckSum here +- not validCheckSum here +-- not validCheckSum here +not ignoreLines here +- not ignoreLines here +-- not ignoreLines here +""".trim()) + } + def parse_withComment() throws Exception { when: String changeLogWithComment = "--liquibase formatted sql\n\n" + @@ -569,7 +624,7 @@ CREATE TABLE ALL_CAPS_TABLE_2 ( then: def e = thrown(ChangeLogParseException) assert e : "ChangeLogParseException should be thrown" - assert e.getMessage().contains("do not allow comment lines outside of change sets") + assert e.getMessage().contains("do not allow comment lines outside of changesets") } def parse_withWithIgnoreNotIgnoreLines() { diff --git a/liquibase-core/src/test/groovy/liquibase/parser/core/xml/LiquibaseEntityResolverTest.groovy b/liquibase-core/src/test/groovy/liquibase/parser/core/xml/LiquibaseEntityResolverTest.groovy index 222bc5941d1..67b3c92cfcd 100644 --- a/liquibase-core/src/test/groovy/liquibase/parser/core/xml/LiquibaseEntityResolverTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/parser/core/xml/LiquibaseEntityResolverTest.groovy @@ -1,8 +1,11 @@ package liquibase.parser.core.xml import liquibase.GlobalConfiguration +import liquibase.LiquibaseTest import liquibase.Scope import liquibase.resource.FileSystemResourceAccessor +import liquibase.util.LiquibaseUtil +import org.xml.sax.InputSource import spock.lang.Specification import spock.lang.Unroll @@ -18,13 +21,55 @@ class LiquibaseEntityResolverTest extends Specification { "http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd", "https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd", "http://www.liquibase.org/xml/ns/migrator/dbchangelog-3.1.xsd", - "http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-next.xsd", + "http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd", + "https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd", "http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd", "/liquibase/banner.txt", //can find files without hostnames "http://liquibase/banner.txt", //conversion of hostnames to files works for not just liquibase.org URLs ] } + @Unroll + def "warning message for mismatched xsd and build versions #systemId /// #buildVersion"() { + given: + def uiService = new LiquibaseTest.TestConsoleUIService() + // Save these props for later + def originalProperties = LiquibaseUtil.liquibaseBuildProperties + LiquibaseUtil.liquibaseBuildProperties = new Properties() + LiquibaseUtil.liquibaseBuildProperties.put("build.version", buildVersion) + def er = new LiquibaseEntityResolver() + er.setShouldWarnOnMismatchedXsdVersion(true) + er.hasWarnedAboutMismatchedXsdVersion = false + + expect: + Scope.child([ + (Scope.Attr.ui.name()) : uiService + ], { + er.resolveEntity(null, null, null, systemId) + } as Scope.ScopedRunnerWithReturn) != null + + // This is an ugly assertion line, it is essentially saying, either we expect the message, so make sure it's there + // or we expect no message, so make sure there are no messages. + ((expectedWarningMessage && uiService.getMessages().contains("INFO: An older version of the XSD is specified in one or more changelog's header. This can lead to unexpected outcomes. If a specific XSD is not required, please replace all XSD version references with \"-latest\". Learn more at https://docs.liquibase.com")) + || (!expectedWarningMessage && uiService.getMessages().isEmpty())) + + cleanup: + // Set the build properties back to what they were before the test. + LiquibaseUtil.liquibaseBuildProperties = originalProperties + + where: + buildVersion | systemId | expectedWarningMessage + "3.1.0" | "http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd" | false + "3.1.1" | "http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd" | false + "4.12.0" | "http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd" | true + "4.12.0" | "https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd" | true + "4.12.0" | "http://www.liquibase.org/xml/ns/migrator/dbchangelog-3.1.xsd" | true + "4.12.0" | "http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd" | false + "4.12.0" | "http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd" | false + "4.12.0" | "/liquibase/banner.txt" | false + "4.12.0" | "http://liquibase/banner.txt" | false + } + @Unroll def "resolveEntity finds packaged files correctly even if the configured resourceAccessor doesn't have it"() { expect: diff --git a/liquibase-core/src/test/groovy/liquibase/parser/core/xml/XMLChangeLogSAXParserTest.groovy b/liquibase-core/src/test/groovy/liquibase/parser/core/xml/XMLChangeLogSAXParserTest.groovy index ba733a08c5e..eee93b902fd 100644 --- a/liquibase-core/src/test/groovy/liquibase/parser/core/xml/XMLChangeLogSAXParserTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/parser/core/xml/XMLChangeLogSAXParserTest.groovy @@ -80,7 +80,7 @@ class XMLChangeLogSAXParserTest extends Specification { then: def e = thrown(ChangeLogParseException) - e.message.contains("Unable to resolve xml entity file:///invalid.txt locally: liquibase.secureParsing is set to 'true' which does not allow remote lookups. Set it to 'false' to allow remote lookups of xsd files") + e.message.contains("Unable to resolve xml entity file:///invalid.txt. liquibase.secureParsing is set to 'true'") } def "allows liquibase.secureParsing=false to disable secure parsing"() { @@ -99,7 +99,7 @@ class XMLChangeLogSAXParserTest extends Specification { def "getSchemaVersion"() { expect: - XMLChangeLogSAXParser.getSchemaVersion() == "next" //because test run in an environment with build.version == DEV + XMLChangeLogSAXParser.getSchemaVersion() == "latest" //because test run in an environment with build.version == DEV } @Unroll @@ -109,12 +109,12 @@ class XMLChangeLogSAXParserTest extends Specification { where: buildVersion | expected - "DEV" | "next" + "DEV" | "latest" "4.11.0" | "4.11" "4.11.1" | "4.11" - "4" | "next" //weird versions go to next - "" | "next" //weird versions go to next - null | "next" //weird versions go to next + "4" | "latest" //weird versions go to latest + "" | "latest" //weird versions go to latest + null | "latest" //weird versions go to latest } } diff --git a/liquibase-core/src/test/groovy/liquibase/parser/core/xml/XMLChangeLogSAXParser_RealFile_Test.groovy b/liquibase-core/src/test/groovy/liquibase/parser/core/xml/XMLChangeLogSAXParser_RealFile_Test.groovy index 5823476a3c0..6a40e2117be 100644 --- a/liquibase-core/src/test/groovy/liquibase/parser/core/xml/XMLChangeLogSAXParser_RealFile_Test.groovy +++ b/liquibase-core/src/test/groovy/liquibase/parser/core/xml/XMLChangeLogSAXParser_RealFile_Test.groovy @@ -697,7 +697,7 @@ public class XMLChangeLogSAXParser_RealFile_Test extends Specification { Scope.getCurrentScope().getSingleton(ChangeFactory.class).unregister("createTableExample") } - def "change sets with matching dbms are parsed"() { + def "changesets with matching dbms are parsed"() { when: def path = "liquibase/parser/core/xml/rollbackWithDbmsChangeLog.xml" def database = new MSSQLDatabase() @@ -707,7 +707,7 @@ public class XMLChangeLogSAXParser_RealFile_Test extends Specification { changeLog.getChangeSets().size() == 4 } - def "change sets with non-matching dbms are skipped"() { + def "changesets with non-matching dbms are skipped"() { when: def path = "liquibase/parser/core/xml/rollbackWithDbmsChangeLog.xml" def database = new H2Database() @@ -717,7 +717,7 @@ public class XMLChangeLogSAXParser_RealFile_Test extends Specification { changeLog.getChangeSets().size() == 2 } - def "change sets exclude matching-excluded dbms"() { + def "changesets exclude matching-excluded dbms"() { when: def path = "liquibase/parser/core/xml/excludeDbmsChangeLog.xml" def database = new MSSQLDatabase() @@ -730,7 +730,7 @@ public class XMLChangeLogSAXParser_RealFile_Test extends Specification { change1.getColumns().get(0).getType() == "varchar(50)" } - def "change sets include non-matching-excluded dbms"() { + def "changesets include non-matching-excluded dbms"() { when: def path = "liquibase/parser/core/xml/excludeDbmsChangeLog.xml" def database = new H2Database() diff --git a/liquibase-core/src/test/groovy/liquibase/parser/core/yaml/YamlChangeLogParser_RealFile_Test.groovy b/liquibase-core/src/test/groovy/liquibase/parser/core/yaml/YamlChangeLogParser_RealFile_Test.groovy index a42e92b307c..f269d61df2f 100644 --- a/liquibase-core/src/test/groovy/liquibase/parser/core/yaml/YamlChangeLogParser_RealFile_Test.groovy +++ b/liquibase-core/src/test/groovy/liquibase/parser/core/yaml/YamlChangeLogParser_RealFile_Test.groovy @@ -300,29 +300,6 @@ public class YamlChangeLogParser_RealFile_Test extends Specification { assert e.message.startsWith("Syntax error in file liquibase/parser/core/yaml/malformedChangeLog.yaml") } - def "elements that don't correspond to anything in liquibase are ignored"() throws Exception { - def path = "liquibase/parser/core/yaml/unusedTagsChangeLog.yaml" - expect: - DatabaseChangeLog changeLog = new YamlChangeLogParser().parse(path, new ChangeLogParameters(), new JUnitResourceAccessor()); - - changeLog.getLogicalFilePath() == path - changeLog.getPhysicalFilePath() == path - - changeLog.getPreconditions().getNestedPreconditions().size() == 0 - changeLog.getChangeSets().size() == 1 - - ChangeSet changeSet = changeLog.getChangeSets().get(0); - changeSet.getAuthor() == "nvoxland" - changeSet.getId() == "1" - changeSet.getChanges().size() == 1 - changeSet.getFilePath() == path - changeSet.getComments() == "Some comments go here" - - Change change = changeSet.getChanges().get(0); - Scope.getCurrentScope().getSingleton(ChangeFactory.class).getChangeMetaData(change).getName() == "createTable" - assert change instanceof CreateTableChange - } - def "changeLog parameters are correctly expanded"() throws Exception { when: def params = new ChangeLogParameters(new MockDatabase()); @@ -551,7 +528,7 @@ public class YamlChangeLogParser_RealFile_Test extends Specification { ((AddColumnChange) changeLog.getChangeSet(path, "nvoxland", "different object types for column").changes[1]).columns[3].defaultValueComputed.toString() == "average_size()" ((AddColumnChange) changeLog.getChangeSet(path, "nvoxland", "different object types for column").changes[1]).columns[4].name == "new_col_datetime" - new ISODateFormat().format(new java.sql.Timestamp(((AddColumnChange) changeLog.getChangeSet(path, "nvoxland", "different object types for column").changes[1]).columns[4].defaultValueDate.time)).matches(/2014-12-\d+T\d+:15:33/) //timezones shift actual value around + new ISODateFormat().format(new java.sql.Timestamp(((AddColumnChange) changeLog.getChangeSet(path, "nvoxland", "different object types for column").changes[1]).columns[4].defaultValueDate.time)).matches(/2014-12-\d+T\d+:\d+:33/) //timezones shift actual value around ((AddColumnChange) changeLog.getChangeSet(path, "nvoxland", "different object types for column").changes[1]).columns[5].name == "new_col_seq" ((AddColumnChange) changeLog.getChangeSet(path, "nvoxland", "different object types for column").changes[1]).columns[5].defaultValueSequenceNext.toString() == "seq_test" diff --git a/liquibase-core/src/test/groovy/liquibase/precondition/core/PreconditionContainerTest.groovy b/liquibase-core/src/test/groovy/liquibase/precondition/core/PreconditionContainerTest.groovy index 8cf9b1ccce9..2f19abdfc45 100644 --- a/liquibase-core/src/test/groovy/liquibase/precondition/core/PreconditionContainerTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/precondition/core/PreconditionContainerTest.groovy @@ -1,6 +1,9 @@ package liquibase.precondition.core +import liquibase.GlobalConfiguration +import liquibase.Scope import liquibase.exception.SetupException +import liquibase.parser.ChangeLogParserConfiguration import liquibase.parser.core.ParsedNode import liquibase.parser.core.ParsedNodeException import liquibase.sdk.supplier.resource.ResourceSupplier @@ -9,7 +12,8 @@ import spock.lang.Specification class PreconditionContainerTest extends Specification { - @Shared resourceSupplier = new ResourceSupplier() + @Shared + resourceSupplier = new ResourceSupplier() def "load handles empty node with params"() { when: @@ -101,8 +105,8 @@ class PreconditionContainerTest extends Specification { def node = new ParsedNode(null, "preConditions").addChildren([onFail: "MARK_RAN"]) .addChild(new ParsedNode(null, "runningAs").addChildren([username: "my_user"])) .addChild(new ParsedNode(null, "or") - .addChildren([runningAs: [username: "other_user"]]) - .addChildren([runningAs: [username: "yet_other_user"]]) + .addChildren([runningAs: [username: "other_user"]]) + .addChildren([runningAs: [username: "yet_other_user"]]) ) .addChild(new ParsedNode(null, "tableExists").addChildren([tableName: "my_table"])) @@ -128,4 +132,35 @@ class PreconditionContainerTest extends Specification { } + def "load handles node with unknown preconditions in strict mode"() { + when: + def node = new ParsedNode(null, "preConditions").addChildren([onFail: "MARK_RAN"]) + .addChild(new ParsedNode(null, "invalid").addChildren([tableName: "my_table"])) + .addChild(new ParsedNode(null, "tableExists").addChildren([tableName: "my_table"])) + + def container = new PreconditionContainer() + container.load(node, resourceSupplier.simpleResourceAccessor) + + then: + def e = thrown(ParsedNodeException) + e.message == "Unknown precondition 'invalid'. Check for spelling or capitalization errors and missing extensions such as liquibase-commercial." + } + + def "load handles node with unknown preconditions in lax mode"() { + when: + def node = new ParsedNode(null, "preConditions").addChildren([onFail: "MARK_RAN"]) + .addChild(new ParsedNode(null, "invalid").addChildren([tableName: "my_table"])) + .addChild(new ParsedNode(null, "tableExists").addChildren([tableName: "my_table"])) + + def container = new PreconditionContainer() + Scope.currentScope.child([(ChangeLogParserConfiguration.CHANGELOG_PARSE_MODE.key): ChangeLogParserConfiguration.ChangelogParseMode.LAX], { + -> + container.load(node, resourceSupplier.simpleResourceAccessor) + } as Scope.ScopedRunner) + + + then: + notThrown(ParsedNodeException) + container.getNestedPreconditions().size() == 1 + } } diff --git a/liquibase-core/src/test/java/liquibase/database/AbstractJdbcDatabaseTest.java b/liquibase-core/src/test/java/liquibase/database/AbstractJdbcDatabaseTest.java index da4f96d13b7..bb9c5e1fb6e 100644 --- a/liquibase-core/src/test/java/liquibase/database/AbstractJdbcDatabaseTest.java +++ b/liquibase-core/src/test/java/liquibase/database/AbstractJdbcDatabaseTest.java @@ -1,7 +1,14 @@ package liquibase.database; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import java.util.ArrayList; +import java.util.List; +import org.junit.Test; import liquibase.Scope; import liquibase.change.core.CreateTableChange; +import liquibase.exception.DatabaseException; import liquibase.executor.ExecutorService; import liquibase.sdk.executor.MockExecutor; import liquibase.sql.visitor.AppendSqlVisitor; @@ -9,14 +16,6 @@ import liquibase.statement.SqlStatement; import liquibase.statement.core.DropTableStatement; import liquibase.structure.core.Table; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; /** * Base test class for database-specific tests @@ -88,14 +87,14 @@ public void defaultsWorkWithoutAConnection() { // } @Test - public void escapeTableName_noSchema() { - Database database = getDatabase(); + public void escapeTableName_noSchema() throws DatabaseException { + final Database database = getDatabase(); assertEquals("tableName", database.escapeTableName(null, null, "tableName")); } @Test - public void escapeTableName_withSchema() { - Database database = getDatabase(); + public void escapeTableName_withSchema() throws DatabaseException { + final Database database = getDatabase(); if (database.supportsCatalogInObjectName(Table.class)) { assertEquals("catalogName.schemaName.tableName", database.escapeTableName("catalogName", "schemaName", "tableName")); } else { @@ -283,7 +282,7 @@ public void test_escapeObjectName() { assertTrue(tableName.matches("[\\[\\\"`]?My Table [\\]\\\"`]?")); tableName = database.escapeObjectName("MyTable", Table.class); - assertTrue(tableName.equals("MyTable")); + assertEquals("MyTable", tableName); tableName = database.escapeObjectName("My Table", Table.class); assertTrue(tableName.matches("[\\[\\\"`]?My Table[\\]\\\"`]?")); diff --git a/liquibase-core/src/test/java/liquibase/database/ConnectionServiceFactoryTest.java b/liquibase-core/src/test/java/liquibase/database/ConnectionServiceFactoryTest.java index efe63fa3167..0d5ac9e2490 100644 --- a/liquibase-core/src/test/java/liquibase/database/ConnectionServiceFactoryTest.java +++ b/liquibase-core/src/test/java/liquibase/database/ConnectionServiceFactoryTest.java @@ -1,13 +1,9 @@ package liquibase.database; -import liquibase.database.jvm.JdbcConnection; +import static org.assertj.core.api.Assertions.assertThat; import org.junit.Before; import org.junit.Test; - -import java.sql.Driver; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; +import liquibase.database.jvm.JdbcConnection; public class ConnectionServiceFactoryTest { diff --git a/liquibase-core/src/test/java/liquibase/database/core/AbstractDb2DatabaseTest.java b/liquibase-core/src/test/java/liquibase/database/core/AbstractDb2DatabaseTest.java index db99a27a6c8..7690ebb352f 100644 --- a/liquibase-core/src/test/java/liquibase/database/core/AbstractDb2DatabaseTest.java +++ b/liquibase-core/src/test/java/liquibase/database/core/AbstractDb2DatabaseTest.java @@ -1,15 +1,19 @@ package liquibase.database.core; import junit.framework.TestCase; -import liquibase.database.Database; +import liquibase.exception.DatabaseException; public class AbstractDb2DatabaseTest extends TestCase { - public void testGetDateLiteral() { - AbstractDb2Database database = new DB2Database(); - assertEquals("DATE('2018-12-31')", database.getDateLiteral("2018-12-31")); - assertEquals("TIME('23:58:59')", database.getDateLiteral("23:58:59")); - assertEquals("TIMESTAMP('2018-12-31 23:58:59')", database.getDateLiteral("2018-12-31 23:58:59")); - assertEquals("UNSUPPORTED:foo", database.getDateLiteral("foo")); + public void testGetDateLiteral() throws DatabaseException { + try (AbstractDb2Database database = new DB2Database()) { + assertEquals("DATE('2018-12-31')", database.getDateLiteral("2018-12-31")); + assertEquals("TIME('23:58:59')", database.getDateLiteral("23:58:59")); + assertEquals("TIMESTAMP('2018-12-31 23:58:59')", database.getDateLiteral("2018-12-31 23:58:59")); + assertEquals("UNSUPPORTED:foo", database.getDateLiteral("foo")); + } catch (final DatabaseException e) { + throw e; + } } + } diff --git a/liquibase-core/src/test/java/liquibase/database/core/DB2DatabaseTest.java b/liquibase-core/src/test/java/liquibase/database/core/DB2DatabaseTest.java index 33a017efd7c..9546275e1a4 100644 --- a/liquibase-core/src/test/java/liquibase/database/core/DB2DatabaseTest.java +++ b/liquibase-core/src/test/java/liquibase/database/core/DB2DatabaseTest.java @@ -2,15 +2,18 @@ import junit.framework.TestCase; import liquibase.database.Database; +import liquibase.exception.DatabaseException; public class DB2DatabaseTest extends TestCase { - public void testGetDefaultDriver() { - Database database = new DB2Database(); - assertEquals("com.ibm.db2.jcc.DB2Driver", database.getDefaultDriver("jdbc:db2://localhost:50000/liquibas")); + public void testGetDefaultDriver() throws DatabaseException { + try (Database database = new DB2Database()) { + assertEquals("com.ibm.db2.jcc.DB2Driver", database.getDefaultDriver("jdbc:db2://localhost:50000/liquibas")); - assertNull(database.getDefaultDriver("jdbc:oracle://localhost;databaseName=liquibase")); + assertNull(database.getDefaultDriver("jdbc:oracle://localhost;databaseName=liquibase")); + } catch (final DatabaseException e) { + throw e; + } } - } diff --git a/liquibase-core/src/test/java/liquibase/database/core/DB2zDatabaseTest.java b/liquibase-core/src/test/java/liquibase/database/core/DB2zDatabaseTest.java index 95750b66846..9b3533f538d 100644 --- a/liquibase-core/src/test/java/liquibase/database/core/DB2zDatabaseTest.java +++ b/liquibase-core/src/test/java/liquibase/database/core/DB2zDatabaseTest.java @@ -2,15 +2,18 @@ import junit.framework.TestCase; import liquibase.database.Database; +import liquibase.exception.DatabaseException; public class DB2zDatabaseTest extends TestCase { - public void testGetDefaultDriver() { - Database database = new Db2zDatabase(); - assertEquals("com.ibm.db2.jcc.DB2Driver", database.getDefaultDriver("jdbc:db2://localhost:50000/liquibas")); + public void testGetDefaultDriver() throws DatabaseException { + try (Database database = new Db2zDatabase()) { + assertEquals("com.ibm.db2.jcc.DB2Driver", database.getDefaultDriver("jdbc:db2://localhost:50000/liquibas")); - assertNull(database.getDefaultDriver("jdbc:oracle://localhost;databaseName=liquibase")); + assertNull(database.getDefaultDriver("jdbc:oracle://localhost;databaseName=liquibase")); + } catch (final DatabaseException e) { + throw e; + } } - } diff --git a/liquibase-core/src/test/java/liquibase/database/core/DerbyDatabaseTest.java b/liquibase-core/src/test/java/liquibase/database/core/DerbyDatabaseTest.java index 5b2032eec16..68eb67178d5 100644 --- a/liquibase-core/src/test/java/liquibase/database/core/DerbyDatabaseTest.java +++ b/liquibase-core/src/test/java/liquibase/database/core/DerbyDatabaseTest.java @@ -1,7 +1,7 @@ package liquibase.database.core; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.RETURNS_SMART_NULLS; -import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -19,12 +19,15 @@ import liquibase.exception.DatabaseException; public class DerbyDatabaseTest extends TestCase { - public void testGetDefaultDriver() { - Database database = new DerbyDatabase(); - assertEquals("org.apache.derby.jdbc.EmbeddedDriver", database.getDefaultDriver("java:derby:liquibase;create=true")); + public void testGetDefaultDriver() throws DatabaseException { + try (Database database = new DerbyDatabase()) { + assertEquals("org.apache.derby.jdbc.EmbeddedDriver", database.getDefaultDriver("java:derby:liquibase;create=true")); - assertNull(database.getDefaultDriver("jdbc:oracle://localhost;databaseName=liquibase")); + assertNull(database.getDefaultDriver("jdbc:oracle://localhost;databaseName=liquibase")); + } catch (final DatabaseException e) { + throw e; + } } public void testGetDateLiteral() { diff --git a/liquibase-core/src/test/java/liquibase/database/core/MSSQLDatabaseTest.java b/liquibase-core/src/test/java/liquibase/database/core/MSSQLDatabaseTest.java index fd965be4d15..fffb58f4121 100644 --- a/liquibase-core/src/test/java/liquibase/database/core/MSSQLDatabaseTest.java +++ b/liquibase-core/src/test/java/liquibase/database/core/MSSQLDatabaseTest.java @@ -1,10 +1,15 @@ package liquibase.database.core; -import liquibase.database.*; -import liquibase.test.JUnitResourceAccessor; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; -import static org.junit.Assert.*; +import org.junit.Test; +import liquibase.database.AbstractJdbcDatabaseTest; +import liquibase.database.Database; +import liquibase.database.DatabaseFactory; +import liquibase.exception.DatabaseException; /** * Tests for {@link MSSQLDatabase} @@ -20,7 +25,6 @@ protected String getProductNameString() { return "Microsoft SQL Server"; } - @Override @Test public void supportsInitiallyDeferrableColumns() { @@ -34,31 +38,38 @@ public void getCurrentDateTimeFunction() { } @Test - public void getDefaultDriver() { - Database database = new MSSQLDatabase(); - - assertEquals("com.microsoft.sqlserver.jdbc.SQLServerDriver", database.getDefaultDriver("jdbc:sqlserver://localhost;databaseName=liquibase")); - - assertNull(database.getDefaultDriver("jdbc:oracle:thin://localhost;databaseName=liquibase")); + public void getDefaultDriver() throws DatabaseException { + try (Database database = new MSSQLDatabase()) { + assertEquals("com.microsoft.sqlserver.jdbc.SQLServerDriver", database.getDefaultDriver("jdbc:sqlserver://localhost;databaseName=liquibase")); + + assertNull(database.getDefaultDriver("jdbc:oracle:thin://localhost;databaseName=liquibase")); + } catch (final DatabaseException e) { + throw e; + } } @Override @Test - public void escapeTableName_noSchema() { - Database database = new MSSQLDatabase(); - assertEquals("tableName", database.escapeTableName(null, null, "tableName")); - assertEquals("[tableName€]", database.escapeTableName(null, null, "tableName€")); + public void escapeTableName_noSchema() throws DatabaseException { + try (Database database = new MSSQLDatabase()) { + assertEquals("tableName", database.escapeTableName(null, null, "tableName")); + assertEquals("[tableName€]", database.escapeTableName(null, null, "tableName€")); + } catch (final DatabaseException e) { + throw e; + } } @Override @Test - public void escapeTableName_withSchema() { - Database database = new MSSQLDatabase(); - assertEquals("catalogName.schemaName.tableName", database.escapeTableName("catalogName", "schemaName", - "tableName")); - assertEquals("[catalogName€].[schemaName€].[tableName€]", database.escapeTableName("catalogName€", - "schemaName€", "tableName€")); + public void escapeTableName_withSchema() throws DatabaseException { + try (Database database = new MSSQLDatabase()) { + assertEquals("catalogName.schemaName.tableName", database.escapeTableName("catalogName", "schemaName", "tableName")); + assertEquals("[catalogName€].[schemaName€].[tableName€]", database.escapeTableName("catalogName€", "schemaName€", "tableName€")); + } catch (final DatabaseException e) { + throw e; + } } + private Database createOfflineDatabase(String url) throws Exception { return DatabaseFactory.getInstance().openDatabase(url, null, null, null, null); } @@ -68,15 +79,15 @@ public void setDefaultSchemaName() throws Exception { // // No exception should be thrown by call to setDefaultSchemaName // - Database database = createOfflineDatabase("offline:mssql"); + final Database database = createOfflineDatabase("offline:mssql"); database.setDefaultSchemaName("MySchema"); } @Test public void isUnmodifiable() throws Exception { - Database database = createOfflineDatabase("offline:mssql"); + final Database database = createOfflineDatabase("offline:mssql"); assertTrue(database instanceof MSSQLDatabase); - MSSQLDatabase mssqlDatabase = (MSSQLDatabase)database; + final MSSQLDatabase mssqlDatabase = (MSSQLDatabase) database; assertTrue(mssqlDatabase.dataTypeIsNotModifiable("datetime")); } diff --git a/liquibase-core/src/test/java/liquibase/database/core/MySQLDatabaseTest.java b/liquibase-core/src/test/java/liquibase/database/core/MySQLDatabaseTest.java index dc0f0c411d4..6b0aa06595a 100644 --- a/liquibase-core/src/test/java/liquibase/database/core/MySQLDatabaseTest.java +++ b/liquibase-core/src/test/java/liquibase/database/core/MySQLDatabaseTest.java @@ -1,13 +1,15 @@ package liquibase.database.core; -import liquibase.database.AbstractJdbcDatabase; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; + +import org.junit.Assert; +import org.junit.Test; import liquibase.database.AbstractJdbcDatabaseTest; import liquibase.database.Database; +import liquibase.exception.DatabaseException; import liquibase.statement.DatabaseFunction; -import org.junit.Assert; -import org.junit.Test; - -import static org.junit.Assert.*; /** * Tests for {@link MySQLDatabase} @@ -20,7 +22,7 @@ public MySQLDatabaseTest() throws Exception { @Override protected String getProductNameString() { - return "MySQL"; + return "MySQL"; } @Override @@ -29,8 +31,6 @@ public void supportsInitiallyDeferrableColumns() { assertFalse(getDatabase().supportsInitiallyDeferrableColumns()); } - - @Override @Test public void getCurrentDateTimeFunction() { @@ -39,7 +39,7 @@ public void getCurrentDateTimeFunction() { @Test public void getCurrentDateTimeFunctionWithPrecision() { - MySQLDatabase mySQLDatabase = (MySQLDatabase) getDatabase(); + final MySQLDatabase mySQLDatabase = (MySQLDatabase) getDatabase(); Assert.assertEquals("NOW(1)", mySQLDatabase.getCurrentDateTimeFunction(1)); Assert.assertEquals("NOW(2)", mySQLDatabase.getCurrentDateTimeFunction(2)); Assert.assertEquals("NOW(5)", mySQLDatabase.getCurrentDateTimeFunction(5)); @@ -47,43 +47,45 @@ public void getCurrentDateTimeFunctionWithPrecision() { @Test public void generateDatabaseFunctionValue() { - MySQLDatabase mySQLDatabase = (MySQLDatabase) getDatabase(); + final MySQLDatabase mySQLDatabase = (MySQLDatabase) getDatabase(); assertEquals("NOW()", mySQLDatabase.generateDatabaseFunctionValue(new DatabaseFunction("CURRENT_TIMESTAMP()"))); assertNull(mySQLDatabase.generateDatabaseFunctionValue(new DatabaseFunction(null))); } @Test public void generateDatabaseFunctionValueWithPrecision() { - MySQLDatabase mySQLDatabase = (MySQLDatabase) getDatabase(); + final MySQLDatabase mySQLDatabase = (MySQLDatabase) getDatabase(); assertEquals("NOW(2)", mySQLDatabase.generateDatabaseFunctionValue(new DatabaseFunction("CURRENT_TIMESTAMP(2)"))); assertEquals("NOW(3)", mySQLDatabase.generateDatabaseFunctionValue(new DatabaseFunction("CURRENT_TIMESTAMP(3)"))); } @Test public void generateDatabaseFunctionValueWithIncorrectPrecision() { - MySQLDatabase mySQLDatabase = (MySQLDatabase) getDatabase(); + final MySQLDatabase mySQLDatabase = (MySQLDatabase) getDatabase(); assertEquals("NOW()", mySQLDatabase.generateDatabaseFunctionValue(new DatabaseFunction("CURRENT_TIMESTAMP(string)"))); } - public void testGetDefaultDriver() { - Database database = new MySQLDatabase(); - - assertEquals("com.mysql.cj.jdbc.Driver", database.getDefaultDriver("jdbc:mysql://localhost/liquibase")); + public void testGetDefaultDriver() throws DatabaseException { + try (Database database = new MySQLDatabase()) { + assertEquals("com.mysql.cj.jdbc.Driver", database.getDefaultDriver("jdbc:mysql://localhost/liquibase")); - assertNull(database.getDefaultDriver("jdbc:db2://localhost;databaseName=liquibase")); + assertNull(database.getDefaultDriver("jdbc:db2://localhost;databaseName=liquibase")); + } catch (final DatabaseException e) { + throw e; + } } @Override @Test public void escapeTableName_noSchema() { - Database database = getDatabase(); + final Database database = getDatabase(); assertEquals("tableName", database.escapeTableName(null, null, "tableName")); } @Override @Test public void escapeTableName_withSchema() { - Database database = getDatabase(); + final Database database = getDatabase(); assertEquals("catalogName.tableName", database.escapeTableName("catalogName", "schemaName", "tableName")); } diff --git a/liquibase-core/src/test/java/liquibase/database/core/OracleDatabaseTest.java b/liquibase-core/src/test/java/liquibase/database/core/OracleDatabaseTest.java index f75d10efb5d..a86dff84874 100644 --- a/liquibase-core/src/test/java/liquibase/database/core/OracleDatabaseTest.java +++ b/liquibase-core/src/test/java/liquibase/database/core/OracleDatabaseTest.java @@ -1,5 +1,17 @@ package liquibase.database.core; +import static java.util.ResourceBundle.getBundle; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.ResourceBundle; + +import org.hamcrest.CoreMatchers; +import org.junit.Assert; +import org.junit.Test; import liquibase.Scope; import liquibase.database.AbstractJdbcDatabaseTest; import liquibase.database.Database; @@ -7,6 +19,7 @@ import liquibase.database.OfflineConnection; import liquibase.datatype.DatabaseDataType; import liquibase.datatype.core.TimestampType; +import liquibase.exception.DatabaseException; import liquibase.exception.LiquibaseException; import liquibase.executor.ExecutorService; import liquibase.resource.ResourceAccessor; @@ -16,18 +29,6 @@ import liquibase.statement.SqlStatement; import liquibase.statement.core.UpdateStatement; import liquibase.test.JUnitResourceAccessor; -import org.hamcrest.CoreMatchers; -import org.junit.Assert; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.ResourceBundle; - -import static java.util.ResourceBundle.getBundle; -import static org.junit.Assert.*; - -import org.hamcrest.CoreMatchers; -import org.junit.Test; /** * Tests for {@link liquibase.database.core.OracleDatabase}. @@ -48,72 +49,67 @@ protected String getProductNameString() { @Override @Test public void escapeTableName_noSchema() { - Database database = getDatabase(); - assertEquals("table name without schema is correctly escaped as simply tableName", - "tableName", database.escapeTableName(null, null, "tableName")); + final Database database = getDatabase(); + assertEquals("table name without schema is correctly escaped as simply tableName", "tableName", database.escapeTableName(null, null, "tableName")); } @Test public void saveNlsEnvironment() throws Exception { - Database database = getDatabase(); - ResourceAccessor junitResourceAccessor = new JUnitResourceAccessor(); - OfflineConnection offlineConnection = new OfflineConnection("offline:oracle", junitResourceAccessor); + final Database database = getDatabase(); + final ResourceAccessor junitResourceAccessor = new JUnitResourceAccessor(); + final OfflineConnection offlineConnection = new OfflineConnection("offline:oracle", junitResourceAccessor); database.setConnection(offlineConnection); } @Override @Test public void escapeTableName_withSchema() { - Database database = getDatabase(); - assertEquals("table name without schema but with catalog is correctly escaped as catalogName.tableName", - "catalogName.tableName", database.escapeTableName("catalogName", "schemaName", "tableName")); + final Database database = getDatabase(); + assertEquals("table name without schema but with catalog is correctly escaped as catalogName.tableName", "catalogName.tableName", database.escapeTableName("catalogName", "schemaName", "tableName")); } @Override @Test public void supportsInitiallyDeferrableColumns() { - assertTrue("Oracle Database is correctly reported as being able to do INITIALLY DEFERRED column constraints.", - getDatabase().supportsInitiallyDeferrableColumns()); + assertTrue("Oracle Database is correctly reported as being able to do INITIALLY DEFERRED column constraints.", getDatabase().supportsInitiallyDeferrableColumns()); } - @Override @Test public void getCurrentDateTimeFunction() { - Assert.assertEquals("Oracle Database's 'give me the current timestamp' function is correctly reported.", - "SYSTIMESTAMP", getDatabase().getCurrentDateTimeFunction()); + Assert.assertEquals("Oracle Database's 'give me the current timestamp' function is correctly reported.", "SYSTIMESTAMP", getDatabase().getCurrentDateTimeFunction()); } @Test public void verifyTimestampDataTypeWhenWithoutClauseIsPresent() { - TimestampType ts = new TimestampType(); + final TimestampType ts = new TimestampType(); ts.setAdditionalInformation("WITHOUT TIME ZONE"); - DatabaseDataType oracleDataType = ts.toDatabaseDataType(getDatabase()); + final DatabaseDataType oracleDataType = ts.toDatabaseDataType(getDatabase()); assertThat(oracleDataType.getType(), CoreMatchers.is("TIMESTAMP")); } - public void testGetDefaultDriver() { - Database database = new OracleDatabase(); - - assertEquals("The correct JDBC driver class name is reported if the URL is a Oracle JDBC URL", - "oracle.jdbc.OracleDriver", database.getDefaultDriver("jdbc:oracle:thin:@localhost/XE")); + public void testGetDefaultDriver() throws DatabaseException { + try (Database database = new OracleDatabase()) { + assertEquals("The correct JDBC driver class name is reported if the URL is a Oracle JDBC URL", "oracle.jdbc.OracleDriver", database.getDefaultDriver("jdbc:oracle:thin:@localhost/XE")); - assertNull("No JDBC driver class is returned if the URL is NOT an Oracle Database JDBC URL.", - database.getDefaultDriver("jdbc:db2://localhost;databaseName=liquibase")); + assertNull("No JDBC driver class is returned if the URL is NOT an Oracle Database JDBC URL.", database.getDefaultDriver("jdbc:db2://localhost;databaseName=liquibase")); + } catch (final DatabaseException e) { + throw e; + } } @Test public void validateCore2953WrongSqlOnValueSequenceNext() throws LiquibaseException { - Database database = getDatabase(); + final Database database = getDatabase(); database.setObjectQuotingStrategy(ObjectQuotingStrategy.QUOTE_ALL_OBJECTS); database.setDefaultSchemaName("sampleschema"); - MockExecutor mockExecutor = new MockExecutor(); + final MockExecutor mockExecutor = new MockExecutor(); mockExecutor.setDatabase(database); Scope.getCurrentScope().getSingleton(ExecutorService.class).setExecutor("jdbc", database, mockExecutor); - UpdateStatement updateStatement = new UpdateStatement(null, null, "test_table"); + final UpdateStatement updateStatement = new UpdateStatement(null, null, "test_table"); updateStatement.addNewColumnValue("id", new SequenceNextValueFunction("test_table_id_seq")); database.execute(new SqlStatement[]{updateStatement}, new ArrayList()); diff --git a/liquibase-core/src/test/java/liquibase/database/core/PostgresDatabaseTest.java b/liquibase-core/src/test/java/liquibase/database/core/PostgresDatabaseTest.java index 87bf907ddc8..7ed5ed54439 100644 --- a/liquibase-core/src/test/java/liquibase/database/core/PostgresDatabaseTest.java +++ b/liquibase-core/src/test/java/liquibase/database/core/PostgresDatabaseTest.java @@ -1,16 +1,19 @@ package liquibase.database.core; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Assert; +import org.junit.Test; import liquibase.GlobalConfiguration; import liquibase.changelog.column.LiquibaseColumn; import liquibase.database.AbstractJdbcDatabaseTest; import liquibase.database.Database; import liquibase.database.ObjectQuotingStrategy; +import liquibase.exception.DatabaseException; import liquibase.structure.core.Table; import liquibase.util.StringUtil; -import org.junit.Assert; -import org.junit.Test; - -import static org.junit.Assert.*; /** * Tests for {@link PostgresDatabase} @@ -49,12 +52,14 @@ public void testCheckDatabaseChangeLogTable() throws Exception { ; //TODO: test has troubles, fix later } - public void testGetDefaultDriver() { - Database database = new PostgresDatabase(); - - assertEquals("org.postgresql.Driver", database.getDefaultDriver("jdbc:postgresql://localhost/liquibase")); + public void testGetDefaultDriver() throws DatabaseException { + try (Database database = new PostgresDatabase()) { + assertEquals("org.postgresql.Driver", database.getDefaultDriver("jdbc:postgresql://localhost/liquibase")); - assertNull(database.getDefaultDriver("jdbc:db2://localhost;databaseName=liquibase")); + assertNull(database.getDefaultDriver("jdbc:db2://localhost;databaseName=liquibase")); + } catch (final DatabaseException e) { + throw e; + } } diff --git a/liquibase-core/src/test/java/liquibase/database/core/UnsupportedDatabaseTest.java b/liquibase-core/src/test/java/liquibase/database/core/UnsupportedDatabaseTest.java index a1c23c9e4f3..eb0bb10ae39 100644 --- a/liquibase-core/src/test/java/liquibase/database/core/UnsupportedDatabaseTest.java +++ b/liquibase-core/src/test/java/liquibase/database/core/UnsupportedDatabaseTest.java @@ -2,17 +2,21 @@ import junit.framework.TestCase; import liquibase.database.Database; +import liquibase.exception.DatabaseException; public class UnsupportedDatabaseTest extends TestCase { - public void testGetDefaultDriver() { - Database database = new UnsupportedDatabase(); - assertNull(database.getDefaultDriver("jdbc:oracle://localhost;databaseName=liquibase")); - assertNull(database.getDefaultDriver("jdbc:db2://localhost;databaseName=liquibase")); - assertNull(database.getDefaultDriver("jdbc:hsqldb://localhost;databaseName=liquibase")); - assertNull(database.getDefaultDriver("jdbc:derby://localhost;databaseName=liquibase")); - assertNull(database.getDefaultDriver("jdbc:sqlserver://localhost;databaseName=liquibase")); - assertNull(database.getDefaultDriver("jdbc:postgresql://localhost;databaseName=liquibase")); + public void testGetDefaultDriver() throws DatabaseException { + try (Database database = new UnsupportedDatabase()) { + assertNull(database.getDefaultDriver("jdbc:oracle://localhost;databaseName=liquibase")); + assertNull(database.getDefaultDriver("jdbc:db2://localhost;databaseName=liquibase")); + assertNull(database.getDefaultDriver("jdbc:hsqldb://localhost;databaseName=liquibase")); + assertNull(database.getDefaultDriver("jdbc:derby://localhost;databaseName=liquibase")); + assertNull(database.getDefaultDriver("jdbc:sqlserver://localhost;databaseName=liquibase")); + assertNull(database.getDefaultDriver("jdbc:postgresql://localhost;databaseName=liquibase")); + } catch (final DatabaseException e) { + throw e; + } } } diff --git a/liquibase-core/src/test/java/liquibase/executor/jvm/ExampleExecutor.java b/liquibase-core/src/test/java/liquibase/executor/jvm/ExampleExecutor.java index 05a7b882fa1..2ed86b39e23 100644 --- a/liquibase-core/src/test/java/liquibase/executor/jvm/ExampleExecutor.java +++ b/liquibase-core/src/test/java/liquibase/executor/jvm/ExampleExecutor.java @@ -1,8 +1,8 @@ /* * * This is an example of a custom Executor class. - * Specifying the change set attribute "runWith=" - * instructs Liquibase to execute the changes in the change set + * Specifying the changeset attribute "runWith=" + * instructs Liquibase to execute the changes in the changeset * with the Executor. * */ @@ -68,9 +68,9 @@ public int getPriority() { /** * - * Validate whether the change set can be executed by this Executor + * Validate whether the changeset can be executed by this Executor * - * @param changeSet The change set to validate + * @param changeSet The changeset to validate * @return boolean True if all changes can be executed by the custom Executor * False if any change cannot be executed * diff --git a/liquibase-core/src/test/java/liquibase/sqlgenerator/core/CreateTableGeneratorTest.java b/liquibase-core/src/test/java/liquibase/sqlgenerator/core/CreateTableGeneratorTest.java index 305c810ef76..639275c234c 100644 --- a/liquibase-core/src/test/java/liquibase/sqlgenerator/core/CreateTableGeneratorTest.java +++ b/liquibase-core/src/test/java/liquibase/sqlgenerator/core/CreateTableGeneratorTest.java @@ -540,7 +540,7 @@ public void testAutoIncrementStartWithH2Database() throws Exception { Sql[] generatedSql = this.generatorUnderTest.generateSql(statement, database, null); - assertEquals("CREATE TABLE SCHEMA_NAME.TABLE_NAME (COLUMN1_NAME BIGINT GENERATED BY DEFAULT AS IDENTITY (0))", generatedSql[0].toSql()); + assertEquals("CREATE TABLE SCHEMA_NAME.TABLE_NAME (COLUMN1_NAME BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 0))", generatedSql[0].toSql()); } } } @@ -558,7 +558,7 @@ public void testAutoIncrementStartWithIncrementByH2Database() throws Exception { Sql[] generatedSql = this.generatorUnderTest.generateSql(statement, database, null); - assertEquals("CREATE TABLE SCHEMA_NAME.TABLE_NAME (COLUMN1_NAME BIGINT GENERATED BY DEFAULT AS IDENTITY (0, 10))", generatedSql[0].toSql()); + assertEquals("CREATE TABLE SCHEMA_NAME.TABLE_NAME (COLUMN1_NAME BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 0 INCREMENT BY 10))", generatedSql[0].toSql()); } } } @@ -612,7 +612,7 @@ public void testAutoIncrementStartWithIncrementByHsqlDatabase() throws Exception Sql[] generatedSql = this.generatorUnderTest.generateSql(statement, database, null); - assertEquals("CREATE TABLE SCHEMA_NAME.TABLE_NAME (COLUMN1_NAME BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 10))", generatedSql[0].toSql()); + assertEquals("CREATE TABLE SCHEMA_NAME.TABLE_NAME (COLUMN1_NAME BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1 INCREMENT BY 10))", generatedSql[0].toSql()); } } } diff --git a/liquibase-core/src/test/java/liquibase/verify/saved_state/compareGeneratedSqlWithExpectedSqlForMinimalChangesets/addLookupTable/derby.sql b/liquibase-core/src/test/java/liquibase/verify/saved_state/compareGeneratedSqlWithExpectedSqlForMinimalChangesets/addLookupTable/derby.sql index 12b09b33a05..230fe3911d7 100644 --- a/liquibase-core/src/test/java/liquibase/verify/saved_state/compareGeneratedSqlWithExpectedSqlForMinimalChangesets/addLookupTable/derby.sql +++ b/liquibase-core/src/test/java/liquibase/verify/saved_state/compareGeneratedSqlWithExpectedSqlForMinimalChangesets/addLookupTable/derby.sql @@ -3,7 +3,7 @@ -- Change Parameter: existingTableName=address -- Change Parameter: newColumnName=abbreviation -- Change Parameter: newTableName=state -CREATE TABLE "state" AS SELECT DISTINCT "state" AS abbreviation FROM address WHERE "state" IS NOT NULL; -ALTER TABLE "state" ALTER COLUMN abbreviation NOT NULL; -ALTER TABLE "state" ADD PRIMARY KEY (abbreviation); -ALTER TABLE address ADD CONSTRAINT FK_ADDRESS_STATE FOREIGN KEY ("state") REFERENCES "state" (abbreviation); +CREATE TABLE state AS SELECT DISTINCT state AS abbreviation FROM address WHERE state IS NOT NULL; +ALTER TABLE state ALTER COLUMN abbreviation NOT NULL; +ALTER TABLE state ADD PRIMARY KEY (abbreviation); +ALTER TABLE address ADD CONSTRAINT FK_ADDRESS_STATE FOREIGN KEY (state) REFERENCES state (abbreviation); diff --git a/liquibase-core/src/test/java/liquibase/verify/saved_state/compareGeneratedSqlWithExpectedSqlForMinimalChangesets/renameColumn/mssql.sql b/liquibase-core/src/test/java/liquibase/verify/saved_state/compareGeneratedSqlWithExpectedSqlForMinimalChangesets/renameColumn/mssql.sql index 61ae5adcd6d..eabeb645430 100644 --- a/liquibase-core/src/test/java/liquibase/verify/saved_state/compareGeneratedSqlWithExpectedSqlForMinimalChangesets/renameColumn/mssql.sql +++ b/liquibase-core/src/test/java/liquibase/verify/saved_state/compareGeneratedSqlWithExpectedSqlForMinimalChangesets/renameColumn/mssql.sql @@ -2,4 +2,4 @@ -- Change Parameter: newColumnName=full_name -- Change Parameter: oldColumnName=name -- Change Parameter: tableName=person -exec sp_rename 'person.name', 'full_name'; +exec sp_rename 'person.name', 'full_name', 'COLUMN'; diff --git a/liquibase-core/src/test/resources/liquibase/registered-changelog.json b/liquibase-core/src/test/resources/liquibase/registered-changelog.json index ed23e7f31be..ee5c8244d15 100644 --- a/liquibase-core/src/test/resources/liquibase/registered-changelog.json +++ b/liquibase-core/src/test/resources/liquibase/registered-changelog.json @@ -46,24 +46,6 @@ } }, - { - "changeSet": { - "id": "1604958377003-3", - "author": "wesley (generated)", - "changes": [ - { - "createTrigger": { - "disabled": false, - "path": "objects/trigger/TRIGGER1.sql", - "relativeToChangelogFile": true, - "tableName": "ACCOUNT", - "triggerName": "TRIGGER1" - } - }] - - } - }, - { "changeSet": { "id": "1604958377003-4", @@ -413,40 +395,6 @@ } }] - } - }, - - { - "changeSet": { - "id": "1604958377003-14", - "author": "wesley (generated)", - "changes": [ - { - "addCheckConstraint": { - "constraintBody": "supplier_id BETWEEN 100 and 9999", - "constraintName": "CHECK_SUPPLIER_ID", - "disabled": false, - "tableName": "SUPPLIERS" - } - }] - - } - }, - - { - "changeSet": { - "id": "1604958377003-15", - "author": "wesley (generated)", - "changes": [ - { - "createFunction": { - "functionName": "FUNC_COMPUTE_TAX", - "path": "objects/function/FUNC_COMPUTE_TAX.sql", - "relativeToChangelogFile": true - } - }] - } } - ]} diff --git a/liquibase-core/src/test/resources/liquibase/registered-changelog.yml b/liquibase-core/src/test/resources/liquibase/registered-changelog.yml index 52d2ad1da4b..85440377540 100644 --- a/liquibase-core/src/test/resources/liquibase/registered-changelog.yml +++ b/liquibase-core/src/test/resources/liquibase/registered-changelog.yml @@ -22,16 +22,6 @@ databaseChangeLog: path: objects/storedprocedure/PROC_HELLO_WORLD.sql procedureName: PROC_HELLO_WORLD relativeToChangelogFile: true -- changeSet: - id: 1604960286751-3 - author: wesley (generated) - changes: - - createTrigger: - disabled: false - path: objects/trigger/TRIGGER1.sql - relativeToChangelogFile: true - tableName: ACCOUNT - triggerName: TRIGGER1 - changeSet: id: 1604960286751-4 author: wesley (generated) @@ -208,21 +198,3 @@ databaseChangeLog: type: VARCHAR2(50 BYTE) tableName: SUPPLIERS1 tablespace: USERS -- changeSet: - id: 1604960286751-14 - author: wesley (generated) - changes: - - addCheckConstraint: - constraintBody: supplier_id BETWEEN 100 and 9999 - constraintName: CHECK_SUPPLIER_ID - disabled: false - tableName: SUPPLIERS -- changeSet: - id: 1604960286751-15 - author: wesley (generated) - changes: - - createFunction: - functionName: FUNC_COMPUTE_TAX - path: objects/function/FUNC_COMPUTE_TAX.sql - relativeToChangelogFile: true - diff --git a/liquibase-core/src/test/resources/liquibase/simple.json b/liquibase-core/src/test/resources/liquibase/simple.json index 10a53bf8788..49525411a22 100644 --- a/liquibase-core/src/test/resources/liquibase/simple.json +++ b/liquibase-core/src/test/resources/liquibase/simple.json @@ -44,24 +44,6 @@ } }, - { - "changeSet": { - "id": "1604958377003-3", - "author": "wesley (generated)", - "changes": [ - { - "createTrigger": { - "disabled": false, - "path": "objects/trigger/TRIGGER1.sql", - "relativeToChangelogFile": true, - "tableName": "ACCOUNT", - "triggerName": "TRIGGER1" - } - }] - - } - }, - { "changeSet": { "id": "1604958377003-4", @@ -411,40 +393,6 @@ } }] - } - }, - - { - "changeSet": { - "id": "1604958377003-14", - "author": "wesley (generated)", - "changes": [ - { - "addCheckConstraint": { - "constraintBody": "supplier_id BETWEEN 100 and 9999", - "constraintName": "CHECK_SUPPLIER_ID", - "disabled": false, - "tableName": "SUPPLIERS" - } - }] - - } - }, - - { - "changeSet": { - "id": "1604958377003-15", - "author": "wesley (generated)", - "changes": [ - { - "createFunction": { - "functionName": "FUNC_COMPUTE_TAX", - "path": "objects/function/FUNC_COMPUTE_TAX.sql", - "relativeToChangelogFile": true - } - }] - } } - ]} diff --git a/liquibase-core/src/test/resources/liquibase/test-changelog.json b/liquibase-core/src/test/resources/liquibase/test-changelog.json index 10a53bf8788..49525411a22 100644 --- a/liquibase-core/src/test/resources/liquibase/test-changelog.json +++ b/liquibase-core/src/test/resources/liquibase/test-changelog.json @@ -44,24 +44,6 @@ } }, - { - "changeSet": { - "id": "1604958377003-3", - "author": "wesley (generated)", - "changes": [ - { - "createTrigger": { - "disabled": false, - "path": "objects/trigger/TRIGGER1.sql", - "relativeToChangelogFile": true, - "tableName": "ACCOUNT", - "triggerName": "TRIGGER1" - } - }] - - } - }, - { "changeSet": { "id": "1604958377003-4", @@ -411,40 +393,6 @@ } }] - } - }, - - { - "changeSet": { - "id": "1604958377003-14", - "author": "wesley (generated)", - "changes": [ - { - "addCheckConstraint": { - "constraintBody": "supplier_id BETWEEN 100 and 9999", - "constraintName": "CHECK_SUPPLIER_ID", - "disabled": false, - "tableName": "SUPPLIERS" - } - }] - - } - }, - - { - "changeSet": { - "id": "1604958377003-15", - "author": "wesley (generated)", - "changes": [ - { - "createFunction": { - "functionName": "FUNC_COMPUTE_TAX", - "path": "objects/function/FUNC_COMPUTE_TAX.sql", - "relativeToChangelogFile": true - } - }] - } } - ]} diff --git a/liquibase-core/src/test/resources/liquibase/test-changelog.yml b/liquibase-core/src/test/resources/liquibase/test-changelog.yml index 81ccb6ed59f..1d78e5362e0 100644 --- a/liquibase-core/src/test/resources/liquibase/test-changelog.yml +++ b/liquibase-core/src/test/resources/liquibase/test-changelog.yml @@ -21,16 +21,6 @@ databaseChangeLog: path: objects/storedprocedure/PROC_HELLO_WORLD.sql procedureName: PROC_HELLO_WORLD relativeToChangelogFile: true -- changeSet: - id: 1604960286751-3 - author: wesley (generated) - changes: - - createTrigger: - disabled: false - path: objects/trigger/TRIGGER1.sql - relativeToChangelogFile: true - tableName: ACCOUNT - triggerName: TRIGGER1 - changeSet: id: 1604960286751-4 author: wesley (generated) @@ -207,21 +197,3 @@ databaseChangeLog: type: VARCHAR2(50 BYTE) tableName: SUPPLIERS1 tablespace: USERS -- changeSet: - id: 1604960286751-14 - author: wesley (generated) - changes: - - addCheckConstraint: - constraintBody: supplier_id BETWEEN 100 and 9999 - constraintName: CHECK_SUPPLIER_ID - disabled: false - tableName: SUPPLIERS -- changeSet: - id: 1604960286751-15 - author: wesley (generated) - changes: - - createFunction: - functionName: FUNC_COMPUTE_TAX - path: objects/function/FUNC_COMPUTE_TAX.sql - relativeToChangelogFile: true - diff --git a/liquibase-dist/pom.xml b/liquibase-dist/pom.xml index f4aa8257026..e49e58aef8c 100644 --- a/liquibase-dist/pom.xml +++ b/liquibase-dist/pom.xml @@ -1,80 +1,78 @@ - - 4.0.0 - - - org.liquibase - liquibase - 0-SNAPSHOT - - - liquibase-dist - jar + + 4.0.0 + + org.liquibase + liquibase + 0-SNAPSHOT + + liquibase-dist + jar Liquibase is a tool for managing and executing database changes. - - github - https://maven.pkg.github.com/liquibase + + github + https://maven.pkg.github.com/liquibase - 2.1.214 - 2.5.2 - 42.3.4 - 10.2.1.jre8 - 8.0.21 - 3.0.5 - 21.6.0.0.1 - 3.36.0.3 - 11.5.7.0 - 4.0.6.java8 - + 2.1.214 + 2.5.2 + 42.4.0 + 10.2.1.jre8 + 8.0.21 + 3.0.6 + 21.6.0.0.1 + 3.36.0.3 + 11.5.7.0 + 4.0.6.java8 - - - ${project.groupId} - liquibase-core - ${project.version} - - - ${project.groupId} - liquibase-cli - ${project.version} - + src/main/assembly/assembly-bin.xml + + + + + ${project.groupId} + liquibase-core + ${project.version} + + + ${project.groupId} + liquibase-cli + ${project.version} + ${project.groupId} liquibase-snowflake ${project.version} - - com.h2database - h2 - ${h2.version} + + com.h2database + h2 + ${h2.version} true - + - + org.hsqldb hsqldb ${hsqldb.version} true - + - + org.postgresql postgresql ${postgresql.version} true - + - + com.microsoft.sqlserver mssql-jdbc ${mssql.version} true - + net.snowflake @@ -89,180 +87,185 @@ - + org.mariadb.jdbc mariadb-java-client ${mariadb.version} true - + - + com.oracle.database.jdbc ojdbc8 ${oracle.version} true - + - + org.xerial sqlite-jdbc ${sqlite.version} true - + - + com.ibm.db2 jcc ${db2.version} true - + - + org.firebirdsql.jdbc jaybird ${firebird.version} true - + - - + + + + javax.xml.bind jaxb-api 2.3.1 - - + + org.glassfish.jaxb jaxb-core 4.0.0 true - - + + org.glassfish.jaxb jaxb-runtime - 2.3.6 + 4.0.0 true - + + - - - + liquibase-${project.version} - - + + ${project.basedir}/src/main/archive ${project.build.directory}/archive true - - + + - - + + + org.liquibase.ext + liquibase-sdk-maven-plugin + 0.9 + + + org.apache.maven.plugins maven-source-plugin 3.2.1 - - + + true - - + + - + org.apache.maven.plugins maven-shade-plugin 3.3.0 - - + + com.github.marcosemiao.maven.plugins.shade.resource maven-shade-merge-manifest-transformer 0.0.2 - - - - - + + + + + ${project.groupId}:liquibase-core ${project.groupId}:liquibase-cli ${project.groupId}:liquibase-snowflake - com.datical.lb:liquibase-pro - - - - + + + + *:* - + META-INF/maven/** - - - + + + false true false false - + - + META-INF/maven/org.liquibase/liquibase-core/pom.xml ${basedir}/src/main/maven/release.pom.xml - - + + liquibase.build.properties - - - - - + + + + + package - + shade - - - - + + +
    + - + maven-assembly-plugin - 3.3.0 - + 3.4.1 + liquibase-${project.version} false false - - src/main/assembly/assembly-bin.xml - - - - + + ${assemblyConfigFile} + + + + make-assembly package - + single - - - - - - - + + + + + + maven-install-plugin - + liquibase-core ${project.build.directory}/liquibase-${project.version}.jar ${project.build.directory}/liquibase-${project.version}-sources.jar ${project.build.directory}/flattened-pom/release.pom.xml - - - + + + custom-install install - + install-file - - - - + + + + @@ -283,8 +286,7 @@ - - + org.codehaus.mojo build-helper-maven-plugin 3.3.0 @@ -301,28 +303,30 @@ - - - + + - - - liquibase-pro + + + liquibase-commercial - - + + ../../liquibase-pro/pom.xml - - + + - - - com.datical.lb - liquibase-pro - ${project.version} - - - - + + src/main/assembly/assembly-bin-pro.xml + + + + org.liquibase + liquibase-commercial + ${project.version} + + + + diff --git a/liquibase-dist/src/main/archive/GETTING_STARTED.txt b/liquibase-dist/src/main/archive/GETTING_STARTED.txt index a109bc98d54..46976220aa0 100644 --- a/liquibase-dist/src/main/archive/GETTING_STARTED.txt +++ b/liquibase-dist/src/main/archive/GETTING_STARTED.txt @@ -65,7 +65,7 @@ the command line can also be specified in the properties file. If a parameter is specified in both the properties file and the command line, the command line value will override the value in the file. -Learn more: https://www.liquibase.org/documentation/config_properties.html +Learn more: https://docs.liquibase.com/concepts/connections/creating-config-properties.html Starting the Example H2 Database @@ -220,7 +220,7 @@ COMPANY and PERSON tables in your integration web console. Standard Development Workflow ----------------------------- For more information on the Standard Development Workflow you just completed, see: -https://www.liquibase.org/documentation/workflows/lb-developer-workflow.html +https://www.liquibase.org/get-started/developer-workflow Next Steps diff --git a/liquibase-dist/src/main/archive/README.txt b/liquibase-dist/src/main/archive/README.txt index cba0197cec1..415ce76d175 100644 --- a/liquibase-dist/src/main/archive/README.txt +++ b/liquibase-dist/src/main/archive/README.txt @@ -16,7 +16,7 @@ The default install location on Windows is "\Program Files\liquibase" The default install location on Mac is "/usr/local/opt/liquibase" The following software was installed: - * Liquibase ( http://liquibase.org ) + * Liquibase ( https://liquibase.com ) * H2 Database ( https://www.h2database.com ) * AdoptOpenJDK 13 ( https://adoptopenjdk.net ) @@ -34,7 +34,6 @@ Files are: * liquibase/LICENSE.txt * liquibase/liquibase.sh * liquibase/liquibase.bat - * liquibase/liquibase.jar * liquibase/README.txt * liquibase/GETTING_STARTED.txt * liquibase/examples/start-h2 @@ -42,11 +41,11 @@ Files are: H2 Database Program ---------------------------------------- -As Liquibase ships with an h2 database example, the h2 jdbc driver was placed into +As Liquibase ships with an h2 database example, the h2 jdbc driver was placed into your chosen installation directory. For information on using and configuring the h2 database see: -https://www.liquibase.org/documentation/tutorials/h2.html +https://docs.liquibase.com/install/tutorials/h2.html Open JDK diff --git a/liquibase-dist/src/main/archive/licenses/commercial/Liquibase Pro EULA Software License Subscription and Support Agreement.txt b/liquibase-dist/src/main/archive/licenses/commercial/Liquibase Pro EULA Software License Subscription and Support Agreement.txt index fd9564f02f1..10adb95aea8 100644 --- a/liquibase-dist/src/main/archive/licenses/commercial/Liquibase Pro EULA Software License Subscription and Support Agreement.txt +++ b/liquibase-dist/src/main/archive/licenses/commercial/Liquibase Pro EULA Software License Subscription and Support Agreement.txt @@ -24,7 +24,7 @@ Customer, under an order, a term based non-exclusive, non-transferable license up to the license capacity purchased to use the Software only in Customer’s internal business operations. Third party licenses delivered with the Software may be subject to additional license rights and restrictions a set forth at -https://download.liquibase.org/lbpro-third-party-licenses/. +https://www.liquibase.com/licenses/liquibase_pro_tpl.html. 2. RESTRICTIONS. Customer may not: a. Transfer, assign, sublicense, rent the Software, create derivative works of diff --git a/liquibase-dist/src/main/archive/liquibase b/liquibase-dist/src/main/archive/liquibase index b1e10e39021..65981cdf5e6 100644 --- a/liquibase-dist/src/main/archive/liquibase +++ b/liquibase-dist/src/main/archive/liquibase @@ -30,6 +30,11 @@ if [ -z "${JAVA_HOME}" ]; then elif [ -d "${LIQUIBASE_HOME}/.install4j/jre.bundle/Contents/Home" ]; then JAVA_HOME="${LIQUIBASE_HOME}/.install4j/jre.bundle/Contents/Home" fi +else + if [ ! -x "$JAVA_HOME" ] ; then + echo "ERROR: The JAVA_HOME environment variable is not defined correctly, so Liquibase cannot be started. JAVA_HOME is set to \"$JAVA_HOME\" and it does not exist." >&2 + exit 1 + fi fi if [ -z "${JAVA_HOME}" ]; then @@ -37,6 +42,7 @@ if [ -z "${JAVA_HOME}" ]; then if [ -z "${JAVA_PATH}" ]; then echo "Cannot find java in your path. Install java or use the JAVA_HOME environment variable" + exit 1 fi else #Use path in JAVA_HOME @@ -47,4 +53,4 @@ fi JAVA_OPTS="${JAVA_OPTS-}" export LIQUIBASE_HOME -"${JAVA_PATH}" $JAVA_OPTS -jar "$LIQUIBASE_HOME/liquibase.jar" ${1+"$@"} +"${JAVA_PATH}" $JAVA_OPTS -jar "$LIQUIBASE_HOME/internal/lib/liquibase-core.jar" ${1+"$@"} diff --git a/liquibase-dist/src/main/archive/liquibase.bat b/liquibase-dist/src/main/archive/liquibase.bat index 4ad3e373c64..56f384922e0 100644 --- a/liquibase-dist/src/main/archive/liquibase.bat +++ b/liquibase-dist/src/main/archive/liquibase.bat @@ -17,6 +17,11 @@ if exist "%LIQUIBASE_HOME%\jre" if "%JAVA_HOME%"=="" ( set JAVA_HOME=%LIQUIBASE_HOME%\jre ) +if NOT "%JAVA_HOME%" == "" if not exist "%JAVA_HOME%" ( + echo ERROR: The JAVA_HOME environment variable is not defined correctly, so Liquibase cannot be started. JAVA_HOME is set to "%JAVA_HOME%" and it does not exist. >&2 + exit /B 1 +) + rem special characters may be lost setlocal DISABLEDELAYEDEXPANSION @@ -25,4 +30,4 @@ IF NOT DEFINED JAVA_OPTS set JAVA_OPTS= set JAVA_PATH=java if NOT "%JAVA_HOME%" == "" set JAVA_PATH=%JAVA_HOME%\bin\java -"%JAVA_PATH%" %JAVA_OPTS% -jar "%LIQUIBASE_HOME%\liquibase.jar" %* +"%JAVA_PATH%" %JAVA_OPTS% -jar "%LIQUIBASE_HOME%\internal\lib\liquibase-core.jar" %* diff --git a/liquibase-dist/src/main/assembly/assembly-bin-common.xml b/liquibase-dist/src/main/assembly/assembly-bin-common.xml new file mode 100644 index 00000000000..482d0a401e2 --- /dev/null +++ b/liquibase-dist/src/main/assembly/assembly-bin-common.xml @@ -0,0 +1,141 @@ + + + + ${project.build.directory}/archive + ${file.separator} + unix + + liquibase + + 0755 + + + ${project.build.directory}/archive + + ${file.separator} + dos + + *.bat + + + + ${project.build.directory}/archive + ${file.separator} + unix + + liquibase + *.bat + + + + ${project.build.directory}/site/apidocs + javadoc + + **/* + + + + ${project.basedir}/../liquibase-core/target/classes/liquibase/examples + examples + + **/* + + + **/start-h2* + + + + ${project.basedir}/../liquibase-core/target/classes/liquibase/examples + examples + + **/start-h2 + + unix + 0755 + + + ${project.basedir}/../liquibase-core/target/classes/liquibase/examples + examples + + **/start-h2.bat + + dos + + + + + ${project.build.directory}/liquibase-0-SNAPSHOT.jar + internal/lib/liquibase-core.jar + 0644 + + + + ../LICENSE.txt + ${file.separator} + + + ../ABOUT.txt + ${file.separator} + + + ../changelog.txt + ${file.separator} + + + + + ${artifact.artifactId}${dashClassifier?}.${artifact.extension} + internal/lib + true + runtime + + org.liquibase:liquibase-commercial: + com.opencsv:opencsv: + org.yaml:snakeyaml:jar: + javax.xml.bind:jaxb-api:jar: + org.glassfish.jaxb:jaxb-runtime:jar: + org.glassfish.jaxb:jaxb-core:jar: + info.picocli:picocli:jar: + com.h2database:h2:jar: + org.hsqldb:hsqldb:jar: + org.postgresql:postgresql:jar + org.mariadb.jdbc:mariadb-java-client:jar + com.oracle.database.jdbc:ojdbc8:jar + com.microsoft.sqlserver:mssql-jdbc:jar + org.xerial:sqlite-jdbc:jar: + com.ibm.db2:jcc:jar: + org.firebirdsql.jdbc:jaybird: + net.snowflake:snowflake-jdbc: + + javax.resource:connector-api: + + + + + + + + org.antlr:antlr4-runtime:jar: + org.checkerframework:checker-qual:jar: + commons-beanutils:commons-beanutils:jar: + org.glassfish.jaxb:txw2:jar: + org.eclipse.angus:angus-activation:jar: + com.sun.istack:istack-commons-runtime:jar: + jakarta.activation:jakarta.activation-api:jar: + jakarta.xml.bind:jakarta.xml.bind-api:jar: + com.sun.activation:jakarta.activation:jar: + javax.activation:javax.activation-api:jar: + org.liquibase:liquibase-snowflake:jar: + net.java.truelicense:*:jar: + com.github.jsqlparser:jsqlparser:jar: + commons-codec:commons-codec:jar: + com.fasterxml.jackson.core:*:jar: + com.fasterxml.jackson.module:*:jar: + + + + diff --git a/liquibase-dist/src/main/assembly/assembly-bin-pro.xml b/liquibase-dist/src/main/assembly/assembly-bin-pro.xml new file mode 100644 index 00000000000..e874aecc004 --- /dev/null +++ b/liquibase-dist/src/main/assembly/assembly-bin-pro.xml @@ -0,0 +1,21 @@ + + liquibase-bin + + tar.gz + + false + + src/main/assembly/assembly-bin-common.xml + + + + ${artifact.artifactId}${dashClassifier?}.${artifact.extension} + internal/lib + + + org.liquibase:liquibase-commercial:jar: + + + + + diff --git a/liquibase-dist/src/main/assembly/assembly-bin.xml b/liquibase-dist/src/main/assembly/assembly-bin.xml index 357dfa3fe83..4bb56ee28b1 100644 --- a/liquibase-dist/src/main/assembly/assembly-bin.xml +++ b/liquibase-dist/src/main/assembly/assembly-bin.xml @@ -1,142 +1,11 @@ - liquibase-bin tar.gz false - - - ${project.build.directory}/archive - ${file.separator} - unix - - liquibase - - 0755 - - - ${project.build.directory}/archive - - ${file.separator} - dos - - *.bat - - - - ${project.build.directory}/archive - ${file.separator} - unix - - liquibase - *.bat - - - - ${project.build.directory}/site/apidocs - javadoc - - **/* - - - - ${project.basedir}/../liquibase-core/target/classes/liquibase/examples - examples - - **/* - - - **/start-h2* - - - - ${project.basedir}/../liquibase-core/target/classes/liquibase/examples - examples - - **/start-h2 - - unix - 0755 - - - ${project.basedir}/../liquibase-core/target/classes/liquibase/examples - examples - - **/start-h2.bat - - dos - - - - - ${project.build.directory}/liquibase-0-SNAPSHOT.jar - liquibase.jar - 0644 - - - - ../LICENSE.txt - ${file.separator} - - - ../ABOUT.txt - ${file.separator} - - - ../changelog.txt - ${file.separator} - - - - - ${artifact.artifactId}${dashClassifier?}.${artifact.extension} - internal/lib - true - runtime - - com.opencsv:opencsv: - org.yaml:snakeyaml:jar: - javax.xml.bind:jaxb-api:jar: - org.glassfish.jaxb:jaxb-runtime:jar: - org.glassfish.jaxb:jaxb-core:jar: - info.picocli:picocli:jar: - - com.h2database:h2:jar: - org.hsqldb:hsqldb:jar: - org.postgresql:postgresql:jar - org.mariadb.jdbc:mariadb-java-client:jar - com.oracle.database.jdbc:ojdbc8:jar - com.microsoft.sqlserver:mssql-jdbc:jar - org.xerial:sqlite-jdbc:jar: - com.ibm.db2:jcc:jar: - org.firebirdsql.jdbc:jaybird: - net.snowflake:snowflake-jdbc: - - javax.resource:connector-api: - - - - - - - - org.antlr:antlr4-runtime:jar: - org.checkerframework:checker-qual:jar: - commons-beanutils:commons-beanutils:jar: - org.glassfish.jaxb:txw2:jar: - org.eclipse.angus:angus-activation:jar: - com.sun.istack:istack-commons-runtime:jar: - jakarta.activation:jakarta.activation-api:jar: - jakarta.xml.bind:jakarta.xml.bind-api:jar: - com.sun.activation:jakarta.activation:jar: - javax.activation:javax.activation-api:jar: - - - - - + + src/main/assembly/assembly-bin-common.xml + + \ No newline at end of file diff --git a/liquibase-extension-examples/src/main/java/liquibase/executor/jvm/ExampleExecutor.java b/liquibase-extension-examples/src/main/java/liquibase/executor/jvm/ExampleExecutor.java index 96587c26e9c..cd73e2e0dc4 100644 --- a/liquibase-extension-examples/src/main/java/liquibase/executor/jvm/ExampleExecutor.java +++ b/liquibase-extension-examples/src/main/java/liquibase/executor/jvm/ExampleExecutor.java @@ -1,8 +1,8 @@ /** * * This is an example of a custom Executor class. - * Specifying the change set attribute "runWith=" - * instructs Liquibase to execute the changes in the change set + * Specifying the changeset attribute "runWith=" + * instructs Liquibase to execute the changes in the changeset * with the Executor. * */ @@ -68,9 +68,9 @@ public int getPriority() { /** * - * Validate whether the change set can be executed by this Executor + * Validate whether the changeset can be executed by this Executor * - * @param changeSet The change set to validate + * @param changeSet The changeset to validate * @return boolean True if all changes can be executed by the custom Executor * False if any change cannot be executed * diff --git a/liquibase-extension-testing/pom.xml b/liquibase-extension-testing/pom.xml index e3ce4567ec1..3140020591e 100644 --- a/liquibase-extension-testing/pom.xml +++ b/liquibase-extension-testing/pom.xml @@ -15,7 +15,7 @@ org.testcontainers testcontainers-bom - 1.17.2 + 1.17.3 pom import diff --git a/liquibase-integration-tests/setup/build.xml b/liquibase-integration-tests/setup/build.xml index c0d9af7373d..a4771f93dba 100644 --- a/liquibase-integration-tests/setup/build.xml +++ b/liquibase-integration-tests/setup/build.xml @@ -7,9 +7,9 @@ - - - + + + diff --git a/liquibase-integration-tests/setup/oracle/build.xml b/liquibase-integration-tests/setup/oracle/build.xml index aea82c91357..3c93a02e998 100644 --- a/liquibase-integration-tests/setup/oracle/build.xml +++ b/liquibase-integration-tests/setup/oracle/build.xml @@ -20,9 +20,9 @@ - - - + + + diff --git a/liquibase-integration-tests/src/test/groovy/liquibase/command/core/ListLocksTest.groovy b/liquibase-integration-tests/src/test/groovy/liquibase/command/core/ListLocksTest.groovy new file mode 100644 index 00000000000..cc3310e9c3f --- /dev/null +++ b/liquibase-integration-tests/src/test/groovy/liquibase/command/core/ListLocksTest.groovy @@ -0,0 +1,33 @@ +package liquibase.command.core + +import liquibase.Scope +import liquibase.command.CommandResultsBuilder +import liquibase.command.CommandScope +import liquibase.extension.testing.testsystem.DatabaseTestSystem +import liquibase.extension.testing.testsystem.TestSystemFactory +import liquibase.extension.testing.testsystem.spock.LiquibaseIntegrationTest +import spock.lang.Shared +import spock.lang.Specification + +@LiquibaseIntegrationTest +class ListLocksTest extends Specification { + + @Shared + private DatabaseTestSystem mariadb = + (DatabaseTestSystem) Scope.getCurrentScope().getSingleton(TestSystemFactory.class).getTestSystem("mariadb") + + + def "Can list locks on mariadb"() { + when: + CommandScope commandScope = new CommandScope(ListLocksCommandStep.COMMAND_NAME) + commandScope.addArgumentValue(ListLocksCommandStep.URL_ARG, mariadb.getConnectionUrl()) + commandScope.addArgumentValue(ListLocksCommandStep.USERNAME_ARG, mariadb.getUsername()) + commandScope.addArgumentValue(ListLocksCommandStep.PASSWORD_ARG, mariadb.getPassword()) + OutputStream outputStream = new ByteArrayOutputStream() + CommandResultsBuilder commandResultsBuilder = new CommandResultsBuilder(commandScope, outputStream) + + then: + ListLocksCommandStep diffChangelogCommandStep = new ListLocksCommandStep() + diffChangelogCommandStep.run(commandResultsBuilder) + } +} diff --git a/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java b/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java index 6560145c8c9..1ef790e39e9 100644 --- a/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java +++ b/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java @@ -836,7 +836,7 @@ public void testUnrunChangeSetsEmptyDatabase() throws Exception { liquibase.setChangeLogParameter( "loginuser", testSystem.getUsername()); List list = liquibase.listUnrunChangeSets(new Contexts(this.contexts), new LabelExpression()); - assertTrue("querying the changelog table on an empty target should return at least 1 un-run change set", !list.isEmpty()); + assertTrue("querying the changelog table on an empty target should return at least 1 un-run changeset", !list.isEmpty()); } @@ -918,7 +918,7 @@ public void testDbDoc() throws Exception { } /** - * Create an SQL script from a change set which inserts data from CSV files. The first CSV file is encoded in + * Create an SQL script from a changeset which inserts data from CSV files. The first CSV file is encoded in * UTF-8, the second is encoded in Latin-1. The test is successful if the CSV data is converted into correct * INSERT INTO statements in the final generated SQL file. * @throws Exception @@ -1039,7 +1039,7 @@ public void testGenerateChangeLogWithNoChanges() throws Exception { DiffToChangeLog changeLogWriter = new DiffToChangeLog(diffResult, new DiffOutputControl(false, false, false, null)); List changeSets = changeLogWriter.generateChangeSets(); assertEquals("generating two change logs without any changes in between should result in an empty generated " + - "differential change set.", 0, changeSets.size()); + "differential changeset.", 0, changeSets.size()); } @Test diff --git a/liquibase-integration-tests/src/test/java/liquibase/statementexecute/RenameColumnExecuteTest.java b/liquibase-integration-tests/src/test/java/liquibase/statementexecute/RenameColumnExecuteTest.java index 115de3401f8..aebc561f43c 100644 --- a/liquibase-integration-tests/src/test/java/liquibase/statementexecute/RenameColumnExecuteTest.java +++ b/liquibase-integration-tests/src/test/java/liquibase/statementexecute/RenameColumnExecuteTest.java @@ -50,7 +50,7 @@ public void noSchema() throws Exception { assertCorrect("alter table table_name alter column column_name rename to new_name", H2Database.class, HsqlDatabase.class); assertCorrect("alter table table_name alter column column_name to new_name", FirebirdDatabase.class); assertCorrect("alter table table_name change column_name new_name int", MySQLDatabase.class, MariaDBDatabase.class); - assertCorrect("exec sp_rename '[table_name].[column_name]', 'new_name'", MSSQLDatabase.class); + assertCorrect("exec sp_rename '[table_name].[column_name]', 'new_name', 'COLUMN'", MSSQLDatabase.class); assertCorrect("exec sp_rename 'table_name.column_name', 'new_name'", SybaseDatabase.class); assertCorrect("alter table [table_name] rename column_name to new_name",SybaseASADatabase.class); assertCorrectOnRest("alter table [table_name] rename column [column_name] to [new_name]"); diff --git a/liquibase-integration-tests/src/test/resources/changelogs/h2/complete/root.changelog.xml b/liquibase-integration-tests/src/test/resources/changelogs/h2/complete/root.changelog.xml index 430affa1da2..b28e93010de 100644 --- a/liquibase-integration-tests/src/test/resources/changelogs/h2/complete/root.changelog.xml +++ b/liquibase-integration-tests/src/test/resources/changelogs/h2/complete/root.changelog.xml @@ -3,7 +3,7 @@ + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd"> diff --git a/liquibase-integration-tests/src/test/resources/changelogs/hsqldb/complete/root.changelog.xml b/liquibase-integration-tests/src/test/resources/changelogs/hsqldb/complete/root.changelog.xml index d8b8f1d161b..32757f230f1 100644 --- a/liquibase-integration-tests/src/test/resources/changelogs/hsqldb/complete/root.changelog.xml +++ b/liquibase-integration-tests/src/test/resources/changelogs/hsqldb/complete/root.changelog.xml @@ -3,7 +3,7 @@ + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd"> diff --git a/liquibase-integration-tests/src/test/resources/changelogs/mysql/complete/root.changelog.xml b/liquibase-integration-tests/src/test/resources/changelogs/mysql/complete/root.changelog.xml index 1888c6a717a..fac000d24fe 100644 --- a/liquibase-integration-tests/src/test/resources/changelogs/mysql/complete/root.changelog.xml +++ b/liquibase-integration-tests/src/test/resources/changelogs/mysql/complete/root.changelog.xml @@ -3,7 +3,7 @@ + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd"> select 1 diff --git a/liquibase-integration-tests/src/test/resources/changelogs/pgsql/complete/root.changelog.xml b/liquibase-integration-tests/src/test/resources/changelogs/pgsql/complete/root.changelog.xml index b52fcff6674..0d5ec43c064 100644 --- a/liquibase-integration-tests/src/test/resources/changelogs/pgsql/complete/root.changelog.xml +++ b/liquibase-integration-tests/src/test/resources/changelogs/pgsql/complete/root.changelog.xml @@ -370,7 +370,7 @@ - org.codehaus.mojo - xml-maven-plugin - 1.0.2 - - - transform-deploy-pom - process-resources - - transform - - - - - true - - - ${project.build.directory}/flattened-pom - release.pom.xml - ${project.build.directory} - ${project.basedir}/src/main/maven/liquibase-deployment-pom.xslt - - - - - - - maven-install-plugin + org.apache.maven.plugins + maven-shade-plugin + 3.3.0 - ${project.artifactId} - ${project.build.directory}/${project.artifactId}-${project.version}.jar - ${project.build.directory}/${project.artifactId}-${project.version}-sources.jar - ${project.build.directory}/${project.artifactId}-${project.version}-javadoc.jar - ${project.build.directory}/release.pom.xml + + + ${project.groupId}:liquibase-maven-plugin + + + + + *:* + + META-INF/maven/**/pom.xml + + + + false + false + false + false + + + + META-INF/maven/org.liquibase/liquibase-maven-plugin/pom.xml + ${basedir}/src/main/maven/release.pom.xml + + - custom-install - install + package - install-file + shade @@ -143,6 +136,42 @@ + + + liquibase-commercial + + + + ../../liquibase-pro/pom.xml + + + + + + + maven-install-plugin + + liquibase-maven-plugin + ${project.build.directory}/liquibase-maven-plugin-${project.version}.jar + ${project.build.directory}/liquibase-maven-plugin-${project.version}-sources.jar + ${basedir}/src/main/maven/release.pom.xml + + + + custom-install + install + + install-file + + + + + + + + + + diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseMojo.java index 9f4b89ed873..472cd704ff3 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseMojo.java @@ -361,6 +361,222 @@ public abstract class AbstractLiquibaseMojo extends AbstractMojo { @PropertyElement private String liquibaseLicenseKey; + /** + * Specifies your psql path. + * + * @parameter property="liquibase.psql.path" + */ + @PropertyElement + protected String psqlPath; + + /** + * Specifies whether to keep generated psql files. + * + * @parameter property="liquibase.psql.keep.temp" + */ + @PropertyElement + protected Boolean psqlKeepTemp; + + /** + * Specifies the name of generated psql files. + * + * @parameter property="liquibase.psql.keep.temp.name" + */ + @PropertyElement + protected String psqlKeepTempName; + + /** + * Specifies where to keep generated psql files. + * + * @parameter property="liquibase.psql.keep.temp.path" + */ + @PropertyElement + protected String psqlKeepTempPath; + + /** + * Specifies additional psql args. + * + * @parameter property="liquibase.psql.args" + */ + @PropertyElement + protected String psqlArgs; + + /** + * Specifies psql executor name. + * + * @parameter property="liquibase.psql.executor" + */ + @PropertyElement + protected String psqlExecutorName; + + /** + * Specifies psql timeout. + * + * @parameter property="liquibase.psql.timeout" + */ + @PropertyElement + protected Integer psqlTimeout; + + /** + * Specifies where to output psql logs. + * + * @parameter property="liquibase.psql.logFile" + */ + @PropertyElement + protected String psqlLogFile; + + /** + * Specifies your sqlplus path. + * + * @parameter property="liquibase.sqlplus.path" + */ + @PropertyElement + protected String sqlPlusPath; + + /** + * Specifies whether to keep generated sqlplus files. + * + * @parameter property="liquibase.sqlplus.keep.temp" + */ + @PropertyElement + protected Boolean sqlPlusKeepTemp; + + /** + * Specifies the name of generated sqlplus files. + * + * @parameter property="liquibase.sqlplus.keep.temp.name" + */ + @PropertyElement + protected String sqlPlusKeepTempName; + + /** + * Specifies where to keep generated sqlplus files. + * + * @parameter property="liquibase.sqlplus.keep.temp.path" + */ + @PropertyElement + protected String sqlPlusKeepTempPath; + + /** + * Specifies whether to overwrite generated sqlplus files. + * + * @parameter property="liquibase.sqlplus.keep.temp.overwrite" + */ + @PropertyElement + protected Boolean sqlPlusKeepTempOverwrite; + + /** + * Specifies additional sqlplus args. + * + * @parameter property="liquibase.sqlplus.args" + */ + @PropertyElement + protected String sqlPlusArgs; + + /** + * Specifies sqlPlus executor name. + * + * @parameter property="liquibase.sqlplus.executor" + */ + @PropertyElement + protected String sqlPlusExecutorName; + + /** + * Specifies sqlplus timeout. + * + * @parameter property="liquibase.sqlplus.timeout" + */ + @PropertyElement + protected Integer sqlPlusTimeout; + + /** + * Specifies where to output sqlplus logs. + * + * @parameter property="liquibase.sqlplus.logFile" + */ + @PropertyElement + protected String sqlPlusLogFile; + + /** + * Specifies your sqlcmd path. + * + * @parameter property="liquibase.sqlcmd.path" + */ + @PropertyElement + protected String sqlcmdPath; + + /** + * Specifies whether to keep generated sqlcmd files. + * + * @parameter property="liquibase.sqlcmd.keep.temp" + */ + @PropertyElement + protected Boolean sqlcmdKeepTemp; + + /** + * Specifies the name of generated sqlcmd files. + * + * @parameter property="liquibase.sqlcmd.keep.temp.name" + */ + @PropertyElement + protected String sqlcmdKeepTempName; + + /** + * Specifies where to keep generated sqlcmd files. + * + * @parameter property="liquibase.sqlcmd.keep.temp.path" + */ + @PropertyElement + protected String sqlcmdKeepTempPath; + + /** + * Specifies whether to overwrite generated sqlcmd files. + * + * @parameter property="liquibase.sqlcmd.keep.temp.overwrite" + */ + @PropertyElement + protected Boolean sqlcmdKeepTempOverwrite; + + /** + * Specifies additional sqlcmd args. + * + * @parameter property="liquibase.sqlcmd.args" + */ + @PropertyElement + protected String sqlcmdArgs; + + /** + * Specifies sqlcmd executor name. + * + * @parameter property="liquibase.sqlcmd.executor" + */ + @PropertyElement + protected String sqlcmdExecutorName; + + /** + * Specifies sqlcmd timeout. + * + * @parameter property="liquibase.sqlcmd.timeout" + */ + @PropertyElement + protected Integer sqlcmdTimeout; + + /** + * Specifies where to output sqlcmd logs. + * + * @parameter property="liquibase.sqlcmd.logFile" + */ + @PropertyElement + protected String sqlcmdLogFile; + + /** + * Specifies sqlcmd catalog name. + * + * @parameter property="liquibase.sqlcmd.catalogName" + */ + @PropertyElement + protected String sqlcmdCatalogName; + protected String commandName; /** @@ -458,6 +674,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { scopeValues.put("liquibase.licenseKey", getLicenseKey()); String key = GlobalConfiguration.PRESERVE_SCHEMA_CASE.getKey(); scopeValues.put(key, preserveSchemaCase); + scopeValues.putAll(getNativeExecutorProperties()); Scope.child(scopeValues, () -> { configureFieldsAndValues(); @@ -882,4 +1099,36 @@ private void processSystemProperties() { } } + private Map getNativeExecutorProperties() { + Map nativeProperties = new HashMap<>(); + // Don't add properties to the map if the value is null + nativeProperties.computeIfAbsent("liquibase.psql.path", val -> psqlPath); + nativeProperties.computeIfAbsent("liquibase.psql.keep.temp", val -> psqlKeepTemp); + nativeProperties.computeIfAbsent("liquibase.psql.keep.temp.name", val -> psqlKeepTempName); + nativeProperties.computeIfAbsent("liquibase.psql.keep.temp.path", val -> psqlKeepTempPath); + nativeProperties.computeIfAbsent("liquibase.psql.args", val -> psqlArgs); + nativeProperties.computeIfAbsent("liquibase.psql.executor", val -> psqlExecutorName); + nativeProperties.computeIfAbsent("liquibase.psql.timeout", val -> psqlTimeout); + nativeProperties.computeIfAbsent("liquibase.psql.logFile", val -> psqlLogFile); + nativeProperties.computeIfAbsent("liquibase.sqlplus.path", val -> sqlPlusPath); + nativeProperties.computeIfAbsent("liquibase.sqlplus.keep.temp", val -> sqlPlusKeepTemp); + nativeProperties.computeIfAbsent("liquibase.sqlplus.keep.temp.name", val -> sqlPlusKeepTempName); + nativeProperties.computeIfAbsent("liquibase.sqlplus.keep.temp.path", val -> sqlPlusKeepTempPath); + nativeProperties.computeIfAbsent("liquibase.sqlplus.keep.temp.overwrite", val -> sqlPlusKeepTempOverwrite); + nativeProperties.computeIfAbsent("liquibase.sqlplus.args", val -> sqlPlusArgs); + nativeProperties.computeIfAbsent("liquibase.sqlplus.executor", val -> sqlPlusExecutorName); + nativeProperties.computeIfAbsent("liquibase.sqlplus.timeout", val -> sqlPlusTimeout); + nativeProperties.computeIfAbsent("liquibase.sqlplus.logFile", val -> sqlPlusLogFile); + nativeProperties.computeIfAbsent("liquibase.sqlcmd.path", val -> sqlcmdPath); + nativeProperties.computeIfAbsent("liquibase.sqlcmd.keep.temp", val -> sqlcmdKeepTemp); + nativeProperties.computeIfAbsent("liquibase.sqlcmd.keep.temp.name", val -> sqlcmdKeepTempName); + nativeProperties.computeIfAbsent("liquibase.sqlcmd.keep.temp.path", val -> sqlcmdKeepTempPath); + nativeProperties.computeIfAbsent("liquibase.sqlcmd.keep.temp.overwrite", val -> sqlcmdKeepTempOverwrite); + nativeProperties.computeIfAbsent("liquibase.sqlcmd.args", val -> sqlcmdArgs); + nativeProperties.computeIfAbsent("liquibase.sqlcmd.executor", val -> sqlcmdExecutorName); + nativeProperties.computeIfAbsent("liquibase.sqlcmd.timeout", val -> sqlcmdTimeout); + nativeProperties.computeIfAbsent("liquibase.sqlcmd.logFile", val -> sqlcmdLogFile); + nativeProperties.computeIfAbsent("liquibase.sqlcmd.catalogName", val -> sqlcmdCatalogName); + return nativeProperties; + } } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDatabaseDiff.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDatabaseDiff.java index 65293294912..d1db9a5e600 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDatabaseDiff.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDatabaseDiff.java @@ -231,61 +231,62 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseExcepti Database db = liquibase.getDatabase(); - Database referenceDatabase = CommandLineUtils.createDatabaseObject(resourceAccessor, referenceUrl, referenceUsername, referencePassword, referenceDriver, referenceDefaultCatalogName, referenceDefaultSchemaName, outputDefaultCatalog, outputDefaultSchema, null, null, propertyProviderClass, null, null, databaseChangeLogTableName, databaseChangeLogLockTableName); + try (Database referenceDatabase = CommandLineUtils.createDatabaseObject(resourceAccessor, referenceUrl, referenceUsername, referencePassword, referenceDriver, referenceDefaultCatalogName, referenceDefaultSchemaName, outputDefaultCatalog, outputDefaultSchema, null, null, propertyProviderClass, null, null, databaseChangeLogTableName, databaseChangeLogLockTableName)) { - getLog().info("Performing Diff on database " + db.toString()); - if ((diffExcludeObjects != null) && (diffIncludeObjects != null)) { - throw new UnexpectedLiquibaseException("Cannot specify both excludeObjects and includeObjects"); - } - ObjectChangeFilter objectChangeFilter = null; - if (diffExcludeObjects != null) { - objectChangeFilter = new StandardObjectChangeFilter(StandardObjectChangeFilter.FilterType.EXCLUDE, diffExcludeObjects); - } - if (diffIncludeObjects != null) { - objectChangeFilter = new StandardObjectChangeFilter(StandardObjectChangeFilter.FilterType.INCLUDE, diffIncludeObjects); - } - - CompareControl.SchemaComparison[] schemaComparisons = createSchemaComparisons(db); - if (diffChangeLogFile != null) { - try { - DiffOutputControl diffOutputControl = new DiffOutputControl(diffIncludeCatalog, diffIncludeSchema, diffIncludeTablespace, null).addIncludedSchema(new CatalogAndSchema(referenceDefaultCatalogName, referenceDefaultSchemaName)); - diffOutputControl.setObjectChangeFilter(objectChangeFilter); - CommandLineUtils.doDiffToChangeLog(diffChangeLogFile, referenceDatabase, db, diffOutputControl, - objectChangeFilter, StringUtil.trimToNull(diffTypes), schemaComparisons); - if (new File(diffChangeLogFile).exists()) { - getLog().info("Differences written to Change Log File, " + diffChangeLogFile); - } - } catch (IOException | ParserConfigurationException e) { - throw new LiquibaseException(e); + getLog().info("Performing Diff on database " + db.toString()); + if ((diffExcludeObjects != null) && (diffIncludeObjects != null)) { + throw new UnexpectedLiquibaseException("Cannot specify both excludeObjects and includeObjects"); + } + ObjectChangeFilter objectChangeFilter = null; + if (diffExcludeObjects != null) { + objectChangeFilter = new StandardObjectChangeFilter(StandardObjectChangeFilter.FilterType.EXCLUDE, diffExcludeObjects); + } + if (diffIncludeObjects != null) { + objectChangeFilter = new StandardObjectChangeFilter(StandardObjectChangeFilter.FilterType.INCLUDE, diffIncludeObjects); } - } else { - PrintStream printStream = createPrintStream(); - if (isFormattedDiff()) { - CommandScope liquibaseCommand = new CommandScope("internalDiff"); - CommandScope diffCommand = - CommandLineUtils.createDiffCommand(referenceDatabase, db, StringUtil.trimToNull(diffTypes), - schemaComparisons, objectChangeFilter, printStream); - CompareControl compareControl = new CompareControl(schemaComparisons, diffTypes); - liquibaseCommand.addArgumentValue("format", format); - liquibaseCommand.addArgumentValue("diffCommand", diffCommand); - liquibaseCommand.addArgumentValue("targetDatabase", db); - liquibaseCommand.addArgumentValue("referenceDatabase", referenceDatabase); - liquibaseCommand.addArgumentValue("compareControl", compareControl); - liquibaseCommand.addArgumentValue("objectChangeFilter", objectChangeFilter); - if (StringUtil.isEmpty(diffTypes)) { - liquibaseCommand.addArgumentValue("snapshotTypes", new Class[0]); - } else { - liquibaseCommand.addArgumentValue("snapshotTypes", diffTypes); + CompareControl.SchemaComparison[] schemaComparisons = createSchemaComparisons(db); + if (diffChangeLogFile != null) { + try { + DiffOutputControl diffOutputControl = new DiffOutputControl(diffIncludeCatalog, diffIncludeSchema, diffIncludeTablespace, null).addIncludedSchema(new CatalogAndSchema(referenceDefaultCatalogName, referenceDefaultSchemaName)); + diffOutputControl.setObjectChangeFilter(objectChangeFilter); + CommandLineUtils.doDiffToChangeLog(diffChangeLogFile, referenceDatabase, db, diffOutputControl, + objectChangeFilter, StringUtil.trimToNull(diffTypes), schemaComparisons); + if (new File(diffChangeLogFile).exists()) { + getLog().info("Differences written to Change Log File, " + diffChangeLogFile); + } + } catch (IOException | ParserConfigurationException e) { + throw new LiquibaseException(e); } + } else { + PrintStream printStream = createPrintStream(); + if (isFormattedDiff()) { + CommandScope liquibaseCommand = new CommandScope("internalDiff"); + CommandScope diffCommand = + CommandLineUtils.createDiffCommand(referenceDatabase, db, StringUtil.trimToNull(diffTypes), + schemaComparisons, objectChangeFilter, printStream); + CompareControl compareControl = new CompareControl(schemaComparisons, diffTypes); - CommandScope formattedDiffCommand = new CommandScope("internalFormattedDiff"); - formattedDiffCommand.addArgumentValue("format", format); - formattedDiffCommand.addArgumentValue("diffCommand", liquibaseCommand); + liquibaseCommand.addArgumentValue("format", format); + liquibaseCommand.addArgumentValue("diffCommand", diffCommand); + liquibaseCommand.addArgumentValue("targetDatabase", db); + liquibaseCommand.addArgumentValue("referenceDatabase", referenceDatabase); + liquibaseCommand.addArgumentValue("compareControl", compareControl); + liquibaseCommand.addArgumentValue("objectChangeFilter", objectChangeFilter); + if (StringUtil.isEmpty(diffTypes)) { + liquibaseCommand.addArgumentValue("snapshotTypes", new Class[0]); + } else { + liquibaseCommand.addArgumentValue("snapshotTypes", diffTypes); + } - formattedDiffCommand.execute(); - } else { - CommandLineUtils.doDiff(referenceDatabase, db, StringUtil.trimToNull(diffTypes), schemaComparisons, objectChangeFilter, printStream); + CommandScope formattedDiffCommand = new CommandScope("internalFormattedDiff"); + formattedDiffCommand.addArgumentValue("format", format); + formattedDiffCommand.addArgumentValue("diffCommand", liquibaseCommand); + + formattedDiffCommand.execute(); + } else { + CommandLineUtils.doDiff(referenceDatabase, db, StringUtil.trimToNull(diffTypes), schemaComparisons, objectChangeFilter, printStream); + } } } } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseGenerateChangeLogMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseGenerateChangeLogMojo.java index f339ce3bcc4..1e5daeb205c 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseGenerateChangeLogMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseGenerateChangeLogMojo.java @@ -43,7 +43,7 @@ public class LiquibaseGenerateChangeLogMojo extends protected String dataDir; /** - * The author to be specified for Change Sets in the generated Change Log. + * The author to be specified for Changesets in the generated Change Log. * * @parameter property="liquibase.changeSetAuthor" */ @@ -58,7 +58,7 @@ public class LiquibaseGenerateChangeLogMojo extends protected String contexts; /** - * The execution context to be used for Change Sets in the generated Change Log, which can be "," separated if multiple contexts. + * The execution context to be used for Changesets in the generated Change Log, which can be "," separated if multiple contexts. * * @parameter property="liquibase.changeSetContext" */ diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollback.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollback.java index 8cd17ec3a82..96b9f2af088 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollback.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollback.java @@ -15,7 +15,7 @@ /** *

    Invokes Liquibase to rollback the database (and mark changesets as unapplied). The - * change sets to be rolled back are specified using attributes 'rollbackCount', + * changesets to be rolled back are specified using attributes 'rollbackCount', * 'rollbackTag' and/or 'rollbackDate'

    * @author Peter Murray * @goal rollback @@ -34,7 +34,7 @@ protected enum RollbackType { protected String rollbackTag; /** - * The number of change sets to rollback. + * The number of changesets to rollback. * @parameter property="liquibase.rollbackCount" default-value="-1" */ protected int rollbackCount; diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetMojo.java index d3ca4d7ef4a..98d9b451a3e 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetMojo.java @@ -23,7 +23,7 @@ public class LiquibaseRollbackOneChangeSetMojo extends AbstractLiquibaseChangeLo /** * - * The change set ID to rollback + * The changeset ID to rollback * * @parameter property="liquibase.changeSetId" * @@ -80,9 +80,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { @Override protected void printSettings(String indent) { super.printSettings(indent); - getLog().info(indent + "Change Set ID: " + changeSetId); - getLog().info(indent + "Change Set Author: " + changeSetAuthor); - getLog().info(indent + "Change Set Path: " + changeSetPath); + getLog().info(indent + "Changeset ID: " + changeSetId); + getLog().info(indent + "Changeset Author: " + changeSetAuthor); + getLog().info(indent + "Changeset Path: " + changeSetPath); getLog().info(indent + "Rollback script: " + rollbackScript); } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetSQL.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetSQL.java index c8d2ce14d97..325003a3d3e 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetSQL.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetSQL.java @@ -30,7 +30,7 @@ public class LiquibaseRollbackOneChangeSetSQL extends AbstractLiquibaseChangeLog /** * - * The change set ID to rollback + * The changeset ID to rollback * * @parameter property="liquibase.changeSetId" * @@ -85,9 +85,9 @@ public class LiquibaseRollbackOneChangeSetSQL extends AbstractLiquibaseChangeLog @Override protected void printSettings(String indent) { super.printSettings(indent); - getLog().info(indent + "Change Set ID: " + changeSetId); - getLog().info(indent + "Change Set Author: " + changeSetAuthor); - getLog().info(indent + "Change Set Path: " + changeSetPath); + getLog().info(indent + "Changeset ID: " + changeSetId); + getLog().info(indent + "Changeset Author: " + changeSetAuthor); + getLog().info(indent + "Changeset Path: " + changeSetPath); getLog().info(indent + "Rollback script: " + rollbackScript); } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneUpdateSQL.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneUpdateSQL.java index f89eb5e8e12..1b0cb4ce0f2 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneUpdateSQL.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneUpdateSQL.java @@ -27,7 +27,7 @@ */ public class LiquibaseRollbackOneUpdateSQL extends AbstractLiquibaseChangeLogMojo { /** - * Specifies the Deployment ID in the DATABASECHANGELOG table for all change sets you + * Specifies the Deployment ID in the DATABASECHANGELOG table for all changesets you * want to rollback. * * @parameter property="liquibase.deploymentId" diff --git a/liquibase-maven-plugin/src/main/maven/liquibase-deployment-pom.xslt b/liquibase-maven-plugin/src/main/maven/liquibase-deployment-pom.xslt deleted file mode 100644 index ae28b294422..00000000000 --- a/liquibase-maven-plugin/src/main/maven/liquibase-deployment-pom.xslt +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - Liquibase Maven Plugin - - - - diff --git a/liquibase-maven-plugin/src/main/maven/release.pom.xml b/liquibase-maven-plugin/src/main/maven/release.pom.xml new file mode 100644 index 00000000000..66af84f45fc --- /dev/null +++ b/liquibase-maven-plugin/src/main/maven/release.pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + org.liquibase + liquibase-maven-plugin + 0-SNAPSHOT + maven-plugin + Liquibase Maven Plugin + A Maven plugin wraps up some of the functionality of Liquibase + http://www.liquibase.org/liquibase-maven-plugin + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + + + + + nvoxland + Nathan Voxland + nathan.voxland@liquibase.org + + architect + developer + + -6 + + + + scm:git:git@github.com:liquibase/liquibase.git/liquibase-maven-plugin + scm:git:git@github.com:liquibase/liquibase.git/liquibase-maven-plugin + scm:git:git@github.com:liquibase/liquibase.git/liquibase-maven-plugin + + + + org.liquibase + liquibase-core + 0-SNAPSHOT + runtime + + + org.liquibase + liquibase-commercial + 0-SNAPSHOT + runtime + + + diff --git a/pom.xml b/pom.xml index 973eeb7f3a6..4cfd28a639a 100644 --- a/pom.xml +++ b/pom.xml @@ -192,14 +192,14 @@ org.postgresql postgresql - 42.3.4 + 42.4.0 test org.mariadb.jdbc mariadb-java-client - 3.0.5 + 3.0.6 test @@ -247,7 +247,7 @@ org.glassfish.jaxb jaxb-runtime - 2.3.6 + 4.0.0 test