From ed687b1f78e01807ecdea6fbfb907c1ddf181f7a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 20:42:15 +0200 Subject: [PATCH 01/32] chore(main): release 2.20.3-SNAPSHOT (#1699) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 9f17e9c78..48bad350b 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 google-cloud-spanner-jdbc - 2.20.2 + 2.20.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index ef21adcf1..fcfad34c9 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.2 + 2.20.3-SNAPSHOT diff --git a/versions.txt b/versions.txt index 6f8ffa714..716f29f11 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.20.2:2.20.2 +google-cloud-spanner-jdbc:2.20.2:2.20.3-SNAPSHOT From f3f0c10394e76389dbc4a62e5702fd5f80c57b1a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 11:54:29 +0200 Subject: [PATCH 02/32] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.34.0 (#1705) --- .github/workflows/unmanaged_dependency_check.yaml | 2 +- .kokoro/presubmit/graalvm-native-17.cfg | 2 +- .kokoro/presubmit/graalvm-native.cfg | 2 +- pom.xml | 2 +- samples/snippets/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/unmanaged_dependency_check.yaml b/.github/workflows/unmanaged_dependency_check.yaml index 09f954387..8d462abb5 100644 --- a/.github/workflows/unmanaged_dependency_check.yaml +++ b/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.33.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.34.0 with: bom-path: pom.xml diff --git a/.kokoro/presubmit/graalvm-native-17.cfg b/.kokoro/presubmit/graalvm-native-17.cfg index 7008a7215..53cd15405 100644 --- a/.kokoro/presubmit/graalvm-native-17.cfg +++ b/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.33.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.34.0" } env_vars: { diff --git a/.kokoro/presubmit/graalvm-native.cfg b/.kokoro/presubmit/graalvm-native.cfg index 931f9bb00..e211e47fc 100644 --- a/.kokoro/presubmit/graalvm-native.cfg +++ b/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.33.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.34.0" } env_vars: { diff --git a/pom.xml b/pom.xml index 48bad350b..4ab18c747 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.33.0 + 3.34.0 diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index ee6deda8b..1df5b3ee5 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.33.0 + 3.34.0 From e82d8398eede11469c966aa11c2188c671a5f02b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 12:04:54 +0200 Subject: [PATCH 03/32] deps: update dependency org.springframework.data:spring-data-bom to v2024.0.3 (#1704) --- samples/spring-data-jdbc/pom.xml | 2 +- samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index f2d20d8ac..019a08a3f 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.0.2 + 2024.0.3 import pom diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index a5ad7633d..0768173bf 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.0.2 + 2024.0.3 import pom From af58b7a882edae9a50fbc0d4084cb74b3727d5a6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 12:05:43 +0200 Subject: [PATCH 04/32] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.41.0 (#1703) --- samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 019a08a3f..fbf80e355 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.40.0 + 1.41.0 pom import From 31a961d29c7b51e9dcd5aac8a8a66444abbd9088 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 12:06:10 +0200 Subject: [PATCH 05/32] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.72.0 (#1702) --- samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index fbf80e355..866ef4812 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.71.0 + 6.72.0 import pom From 6092016f7b95a9c1f62d65be5d30be5fdcf700c1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 12:06:46 +0200 Subject: [PATCH 06/32] chore(deps): update dependency com.google.cloud:libraries-bom to v26.44.0 (#1701) --- samples/snippets/pom.xml | 2 +- samples/spring-data-jdbc/pom.xml | 2 +- samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 1df5b3ee5..3260b2985 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.43.0 + 26.44.0 pom import diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 866ef4812..f6135bb29 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.43.0 + 26.44.0 import pom diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index 0768173bf..29fa43af7 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.43.0 + 26.44.0 import pom From c49c9db3025a9e9db1c99f2140755fcc0f758e00 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 12:07:11 +0200 Subject: [PATCH 07/32] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.20.2 (#1700) --- samples/install-without-bom/pom.xml | 2 +- samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 87be572f4..522c41a61 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.1 + 2.20.2 diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index f6135bb29..0cb0aaa7c 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.1 + 2.20.2 org.postgresql From 09073057df2cff41b7a62f56dc0cf57ed62f4801 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 14:21:24 +0200 Subject: [PATCH 08/32] deps: update dependency org.testcontainers:testcontainers to v1.20.1 (#1684) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency org.testcontainers:testcontainers to v1.20.1 * chore: ignore errors during availability check --------- Co-authored-by: Knut Olav Løite --- pom.xml | 2 +- samples/snippets/pom.xml | 2 +- samples/spring-data-jdbc/pom.xml | 2 +- .../spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java | 8 +++++++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 4ab18c747..97c020916 100644 --- a/pom.xml +++ b/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 1.19.8 + 1.20.1 test diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 3260b2985..2d0ed2811 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -48,7 +48,7 @@ org.testcontainers testcontainers - 1.19.8 + 1.20.1 test diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 0cb0aaa7c..b6ea7780b 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -109,7 +109,7 @@ org.testcontainers testcontainers - 1.19.8 + 1.20.1 test diff --git a/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java b/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java index 887412048..74a005038 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java @@ -45,7 +45,13 @@ public class ConcurrentTransactionOnEmulatorTest { @BeforeClass public static void startEmulator() { - assumeTrue(DockerClientFactory.instance().isDockerAvailable()); + boolean dockerAvailable = false; + try { + dockerAvailable = DockerClientFactory.instance().isDockerAvailable(); + } catch (Exception ignore) { + // Ignore, and just skip the test. + } + assumeTrue(dockerAvailable); emulator = new GenericContainer<>( From c0548908abc801064e4c514df1e7eeab99a46c71 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 12:16:31 +0200 Subject: [PATCH 09/32] build(deps): update dependency org.apache.maven.plugins:maven-deploy-plugin to v3.1.3 (#1707) --- samples/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/pom.xml b/samples/pom.xml index 31285be61..39d5d24c8 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -39,7 +39,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.2 + 3.1.3 true From 68815128ae2c40c224b4ab155b942e8f5313024f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 14:31:25 +0200 Subject: [PATCH 10/32] deps: update dependency com.spotify.fmt:fmt-maven-plugin to v2.24 (#1708) --- samples/spring-data-jdbc/pom.xml | 2 +- samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index b6ea7780b..6a138bbcf 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -119,7 +119,7 @@ com.spotify.fmt fmt-maven-plugin - 2.23 + 2.24 diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index 29fa43af7..87793be8d 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -97,7 +97,7 @@ com.spotify.fmt fmt-maven-plugin - 2.23 + 2.24 From b6bbd8f40c1ce61914e2c7b80be04abbf4e346ab Mon Sep 17 00:00:00 2001 From: Szabolcs Rozsnyai Date: Tue, 20 Aug 2024 14:50:19 +0200 Subject: [PATCH 11/32] feat: add Quickperf for simple performance testing with JDBC (#1619) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat:Adding Quickperf for simple performance testing with JDBC * Update samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java Co-authored-by: Knut Olav Løite * Update samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerf.java Co-authored-by: Knut Olav Løite * Update samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerf.java Co-authored-by: Knut Olav Løite * Update samples/quickperf/readme.md Co-authored-by: Knut Olav Løite * Update samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java Co-authored-by: Knut Olav Løite * Update samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java Co-authored-by: Knut Olav Løite * Update samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java Co-authored-by: Knut Olav Løite * Updating based on review comments #1619 * Updating based on review comments * Incorporating additional changes from review #1619 * Split app into two classes to separate app driver and app following review feedback #1619 * fixed compilation issues * Update readme.md fixed markdown issues for indented bullet points * Update readme.md removed -Dexec.args from readme * Update QuickPerf.java separated thread init (for sampling) from thread execution * Update ProgressTracker.java added InterruptedException handling * chore: add parent pom and run code formatter * chore: cleanup some warnings + simplify test setup * test: add test runner for quickperf * chore: remove some more warnings * fix: include empty test file --------- Co-authored-by: Knut Olav Løite --- .github/workflows/quickperf.yaml | 30 ++ samples/quickperf/.gitignore | 3 + samples/quickperf/exampleconfigs/config.json | 9 + .../exampleconfigs/users/groupmgt_config.json | 13 + .../exampleconfigs/users/loadtestusers.json | 13 + .../users/membership_config.json | 9 + samples/quickperf/exampleconfigs/users/run.sh | 15 + .../quickperf/exampleconfigs/users/users.ddl | 17 + .../exampleconfigs/users/users_config.json | 13 + samples/quickperf/java.header | 15 + samples/quickperf/license-checks.xml | 10 + samples/quickperf/pom.xml | 100 ++++++ samples/quickperf/readme.md | 302 +++++++++++++++++ .../cloud/jdbc/quickperf/ProgressTracker.java | 79 +++++ .../cloud/jdbc/quickperf/QuickPerf.java | 191 +++++++++++ .../cloud/jdbc/quickperf/QuickPerfRunner.java | 320 ++++++++++++++++++ .../cloud/jdbc/quickperf/config/Config.java | 145 ++++++++ .../jdbc/quickperf/config/ConfigParser.java | 30 ++ .../jdbc/quickperf/config/QueryParam.java | 38 +++ .../google/cloud/jdbc/quickperf/AppTest.java | 174 ++++++++++ .../cloud/jdbc/quickperf/ProjectConfig.java | 113 +++++++ .../cloud/jdbc/quickperf/QueryParam.java | 45 +++ .../src/test/resources/testfile.json | 0 23 files changed, 1684 insertions(+) create mode 100644 .github/workflows/quickperf.yaml create mode 100644 samples/quickperf/.gitignore create mode 100644 samples/quickperf/exampleconfigs/config.json create mode 100644 samples/quickperf/exampleconfigs/users/groupmgt_config.json create mode 100644 samples/quickperf/exampleconfigs/users/loadtestusers.json create mode 100644 samples/quickperf/exampleconfigs/users/membership_config.json create mode 100755 samples/quickperf/exampleconfigs/users/run.sh create mode 100644 samples/quickperf/exampleconfigs/users/users.ddl create mode 100644 samples/quickperf/exampleconfigs/users/users_config.json create mode 100644 samples/quickperf/java.header create mode 100644 samples/quickperf/license-checks.xml create mode 100644 samples/quickperf/pom.xml create mode 100644 samples/quickperf/readme.md create mode 100644 samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java create mode 100644 samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerf.java create mode 100644 samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerfRunner.java create mode 100644 samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/Config.java create mode 100644 samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/ConfigParser.java create mode 100644 samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/QueryParam.java create mode 100644 samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/AppTest.java create mode 100644 samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/ProjectConfig.java create mode 100644 samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/QueryParam.java create mode 100644 samples/quickperf/src/test/resources/testfile.json diff --git a/.github/workflows/quickperf.yaml b/.github/workflows/quickperf.yaml new file mode 100644 index 000000000..03c242fef --- /dev/null +++ b/.github/workflows/quickperf.yaml @@ -0,0 +1,30 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# Github action job to test core java library features on +# downstream client libraries before they are released. +on: + pull_request: +name: quickperf +jobs: + quickperf: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + - name: Run tests + run: mvn test + working-directory: samples/quickperf diff --git a/samples/quickperf/.gitignore b/samples/quickperf/.gitignore new file mode 100644 index 000000000..1df5b5e0c --- /dev/null +++ b/samples/quickperf/.gitignore @@ -0,0 +1,3 @@ +target +.vscode +.DS_Store \ No newline at end of file diff --git a/samples/quickperf/exampleconfigs/config.json b/samples/quickperf/exampleconfigs/config.json new file mode 100644 index 000000000..b43c32e1c --- /dev/null +++ b/samples/quickperf/exampleconfigs/config.json @@ -0,0 +1,9 @@ +{ + "project": "xxxx", + "instance": "xxx", + "database": "xxx", + "threads": 1, + "iterations": 100, + "query": "SELECT 1", + "writeMetricToFile": false +} \ No newline at end of file diff --git a/samples/quickperf/exampleconfigs/users/groupmgt_config.json b/samples/quickperf/exampleconfigs/users/groupmgt_config.json new file mode 100644 index 000000000..8bc094513 --- /dev/null +++ b/samples/quickperf/exampleconfigs/users/groupmgt_config.json @@ -0,0 +1,13 @@ +{ + "project": "xxx", + "instance": "xxx", + "database": "users", + "threads": 4, + "iterations": 250, + "query": "INSERT INTO GroupMgmt (group_id, grpname) VALUES(?,?)", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#i"}, + {"order": 2, "value": "#s"} + ] +} \ No newline at end of file diff --git a/samples/quickperf/exampleconfigs/users/loadtestusers.json b/samples/quickperf/exampleconfigs/users/loadtestusers.json new file mode 100644 index 000000000..4a4a3aee8 --- /dev/null +++ b/samples/quickperf/exampleconfigs/users/loadtestusers.json @@ -0,0 +1,13 @@ +{ + "project": "xxx", + "instance": "xxx", + "database": "users", + "threads": 1, + "iterations": 10, + "query": "SELECT users.user_id, membership.enrolled, GroupMgmt.grpname FROM users, GroupMgmt, membership WHERE users.user_id = ? AND users.user_id = membership.user_id AND GroupMgmt.group_id = membership.group_id", + "samplingQuery": "SELECT user_id FROM Users TABLESAMPLE RESERVOIR (100000 ROWS)", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#pi"} + ] +} \ No newline at end of file diff --git a/samples/quickperf/exampleconfigs/users/membership_config.json b/samples/quickperf/exampleconfigs/users/membership_config.json new file mode 100644 index 000000000..d3c56d101 --- /dev/null +++ b/samples/quickperf/exampleconfigs/users/membership_config.json @@ -0,0 +1,9 @@ +{ + "project": "xxx", + "instance": "xxx", + "database": "users", + "threads": 1, + "iterations": 100, + "query": "INSERT INTO membership(user_id, group_id, enrolled) VALUES((SELECT user_id FROM Users TABLESAMPLE RESERVOIR (1 ROWS)), (SELECT group_id FROM GroupMgmt TABLESAMPLE RESERVOIR (1 ROWS)), CURRENT_TIMESTAMP())", + "writeMetricToFile": false +} \ No newline at end of file diff --git a/samples/quickperf/exampleconfigs/users/run.sh b/samples/quickperf/exampleconfigs/users/run.sh new file mode 100755 index 000000000..ac82643f8 --- /dev/null +++ b/samples/quickperf/exampleconfigs/users/run.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Generate Data +cd ../.. + +mvn -q compile + +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/users_config.json" + +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/groupmgt_config.json" + +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/membership_config.json" + +# load test random users +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/loadtestusers.json" diff --git a/samples/quickperf/exampleconfigs/users/users.ddl b/samples/quickperf/exampleconfigs/users/users.ddl new file mode 100644 index 000000000..6498bb591 --- /dev/null +++ b/samples/quickperf/exampleconfigs/users/users.ddl @@ -0,0 +1,17 @@ +CREATE TABLE GroupMgmt ( + group_id INT64, + grpname STRING(MAX), +) PRIMARY KEY(group_id); + +CREATE TABLE Users ( + user_id INT64, + name STRING(MAX), +) PRIMARY KEY(user_id); + +CREATE TABLE membership ( + user_id INT64, + group_id INT64, + enrolled TIMESTAMP NOT NULL OPTIONS ( + allow_commit_timestamp = true + ), +) PRIMARY KEY(user_id, group_id); \ No newline at end of file diff --git a/samples/quickperf/exampleconfigs/users/users_config.json b/samples/quickperf/exampleconfigs/users/users_config.json new file mode 100644 index 000000000..6cdbbedc5 --- /dev/null +++ b/samples/quickperf/exampleconfigs/users/users_config.json @@ -0,0 +1,13 @@ +{ + "project": "xxx", + "instance": "xxx", + "database": "users", + "threads": 1, + "iterations": 1000, + "query": "INSERT INTO Users (user_id, name) VALUES(?,?)", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#i"}, + {"order": 2, "value": "#s"} + ] +} \ No newline at end of file diff --git a/samples/quickperf/java.header b/samples/quickperf/java.header new file mode 100644 index 000000000..d0970ba7d --- /dev/null +++ b/samples/quickperf/java.header @@ -0,0 +1,15 @@ +^/\*$ +^ \* Copyright \d\d\d\d,? Google (Inc\.|LLC)$ +^ \*$ +^ \* Licensed under the Apache License, Version 2\.0 \(the "License"\);$ +^ \* you may not use this file except in compliance with the License\.$ +^ \* You may obtain a copy of the License at$ +^ \*$ +^ \*[ ]+https?://www.apache.org/licenses/LICENSE-2\.0$ +^ \*$ +^ \* Unless required by applicable law or agreed to in writing, software$ +^ \* distributed under the License is distributed on an "AS IS" BASIS,$ +^ \* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\.$ +^ \* See the License for the specific language governing permissions and$ +^ \* limitations under the License\.$ +^ \*/$ diff --git a/samples/quickperf/license-checks.xml b/samples/quickperf/license-checks.xml new file mode 100644 index 000000000..a7a611940 --- /dev/null +++ b/samples/quickperf/license-checks.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/samples/quickperf/pom.xml b/samples/quickperf/pom.xml new file mode 100644 index 000000000..38750500e --- /dev/null +++ b/samples/quickperf/pom.xml @@ -0,0 +1,100 @@ + + + + 4.0.0 + + com.google.cloud.jdbc.quickperf + jdbc-quickperf + 1.0.0 + jdbc-quickperf + + com.google.cloud + sdk-platform-java-config + 3.34.0 + + + + + UTF-8 + 1.8 + 1.8 + + + + + + com.google.cloud + libraries-bom + 26.43.0 + pom + import + + + + + + + net.datafaker + datafaker + 2.3.1 + + + com.google.cloud + google-cloud-spanner + + + commons-cli + commons-cli + 1.5.0 + + + com.google.cloud + google-cloud-spanner-jdbc + + + org.apache.commons + commons-lang3 + 3.13.0 + + + com.fasterxml.jackson.core + jackson-databind + 2.13.4.1 + + + + org.testcontainers + testcontainers + 1.20.1 + test + + + org.springframework.boot + spring-boot + 3.2.5 + test + + + junit + junit + 4.13.1 + test + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + com.google.cloud.jdbc.quickperf.QuickPerf + + + + + + \ No newline at end of file diff --git a/samples/quickperf/readme.md b/samples/quickperf/readme.md new file mode 100644 index 000000000..675155b94 --- /dev/null +++ b/samples/quickperf/readme.md @@ -0,0 +1,302 @@ +# Introduction + +QuickPerf is a simple utility that uses JDBC to perform load testing on individual statements (such as queries and DML) against Spanner. It provides a rapid assessment of expected end-to-end latencies for specific statements, aiding in the performance tuning of schemas, indexes, and more. The tool includes random data generators to quickly fill a given schema with dummy data, respecting foreign-key relationships and interleaved tables. + +QuickPerf is not designed to replace comprehensive test suites like JMeter. Instead, it serves as a quick alternative for gaining performance insights or populating schemas. + +**Key Features**: +* Multi-threading to simulate concurrency +* Query parameterization with random value generators (String, Integer, Timestamp) +* Sampling of records for seeding foreign-key relationships or testing against a specific subset of data +* Batch mode support +* Automatic statement and transaction tagging + + +# Installation on Ubuntu +``` +sudo apt-get install openjdk-8-jdk +sudo apt install maven +``` + +## Authentification +It is recommended to use a service account, otherwise larger scale tests will run into quota limitations + +Set active auth to service account: +``` +gcloud auth list +gcloud config set account xxx-compute@developer.gserviceaccount.com +``` + +# Configuration + +## Parameters +``` +{ + "project": "Project ID", + "instance": "Spanner Instance", + "database": "Spanner Database", + "threads": Number of concurrent threads, + "iterations": Number of how often a statement should be executed in a thread, + "query": "Statement (e.g. query)", + "samplingQuery": "OPTIONAL - Sampling query", + "writeMetricToFile": Will write latency metrics to a file (true/false), + "batchSize": If testing batching - determines how large a batch size would be, + "queryParams": [ + {"order": 1, "value": "query paramters with value generator"} + ] +} +``` + +## Example Config +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "users", + "threads": 1, + "iterations": 10, + "query": "SELECT users.user_id, membership.enrolled, GroupMgmt.grpname FROM users, GroupMgmt, membership WHERE users.user_id = ? AND users.user_id = membership.user_id AND GroupMgmt.group_id = membership.group_id", + "samplingQuery": "SELECT user_id FROM Users TABLESAMPLE RESERVOIR (100000 ROWS)", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#pi"} + ] +} +``` + +# Hello World Example + +The folder `exampleconfigs/config.json` contains a simple setup that runs SELECT 1 against the database + +Configure the right Spanner `project` and `instance` and run the app. + +**config.json** +``` +{ +"project": "xxxx", +"instance": "xxx", +"database": "xxx", +"threads": 1, +"iterations": 100, +"query": "SELECT 1", +"writeMetricToFile": false, +"batchSize": 0 +} +``` + +**Run:** +``` +mvn -q exec:java -Dexec.args="-c exampleconfigs/config.json" +``` + + + +# End-to-End Example + +Generates three tables with n:m relationships and performs a load test. + +All in one runner generating test data and executing load test: +``` +exampleconfigs/users/run.sh +``` + +What needs to be done to run it: +* Create spanner instance +* Create database named `users` +* Set `project` and `instance` in each of the config JSON files located under `exampleconfigs/users/users_config.json` + * `exampleconfigs/users/users_config.json` + * `exampleconfigs/users/groupmgt_config.json` + * `exampleconfigs/users/membership_config.json` + * `exampleconfigs/users/loadtestusers.json` + + +**Generate users table:** + +``` +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/users_config.json" +``` + +users_config.json: +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "users", + "threads": 4, + "iterations": 1000, + "query": "INSERT INTO Users (user_id, name) VALUES(?,?)", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#i"}, + {"order": 2, "value": "#s"} + ] +} +``` + +**Generate GroupMgmt table:** + +``` +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/groupmgt_config.json" +``` + +groupmgt_config.json +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "users", + "threads": 4, + "iterations": 1000, + "query": "INSERT INTO GroupMgmt (group_id, grpname) VALUES(?,?)", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#i"}, + {"order": 2, "value": "#s"} + ] +} +``` + +**Generate Membership table:** + +Run: +``` +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/membership_config.json" +``` + +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "users", + "threads": 1, + "iterations": 100, + "query": "INSERT INTO membership(user_id, group_id, enrolled) VALUES((SELECT user_id FROM Users TABLESAMPLE RESERVOIR (1 ROWS)), (SELECT group_id FROM GroupMgmt TABLESAMPLE RESERVOIR (1 ROWS)), CURRENT_TIMESTAMP())", + "writeMetricToFile": false +} +``` + + +Load test random users +``` +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/loadtestusers.json" +``` + +# Randomization examples + +## String +Will generate a different random String value for each #s +``` +INSERT INTO transactions (id, name, ts) VALUES (#s, #s, CURRENT_TIMESTAMP()) +``` +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "xxxx", + "threads": 4, + "iterations": 1000, + "query": "INSERT INTO transactions (id, name, ts) VALUES (?, ?, CURRENT_TIMESTAMP())", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#s"}, + {"order": 2, "value": "#s"} + ] +} +``` + +``` +SELECT * FROM transactions WHERE id=#s +``` +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "xxxx", + "threads": 4, + "iterations": 1000, + "query": "SELECT * FROM transactions WHERE id=?", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#s"}, + ] +} +``` + + +## Integer +Will generate a different random value for each #i +``` +UPDATE accounts SET cid=#i WHERE aaId=4 +``` + +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "xxxx", + "threads": 4, + "iterations": 1000, + "query": "UPDATE accounts SET ? WHERE aaId=4", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#i"}, + ] +} +``` + +## Integer min max +Generates #i(1,10) integer values between 1 and 10 +``` +INSERT INTO test (id, groupid, amount) VALUES (#s, #i(1,2)#, #i) +``` + +## Timestamp +Workaround for not randomizing timestamps is to use current_timestsamp() +``` +INSERT INTO transactions (id, name, ts) VALUES (#s, #s, CURRENT_TIMESTAMP())' +``` +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "xxxx", + "threads": 4, + "iterations": 1000, + "query": "INSERT INTO transactions (id, name, ts) VALUES (?, ?, CURRENT_TIMESTAMP())'", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#s"}, + {"order": 1, "value": "#s"} + ] +} +``` + +## Sampling IDs +Sometimes it might be required to sample existing IDs that are then used in the query that is executed. +The parameter ```-s``` allows to pull a sampled dataset, but only one column is allowed in the resultset. +This query is executed only once and before the beginning of the run and the dataset is reused across the threads. + +* #ps will add quotes - such as for Strings +* #pi will **not** add quotes such as when integers are used + +In this case the #ps is the placeholder for samples that are pulled from the -s parameter +``` +-q 'SELECT * FROM test WHERE id = #ps'' +-s 'SELECT id FROM test TABLESAMPLE RESERVOIR (100 ROWS)' +``` + +## Many-to-Many Relationship Example +Insert Users +``` +INSERT INTO Users (user_id, name) VALUES(#i,#s) +``` + +Insert Groups +``` +INSERT INTO GroupMgmt (group_id, grpname) VALUES(#i,#s) +``` + +Insert relationships with sampling: +``` +INSERT INTO membership(user_id, group_id, enrolled) VALUES((SELECT user_id FROM Users TABLESAMPLE RESERVOIR (1 ROWS)), (SELECT group_id FROM GroupMgmt TABLESAMPLE RESERVOIR (1 ROWS)), CURRENT_TIMESTAMP()) +``` \ No newline at end of file diff --git a/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java b/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java new file mode 100644 index 000000000..90b241b1d --- /dev/null +++ b/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java @@ -0,0 +1,79 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf; + +import java.util.List; + +public class ProgressTracker extends Thread { + private static final int SLEEP_TIME_INIT = 2000; + private static final int SLEEP_TIME_POLL = 200; + + private final List threadList; + + private final int maxIt; + private int currentIt = 0; + + public ProgressTracker(List threadList, int maxIt) { + this.threadList = threadList; + this.maxIt = maxIt; + } + + public void run() { + sleep(SLEEP_TIME_INIT); + while (currentIt < maxIt) { + currentIt = 0; + for (QuickPerfRunner thread : threadList) { + currentIt = currentIt + thread.getProgress(); + + int percent = (int) Math.ceil(((double) currentIt / maxIt) * 100.0); + print_progress(percent); + } + + if (sleep(SLEEP_TIME_POLL)) { + break; + } + } + print_progress(100); + } + + public void print_progress(int percent) { + StringBuilder bar = new StringBuilder("Progress: ["); + + for (int i = 0; i < 50; i++) { + if (i < (percent / 2)) { + bar.append("="); + } else if (i == (percent / 2)) { + bar.append(">"); + } else { + bar.append(" "); + } + } + + bar.append("] ").append(percent).append("% "); + System.out.print("\r" + bar); + } + + private boolean sleep(int sleeptime) { + try { + Thread.sleep(sleeptime); + } catch (InterruptedException e) { + System.err.println("Progress tracker thread interrupted"); + return true; + } + return false; + } +} diff --git a/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerf.java b/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerf.java new file mode 100644 index 000000000..9eb0fc45c --- /dev/null +++ b/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerf.java @@ -0,0 +1,191 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf; + +import com.google.cloud.jdbc.quickperf.config.Config; +import com.google.cloud.jdbc.quickperf.config.ConfigParser; +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.lang3.ArrayUtils; + +public class QuickPerf extends Thread { + + private static final String BREAK_STR = + "###################################################################################################"; + + // TODO: make measurement file configurable + private static final String MEASURES_FILE_NAME = "measures.txt"; + + public static void main(String[] args) throws Exception { + Options options = new Options(); + + options.addOption(QuickPerf.addOption("c", "config", true, "Config File")); + + CommandLineParser parser = new DefaultParser(); + HelpFormatter formatter = new HelpFormatter(); + CommandLine cmd = null; + + ZonedDateTime testStartTimestamp = ZonedDateTime.now(); + + try { + cmd = parser.parse(options, args); + } catch (ParseException e) { + System.out.println(e.getMessage()); + formatter.printHelp("utility-name", options); + + System.exit(1); + } + + Config config = ConfigParser.parseConfigFile(cmd.getOptionValue("config")); + + float[] measures = new float[config.getIterations() * config.getThreads()]; + + // initialize threads (for sampling if present) + List threadList = new ArrayList(); + for (int i = 0; i < config.getThreads(); i++) { + QuickPerfRunner thread = new QuickPerfRunner(config); + if (config.getSamplingQuery() != null) { + thread.runSampling(); + } + threadList.add(thread); + } + + // start threads + for (QuickPerfRunner thread : threadList) { + thread.start(); + } + + // ProgressBar Tracker Thread + ProgressTracker progressTracker = + progressTracker = + new ProgressTracker(threadList, config.getIterations() * config.getThreads()); + + progressTracker.start(); + progressTracker.join(); + + int i = 0; + for (QuickPerfRunner thread : threadList) { + thread.join(); + + if (i == 0) { + measures = thread.getMeasures(); + } else { + measures = ArrayUtils.addAll(measures, thread.getMeasures()); + } + i++; + } + + // write to file before its sorted + if (config.getWriteMetricToFile()) { + try { + writeMeasuresToFile(measures, MEASURES_FILE_NAME); + } catch (IOException e) { + System.err.println("An error occurred while writing the file: " + e.getMessage()); + } + } + + System.out.println("\n" + BREAK_STR); + System.out.println("Query: " + config.getQuery()); + System.out.println("Params: " + config.paramsToString()); + System.out.println("Tag: " + Config.DEFAULT_TAG); + if (config.getBatchSize() > 0) { + System.out.println("Batching Enabled (size): " + config.getBatchSize()); + } + System.out.printf("Start: %s End: %s%n", testStartTimestamp, ZonedDateTime.now()); + System.out.printf( + "Finished with a total of %s runs across %s Threads.\nLatencies (ms): p50 = %s, p95 = %s, p99 = %s, min = %s, max = %s%n", + config.getIterations() * config.getThreads(), + config.getThreads(), + calcPerc(measures, 50), + calcPerc(measures, 95), + calcPerc(measures, 99), + getMin(measures), + getMax(measures)); + System.out.println(BREAK_STR); + } + + public static Option addOption(String option, String longOption, boolean hasArgs, String desc) { + Option opt = new Option(option, longOption, hasArgs, desc); + opt.setRequired(true); + + return opt; + } + + public static Option addOption( + String option, String longOption, boolean hasArgs, String desc, boolean required) { + Option opt = new Option(option, longOption, hasArgs, desc); + opt.setRequired(required); + + return opt; + } + + public static float calcPerc(float[] nums, double percentile) { + int n = nums.length; + Arrays.sort(nums); + + double index = (percentile / 100) * (n - 1); + + if (index == Math.floor(index)) { + return nums[(int) index]; + } else { + int lowerIndex = (int) Math.floor(index); + int upperIndex = (int) Math.ceil(index); + float lowerValue = nums[lowerIndex]; + float upperValue = nums[upperIndex]; + return (float) ((1 - (index - lowerIndex)) * lowerValue + (index - lowerIndex) * upperValue); + } + } + + public static float getMax(float[] measures) { + if (measures == null || measures.length == 0) { + throw new IllegalArgumentException("Array is null or empty"); + } + + Arrays.sort(measures); + return measures[measures.length - 1]; + } + + public static float getMin(float[] measures) { + if (measures == null || measures.length == 0) { + throw new IllegalArgumentException("Array is null or empty"); + } + + Arrays.sort(measures); + return measures[0]; + } + + public static void writeMeasuresToFile(float[] array, String fileName) throws IOException { + try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) { + for (float value : array) { + writer.write(Float.toString(value)); + writer.newLine(); + } + } + } +} diff --git a/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerfRunner.java b/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerfRunner.java new file mode 100644 index 000000000..84e2bc9ac --- /dev/null +++ b/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerfRunner.java @@ -0,0 +1,320 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.jdbc.quickperf; + +import com.google.cloud.jdbc.quickperf.config.Config; +import com.google.cloud.jdbc.quickperf.config.QueryParam; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; +import java.security.SecureRandom; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.Random; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import net.datafaker.Faker; + +public class QuickPerfRunner extends Thread { + private static final Properties DEFAULT_PROPERTIES = new Properties(); + + // perf measurement + private float[] measures; + + private final List sampledValueList = new ArrayList(); + private final Config config; + + private int progress; + + public QuickPerfRunner(Config config) { + this.config = config; + } + + public void runSampling() { + System.out.println("Running Sampling... "); + + try (Connection connection = createConnection(config)) { + try (Statement statement = connection.createStatement()) { + boolean hasResults = statement.execute(config.getSamplingQuery()); + + if (!hasResults) { + System.out.println("Nothing sampled"); + return; + } + + ResultSet rs = statement.getResultSet(); + while (rs.next()) { + String value = rs.getString(1); + sampledValueList.add(value); + } + + System.out.printf("Finished sampling %s records%n", sampledValueList.size()); + } catch (SQLException e) { + //noinspection CallToPrintStackTrace + e.printStackTrace(); + } + + } catch (SQLException e) { + //noinspection CallToPrintStackTrace + e.printStackTrace(); + } + } + + private Connection createConnection(Config config) throws SQLException { + String connectionUrl = createConnectionURL(config); + Properties properties = createConnectionProperties(); + return DriverManager.getConnection(connectionUrl, properties); + } + + private String createConnectionURL(Config config) { + if (config.isIsEmulator()) { + return String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s?autoConfigEmulator=true", + config.getProject(), config.getInstance(), config.getDatabase()); + } else { + return String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + config.getProject(), config.getInstance(), config.getDatabase()); + } + } + + private Properties createConnectionProperties() { + if (System.getProperty("spanner.host") != null) { + Properties properties = new Properties(); + properties.setProperty("endpoint", System.getProperty("spanner.host")); + return properties; + } + return DEFAULT_PROPERTIES; + } + + public void run() { + if (config.getBatchSize() > 0) { + int val = (int) Math.ceil((double) config.getIterations() / config.getBatchSize()); + measures = new float[val]; + } else { + measures = new float[config.getIterations()]; + } + + try (Connection connection = createConnection(config)) { + + // determine database dialect to set right tagging syntax + boolean isGoogleSQL = + connection + .unwrap(CloudSpannerJdbcConnection.class) + .getDialect() + .equals(Dialect.GOOGLE_STANDARD_SQL); + String tagPrefix = isGoogleSQL ? "" : "SPANNER."; + + connection.setAutoCommit(false); + + // if there is DML switch to r/w transaction mode and apply transaction tagging. + // Otherwise set to read-only mode. + if (config.getQuery().contains("INSERT") + || config.getQuery().contains("UPDATE") + || config.getQuery().contains("DELETE")) { + // read-write + connection.createStatement().execute("SET TRANSACTION READ WRITE"); + connection + .createStatement() + .execute(String.format("SET %sTRANSACTION_TAG = '%s'", tagPrefix, config.DEFAULT_TAG)); + + } else { + // read-only + // connection.createStatement().execute("SET TRANSACTION READ ONLY"); + connection.setAutoCommit(true); + } + + PreparedStatement statement = connection.prepareStatement(config.getQuery()); + int batchCounter = config.getBatchSize(); + int batchRound = 0; + + for (int i = 0; i < config.getIterations(); i++) { + if (config.getBatchSize() == 0) { + // single statements + try { + if (config.getQueryParams() != null) { + parametrizeStatement(statement, config.getQueryParams()); + } + connection + .createStatement() + .execute(String.format("SET %sSTATEMENT_TAG='%s'", tagPrefix, config.DEFAULT_TAG)); + + long start = System.nanoTime(); + boolean hasResults = statement.execute(); + if (!connection.getAutoCommit()) { + connection.commit(); + } + long stop = System.nanoTime() - start; + + if (hasResults) { + statement.getResultSet().close(); + } + + measures[i] = (float) stop / 1000000; + progress++; + } catch (Exception e) { + if (e.getMessage().contains("ALREADY_EXISTS:")) { + System.out.println("duplicate key - retry"); + i--; + } else { + throw e; + } + } + } else if (config.getQuery().contains("INSERT") + || config.getQuery().contains("UPDATE") + || config.getQuery().contains("DELETE")) { + // batching + try { + if (config.getQueryParams() != null) { + parametrizeStatement(statement, config.getQueryParams()); + } + + statement.addBatch(); + + if (batchCounter == 0 || i == config.getIterations() - 1) { + connection + .createStatement() + .execute( + String.format("SET %sSTATEMENT_TAG='%s'", tagPrefix, config.DEFAULT_TAG)); + + long start = System.nanoTime(); + statement.executeBatch(); + if (!connection.getAutoCommit()) { + connection.commit(); + } + long stop = System.nanoTime() - start; + + batchCounter = config.getBatchSize(); + + measures[batchRound] = (float) stop / 1000000; + batchRound++; + } + + progress++; + batchCounter--; + } catch (Exception e) { + if (e.getMessage().contains("ALREADY_EXISTS:")) { + System.out.println("duplicate key - retry"); + i--; + } else { + throw e; + } + } + } else { + System.out.println( + "Batching is only allowed for DML. Set batchSize=0 to disable batching."); + System.exit(1); + } + } + } catch (SQLException e) { + //noinspection CallToPrintStackTrace + e.printStackTrace(); + } + } + + public static float[] appendFloatArray(float[] originalArray, float[] elementsToAppend) { + int originalLength = originalArray.length; + int elementsLength = elementsToAppend.length; + + float[] resultArray = new float[originalLength + elementsLength]; + System.arraycopy(originalArray, 0, resultArray, 0, originalLength); + System.arraycopy(elementsToAppend, 0, resultArray, originalLength, elementsLength); + + return resultArray; + } + + private void parametrizeStatement(PreparedStatement statement, List paramList) + throws SQLException { + for (QueryParam param : paramList) { + if (param.getValue().contains("#i")) { + // integer plus integer with custom range + int value = replaceInt(param.getValue()); + statement.setInt(param.getOrder(), value); + } else if (param.getValue().contains("#d")) { + // double + Double value = replaceDouble(param.getValue()); + statement.setDouble(param.getOrder(), value); + } else if (param.getValue().contains("#s")) { + // String + String value = replaceString(param.getValue()); + statement.setString(param.getOrder(), value); + } else if (param.getValue().contains("#ps")) { + // Sampled Query - String + String value = replaceSampleQueryString(param.getValue()); + statement.setString(param.getOrder(), value); + } else if (param.getValue().contains("#pi")) { + // Sampled Query - Integer + Long value = replaceSampleQueryInt(param.getValue()); + statement.setLong(param.getOrder(), value); + } + } + } + + private int replaceInt(String value) { + Faker f = new Faker(); + // integer with min, max + String pattern = "#i\\((\\d+),(\\d+)\\)#"; + Pattern regexPattern = Pattern.compile(pattern); + Matcher matcher = regexPattern.matcher(value); + + if (matcher.find()) { + int min = Integer.parseInt(matcher.group(1)); + int max = Integer.parseInt(matcher.group(2)); + + return f.number().numberBetween(min, max); + } + + return Integer.parseInt( + value.replaceFirst("#i", String.valueOf(new SecureRandom().nextInt(Integer.MAX_VALUE)))); + } + + private Double replaceDouble(String value) { + Faker f = new Faker(); + + return Double.valueOf( + value.replaceFirst("#d", String.valueOf(f.number().randomDouble(2, 0, 999999999)))); + } + + private String replaceString(String value) { + return value.replaceFirst("#s", UUID.randomUUID().toString()); + } + + private String replaceSampleQueryString(String value) { + int randomIndex = new Random().nextInt(sampledValueList.size()); + return value.replaceFirst("#ps", sampledValueList.get(randomIndex)); + } + + private Long replaceSampleQueryInt(String value) { + int randomIndex = new Random().nextInt(sampledValueList.size()); + + return Long.parseLong(value.replaceFirst("#pi", sampledValueList.get(randomIndex))); + } + + public int getProgress() { + return progress; + } + + public float[] getMeasures() { + return measures; + } +} diff --git a/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/Config.java b/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/Config.java new file mode 100644 index 000000000..b869be386 --- /dev/null +++ b/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/Config.java @@ -0,0 +1,145 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf.config; + +import java.util.List; +import java.util.Random; + +public class Config { + public static String DEFAULT_TAG = "perftest_" + (new Random()).nextInt(300); + + private String project; + private String instance; + private String database; + private int threads; + private int iterations; + private String query; + private String samplingQuery; + private boolean writeMetricToFile; + private int batchSize; + private boolean isEmulator; + private List queryParams; + + public String paramsToString() { + StringBuilder retVal = new StringBuilder(); + + if (queryParams != null) { + + for (QueryParam param : queryParams) { + retVal.append(String.format("%s:%s ", param.getOrder(), param.getValue())); + } + } + + return retVal.toString(); + } + + public int getBatchSize() { + return this.batchSize; + } + + public void setBatchSize(int batchSize) { + this.batchSize = batchSize; + } + + public String getProject() { + return project; + } + + public void setProject(String project) { + this.project = project; + } + + public String getInstance() { + return instance; + } + + public void setInstance(String instance) { + this.instance = instance; + } + + public String getDatabase() { + return database; + } + + public void setDatabase(String database) { + this.database = database; + } + + public int getThreads() { + return threads; + } + + public void setThreads(int threads) { + this.threads = threads; + } + + public int getIterations() { + return iterations; + } + + public void setIterations(int iterations) { + this.iterations = iterations; + } + + public String getQuery() { + return query; + } + + public void setQuery(String query) { + this.query = query; + } + + public boolean isWriteMetricToFile() { + return writeMetricToFile; + } + + public void setWriteMetricToFile(boolean writeMetricToFile) { + this.writeMetricToFile = writeMetricToFile; + } + + public List getQueryParams() { + return queryParams; + } + + public void setQueryParams(List queryParams) { + this.queryParams = queryParams; + } + + public String getSamplingQuery() { + return this.samplingQuery; + } + + public void setSamplingQuery(String samplingQuery) { + this.samplingQuery = samplingQuery; + } + + public boolean getWriteMetricToFile() { + return this.writeMetricToFile; + } + + public boolean isIsEmulator() { + return this.isEmulator; + } + + public boolean getIsEmulator() { + return this.isEmulator; + } + + public void setIsEmulator(boolean isEmulator) { + this.isEmulator = isEmulator; + } +} diff --git a/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/ConfigParser.java b/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/ConfigParser.java new file mode 100644 index 000000000..8f056d114 --- /dev/null +++ b/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/ConfigParser.java @@ -0,0 +1,30 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.IOException; + +public class ConfigParser { + + public static Config parseConfigFile(String configFile) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + + return mapper.readValue(new File(configFile), Config.class); + } +} diff --git a/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/QueryParam.java b/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/QueryParam.java new file mode 100644 index 000000000..52807eb49 --- /dev/null +++ b/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/QueryParam.java @@ -0,0 +1,38 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf.config; + +public class QueryParam { + private int order; + private String value; + + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/AppTest.java b/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/AppTest.java new file mode 100644 index 000000000..c147ebaa9 --- /dev/null +++ b/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/AppTest.java @@ -0,0 +1,174 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.jdbc.quickperf; + +import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.google.cloud.spanner.connection.SpannerPool; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; +import javax.annotation.Nonnull; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.boot.SpringApplication; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; + +public class AppTest { + + private static final String TEST_FILE = "src/test/resources/testfile.json"; + + private static GenericContainer emulator; + + private static final String projectId = "test"; + private static final String instanceId = "test"; + private static final String databaseId = "quickperftest"; + + @BeforeClass + public static void setup() throws Exception { + System.out.println("Starting Emulator"); + emulator = + new GenericContainer<>( + DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator:latest")) + .withExposedPorts(9010) + .waitingFor(Wait.forListeningPort()); + + emulator.start(); + System.out.println("Finished starting Emulator"); + + List ddlList = + Arrays.asList( + "CREATE TABLE GroupMgmt (" + + "group_id INT64," + + "grpname STRING(MAX)," + + ") PRIMARY KEY(group_id)", + "CREATE TABLE Users (" + + "user_id INT64," + + "name STRING(MAX)," + + ") PRIMARY KEY(user_id)", + "CREATE TABLE membership (" + + "user_id INT64," + + "group_id INT64," + + "enrolled TIMESTAMP NOT NULL OPTIONS (" + + " allow_commit_timestamp = true" + + ")," + + ") PRIMARY KEY(user_id, group_id)"); + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + for (String ddl : ddlList) { + statement.addBatch(ddl); + } + statement.executeBatch(); + } + // create test file + ProjectConfig projectConfig = createProjectConfig(); + + // Write the JSON to a file + ObjectMapper mapper = new ObjectMapper(); + mapper.enable(SerializationFeature.INDENT_OUTPUT); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + + File file = new File(TEST_FILE); + mapper.writeValue(file, projectConfig); + } + + @Nonnull + private static ProjectConfig createProjectConfig() { + ProjectConfig projectConfig = new ProjectConfig(); + projectConfig.setProject(projectId); + projectConfig.setInstance(instanceId); + projectConfig.setDatabase(databaseId); + projectConfig.setThreads(1); + projectConfig.setIterations(1000); + projectConfig.setQuery("INSERT INTO Users (user_id, name) VALUES(?,?)"); + projectConfig.setWriteMetricToFile(false); + projectConfig.setIsEmulator(true); + + QueryParam param1 = new QueryParam(1, "#i"); + QueryParam param2 = new QueryParam(2, "#s"); + projectConfig.setQueryParams(Arrays.asList(param1, param2)); + return projectConfig; + } + + @AfterClass + public static void cleanup() throws IOException { + // Close all Spanner connections. + SpannerPool.closeSpannerPool(); + + // Write an empty test file + Path path = Paths.get(TEST_FILE); + Files.newBufferedWriter(path, TRUNCATE_EXISTING).close(); + + // Stop the emulator. + emulator.stop(); + } + + private static Connection createConnection() throws SQLException { + String url = + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s?autoConfigEmulator=true", + projectId, instanceId, databaseId); + Properties properties = new Properties(); + properties.put("endpoint", "localhost:" + emulator.getMappedPort(9010)); + return DriverManager.getConnection(url, properties); + } + + @Test + public void testRunApplication() throws Exception { + + System.setProperty("spanner.emulator", "true"); + System.setProperty("spanner.host", "localhost:" + emulator.getMappedPort(9010)); + SpringApplication.run(AppTest.class).close(); + + String[] userConfig = {"-c" + TEST_FILE}; + QuickPerf.main(userConfig); + + try (Connection connection = createConnection()) { + testQuery(connection, "SELECT count(*) FROM Users", 1000); + } + } + + private void testQuery(Connection connection, String query, int expected) throws SQLException { + try (Statement statement = connection.createStatement()) { + boolean hasResults = statement.execute(query); + assertTrue(hasResults); + + ResultSet rs = statement.getResultSet(); + while (rs.next()) { + int value = rs.getInt(1); + assertEquals(expected, value); + } + } + } +} diff --git a/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/ProjectConfig.java b/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/ProjectConfig.java new file mode 100644 index 000000000..372d100fd --- /dev/null +++ b/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/ProjectConfig.java @@ -0,0 +1,113 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf; + +import java.util.List; + +public class ProjectConfig { + private String project; + private String instance; + private String database; + private int threads; + private int iterations; + private String query; + private boolean writeMetricToFile; + private boolean isEmulator; + private List queryParams; + + // Getters and setters + + public String getProject() { + return project; + } + + public void setProject(String project) { + this.project = project; + } + + public String getInstance() { + return instance; + } + + public void setInstance(String instance) { + this.instance = instance; + } + + public String getDatabase() { + return database; + } + + public void setDatabase(String database) { + this.database = database; + } + + public int getThreads() { + return threads; + } + + public void setThreads(int threads) { + this.threads = threads; + } + + public int getIterations() { + return iterations; + } + + public void setIterations(int iterations) { + this.iterations = iterations; + } + + public String getQuery() { + return query; + } + + public void setQuery(String query) { + this.query = query; + } + + public boolean isWriteMetricToFile() { + return writeMetricToFile; + } + + public void setWriteMetricToFile(boolean writeMetricToFile) { + this.writeMetricToFile = writeMetricToFile; + } + + public List getQueryParams() { + return queryParams; + } + + public void setQueryParams(List queryParams) { + this.queryParams = queryParams; + } + + public boolean getWriteMetricToFile() { + return this.writeMetricToFile; + } + + public boolean isIsEmulator() { + return this.isEmulator; + } + + public boolean getIsEmulator() { + return this.isEmulator; + } + + public void setIsEmulator(boolean isEmulator) { + this.isEmulator = isEmulator; + } +} diff --git a/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/QueryParam.java b/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/QueryParam.java new file mode 100644 index 000000000..dcc0d85d4 --- /dev/null +++ b/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/QueryParam.java @@ -0,0 +1,45 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf; + +public class QueryParam { + private int order; + private String value; + + public QueryParam(int order, String value) { + this.order = order; + this.value = value; + } + + // Getters and setters + + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/samples/quickperf/src/test/resources/testfile.json b/samples/quickperf/src/test/resources/testfile.json new file mode 100644 index 000000000..e69de29bb From b8dadbb0812f38302544e3399810d0fa85060b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 20 Aug 2024 14:51:00 +0200 Subject: [PATCH 12/32] test: add a test for using the single-jar-with-dependencies (#1692) * test: add a test for using the single-jar-with-dependencies The single-jar-with-dependencies is prone to dependency issues, due to the fact that the build can only place one version of each file in the jar, if multiple dependencies define the same file. This change adds a test for using the single-jar with a very simple test application. Updates #1687 * fix: make the test work on the emulator * fix: only add slashes if host is actually set * test: add test for shaded jar --- pom.xml | 26 ++++ .../jdbc/SingleJarTestApplication.java | 55 ++++++++ .../spanner/jdbc/it/ITSingleJarTest.java | 126 ++++++++++++++++++ 3 files changed, 207 insertions(+) create mode 100644 src/test/java/com/google/cloud/spanner/jdbc/SingleJarTestApplication.java create mode 100644 src/test/java/com/google/cloud/spanner/jdbc/it/ITSingleJarTest.java diff --git a/pom.xml b/pom.xml index 97c020916..fc46b2952 100644 --- a/pom.xml +++ b/pom.xml @@ -426,6 +426,32 @@ + + + alt_build_dir + + + alt.build.dir + + + + ${alt.build.dir} + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + + ${alt.build.dir}/single.jar + + + + + + + diff --git a/src/test/java/com/google/cloud/spanner/jdbc/SingleJarTestApplication.java b/src/test/java/com/google/cloud/spanner/jdbc/SingleJarTestApplication.java new file mode 100644 index 000000000..e9cfba1b2 --- /dev/null +++ b/src/test/java/com/google/cloud/spanner/jdbc/SingleJarTestApplication.java @@ -0,0 +1,55 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; + +/** + * Simple Java application that is used to verify the working of the single-jar-with-dependencies. + */ +public class SingleJarTestApplication { + + public static void main(String[] args) throws Exception { + if (args.length != 3) { + throw new IllegalArgumentException("expected 3 arguments"); + } + String project = args[0]; + String instance = args[1]; + String database = args[2]; + String extraOptions = ""; + String host = ""; + if (System.getenv("SPANNER_EMULATOR_HOST") != null) { + extraOptions = "?autoConfigEmulator=true"; + host = "//" + System.getenv("SPANNER_EMULATOR_HOST"); + } + + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:%s/projects/%s/instances/%s/databases/%s%s", + host, project, instance, database, extraOptions))) { + try (ResultSet resultSet = + connection.createStatement().executeQuery("select 'Hello World from Real Spanner!'")) { + while (resultSet.next()) { + System.out.println(resultSet.getString(1)); + } + } + } + } +} diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITSingleJarTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITSingleJarTest.java new file mode 100644 index 000000000..9ae8f6003 --- /dev/null +++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITSingleJarTest.java @@ -0,0 +1,126 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.junit.Assert.assertEquals; + +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.ParallelIntegrationTest; +import com.google.common.collect.ImmutableList; +import com.google.common.io.CharStreams; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Paths; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests that the following works: + * + *
    + *
  1. Build a single-jar-with-dependencies + *
  2. Compile a simple Java application consisting of a single file and no dependencies to a + * class file + *
  3. Run the simple Java application with only itself + the single-jar-with-dependencies on the + * class path + *
+ */ +@Category(ParallelIntegrationTest.class) +@RunWith(JUnit4.class) +public class ITSingleJarTest extends ITAbstractJdbcTest { + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); + + private Database database; + + @Before + public void setup() { + database = + env.getOrCreateDatabase( + getDialect(), + ImmutableList.of("create table test (id int64, value string(max)) primary key (id)")); + } + + @Test + public void testUseSingleJar() throws Exception { + buildSingleJar(); + buildMainClass(); + runTestApplication(); + } + + @Test + public void testUseShadedJar() throws Exception { + buildShadedJar(); + buildMainClass(); + runTestApplication(); + } + + private void runTestApplication() throws Exception { + DatabaseId id = database.getId(); + ProcessBuilder builder = new ProcessBuilder(); + if (System.getenv("SPANNER_EMULATOR_HOST") != null) { + builder.environment().put("SPANNER_EMULATOR_HOST", System.getenv("SPANNER_EMULATOR_HOST")); + } + // This runs the simple test application with only the shaded jar on the classpath. + builder.command( + "java", + "-cp", + "./target/single/test/:target/single/single.jar", + "com/google/cloud/spanner/jdbc/SingleJarTestApplication", + id.getInstanceId().getProject(), + id.getInstanceId().getInstance(), + id.getDatabase()); + execute(builder); + } + + private void buildSingleJar() throws Exception { + ProcessBuilder builder = new ProcessBuilder(); + builder.command("mvn", "clean", "package", "-DskipTests", "-Dalt.build.dir=./target/single"); + execute(builder); + } + + private void buildShadedJar() throws Exception { + ProcessBuilder builder = new ProcessBuilder(); + builder.command( + "mvn", "clean", "-Pshade", "package", "-DskipTests", "-Dalt.build.dir=./target/single"); + execute(builder); + } + + private void buildMainClass() throws Exception { + Files.createDirectories(Paths.get("target", "single", "test")); + ProcessBuilder builder = new ProcessBuilder(); + builder.command( + "javac", + "src/test/java/com/google/cloud/spanner/jdbc/SingleJarTestApplication.java", + "-d", + "./target/single/test"); + execute(builder); + } + + private void execute(ProcessBuilder builder) throws Exception { + Process process = builder.start(); + String errors; + try (InputStreamReader reader = new InputStreamReader(process.getErrorStream())) { + errors = CharStreams.toString(reader); + } + assertEquals(errors, 0, process.waitFor()); + } +} From 80e3185258f5ce65e13de06f46787d24af3caf1c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 15:08:23 +0200 Subject: [PATCH 13/32] test(deps): update dependency junit:junit to v4.13.2 (#1711) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [junit:junit](http://junit.org) ([source](https://togithub.com/junit-team/junit4)) | `4.13.1` -> `4.13.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/junit:junit/4.13.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/junit:junit/4.13.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/junit:junit/4.13.1/4.13.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/junit:junit/4.13.1/4.13.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/quickperf/pom.xml b/samples/quickperf/pom.xml index 38750500e..2ceca71a7 100644 --- a/samples/quickperf/pom.xml +++ b/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ junit junit - 4.13.1 + 4.13.2 test From eff5df22785e55a8f0974f028678883ef404b4e6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 15:10:23 +0200 Subject: [PATCH 14/32] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.13.4.2 [security] (#1710) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.fasterxml.jackson.core:jackson-databind](https://togithub.com/FasterXML/jackson) ([source](https://togithub.com/FasterXML/jackson-databind)) | `2.13.4.1` -> `2.13.4.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.fasterxml.jackson.core:jackson-databind/2.13.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.fasterxml.jackson.core:jackson-databind/2.13.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.fasterxml.jackson.core:jackson-databind/2.13.4.1/2.13.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.fasterxml.jackson.core:jackson-databind/2.13.4.1/2.13.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | ### GitHub Vulnerability Alerts #### [CVE-2022-42003](https://nvd.nist.gov/vuln/detail/CVE-2022-42003) In FasterXML jackson-databind 2.4.0-rc1 until 2.12.7.1 and in 2.13.x before 2.13.4.2 resource exhaustion can occur because of a lack of a check in primitive value deserializers to avoid deep wrapper array nesting, when the UNWRAP_SINGLE_VALUE_ARRAYS feature is enabled. This was patched in 2.12.7.1, 2.13.4.2, and 2.14.0. Commits that introduced vulnerable code are https://togithub.com/FasterXML/jackson-databind/commit/d499f2e7bbc5ebd63af11e1f5cf1989fa323aa45, https://togithub.com/FasterXML/jackson-databind/commit/0e37a39502439ecbaa1a5b5188387c01bf7f7fa1, and https://togithub.com/FasterXML/jackson-databind/commit/7ba9ac5b87a9d6ac0d2815158ecbeb315ad4dcdc. Fix commits are https://togithub.com/FasterXML/jackson-databind/commit/cd090979b7ea78c75e4de8a4aed04f7e9fa8deea and https://togithub.com/FasterXML/jackson-databind/commit/d78d00ee7b5245b93103fef3187f70543d67ca33. --- ### Configuration 📅 **Schedule**: Branch creation - "" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/quickperf/pom.xml b/samples/quickperf/pom.xml index 2ceca71a7..031f4f26b 100644 --- a/samples/quickperf/pom.xml +++ b/samples/quickperf/pom.xml @@ -61,7 +61,7 @@ com.fasterxml.jackson.core jackson-databind - 2.13.4.1 + 2.13.4.2 From 0e44c982127b7db5fbea292d57fb58b02c5222e1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 15:28:24 +0200 Subject: [PATCH 15/32] build(deps): update dependency org.codehaus.mojo:exec-maven-plugin to v3.4.1 (#1712) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.codehaus.mojo:exec-maven-plugin](https://www.mojohaus.org/exec-maven-plugin) ([source](https://togithub.com/mojohaus/exec-maven-plugin)) | `3.1.0` -> `3.4.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.codehaus.mojo:exec-maven-plugin/3.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.codehaus.mojo:exec-maven-plugin/3.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.codehaus.mojo:exec-maven-plugin/3.1.0/3.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.codehaus.mojo:exec-maven-plugin/3.1.0/3.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
mojohaus/exec-maven-plugin (org.codehaus.mojo:exec-maven-plugin) ### [`v3.4.1`](https://togithub.com/mojohaus/exec-maven-plugin/releases/tag/3.4.1) [Compare Source](https://togithub.com/mojohaus/exec-maven-plugin/compare/3.4.0...3.4.1) #### 🐛 Bug Fixes - Environment variable Path should be used as case-insensitive ([#​442](https://togithub.com/mojohaus/exec-maven-plugin/pull/442)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - fix: NPE because declared MavenSession field hides field of superclass ([#​439](https://togithub.com/mojohaus/exec-maven-plugin/pull/439)) [@​sebthom](https://togithub.com/sebthom) #### 📦 Dependency updates - Bump org.codehaus.mojo:mojo-parent from 84 to 85 ([#​441](https://togithub.com/mojohaus/exec-maven-plugin/pull/441)) [@​dependabot](https://togithub.com/dependabot) #### 👻 Maintenance - Remove redundant spotless configuration ([#​440](https://togithub.com/mojohaus/exec-maven-plugin/pull/440)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) #### 🔧 Build - Use Maven4 enabled with GH Action ([#​443](https://togithub.com/mojohaus/exec-maven-plugin/pull/443)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Use shared release drafter GH Action ([#​444](https://togithub.com/mojohaus/exec-maven-plugin/pull/444)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) ### [`v3.4.0`](https://togithub.com/mojohaus/exec-maven-plugin/releases/tag/3.4.0) [Compare Source](https://togithub.com/mojohaus/exec-maven-plugin/compare/3.3.0...3.4.0) #### 🚀 New features and improvements - Allow `` to be specified for the exec:exec goal ([#​432](https://togithub.com/mojohaus/exec-maven-plugin/pull/432)) [@​sebthom](https://togithub.com/sebthom) #### 🐛 Bug Fixes - Do not get UPPERCASE env vars ([#​427](https://togithub.com/mojohaus/exec-maven-plugin/pull/427)) [@​wheezil](https://togithub.com/wheezil) #### 📦 Dependency updates - Bump org.codehaus.mojo:mojo-parent from 82 to 84 ([#​434](https://togithub.com/mojohaus/exec-maven-plugin/pull/434)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-xml from 3.0.0 to 3.0.1 ([#​431](https://togithub.com/mojohaus/exec-maven-plugin/pull/431)) [@​dependabot](https://togithub.com/dependabot) #### 👻 Maintenance - Remove Log4j 1.2.x from ITs ([#​437](https://togithub.com/mojohaus/exec-maven-plugin/pull/437)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) #### 🔧 Build - Use Maven 3.9.7 and 4.0.0-beta-3 ([#​433](https://togithub.com/mojohaus/exec-maven-plugin/pull/433)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) ### [`v3.3.0`](https://togithub.com/mojohaus/exec-maven-plugin/releases/tag/3.3.0) [Compare Source](https://togithub.com/mojohaus/exec-maven-plugin/compare/3.2.0...3.3.0) #### 🚀 New features and improvements - Add option to include runtime and provided ([#​61](https://togithub.com/mojohaus/exec-maven-plugin/pull/61)) [@​rehevkor5](https://togithub.com/rehevkor5) #### 📦 Dependency updates - Bump org.codehaus.mojo:mojo-parent from 80 to 82 ([#​429](https://togithub.com/mojohaus/exec-maven-plugin/pull/429)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-utils from 4.0.0 to 4.0.1 ([#​424](https://togithub.com/mojohaus/exec-maven-plugin/pull/424)) [@​dependabot](https://togithub.com/dependabot) - Bump asm.version from 9.6 to 9.7 ([#​422](https://togithub.com/mojohaus/exec-maven-plugin/pull/422)) [@​dependabot](https://togithub.com/dependabot) - Bump apache/maven-gh-actions-shared from 3 to 4 ([#​420](https://togithub.com/mojohaus/exec-maven-plugin/pull/420)) [@​dependabot](https://togithub.com/dependabot) ### [`v3.2.0`](https://togithub.com/mojohaus/exec-maven-plugin/releases/tag/3.2.0) [Compare Source](https://togithub.com/mojohaus/exec-maven-plugin/compare/3.1.1...3.2.0) ##### 🚀 New features and improvements - Enable to exec:java runnables and not only mains with loosely coupled injections ([#​408](https://togithub.com/mojohaus/exec-maven-plugin/pull/408)) [@​rmannibucau](https://togithub.com/rmannibucau) - Try to get rid of legacy API which can break starting with java 17 ([#​409](https://togithub.com/mojohaus/exec-maven-plugin/pull/409)) [@​rmannibucau](https://togithub.com/rmannibucau) ##### 🐛 Bug Fixes - Fix [#​401](https://togithub.com/mojohaus/exec-maven-plugin/issues/401) - Maven v4 compatibility ([#​414](https://togithub.com/mojohaus/exec-maven-plugin/pull/414)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) ##### 📦 Dependency updates - Bump org.codehaus.mojo:mojo-parent from 78 to 80 ([#​419](https://togithub.com/mojohaus/exec-maven-plugin/pull/419)) [@​dependabot](https://togithub.com/dependabot) - Bump commons-io:commons-io from 1.1 to 2.7 in /src/it/projects/setup-parent ([#​416](https://togithub.com/mojohaus/exec-maven-plugin/pull/416)) [@​dependabot](https://togithub.com/dependabot) - Bump org.apache.commons:commons-exec from 1.3 to 1.4.0 ([#​405](https://togithub.com/mojohaus/exec-maven-plugin/pull/405)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.mojo:mojo-parent from 77 to 78 ([#​406](https://togithub.com/mojohaus/exec-maven-plugin/pull/406)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-component-metadata from 2.1.1 to 2.2.0 ([#​403](https://togithub.com/mojohaus/exec-maven-plugin/pull/403)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-component-annotations from 2.1.1 to 2.2.0 ([#​404](https://togithub.com/mojohaus/exec-maven-plugin/pull/404)) [@​dependabot](https://togithub.com/dependabot) ##### 👻 Maintenance - ITs improvement ([#​415](https://togithub.com/mojohaus/exec-maven-plugin/pull/415)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Fix documentation formatting, add menu items for new examples ([#​412](https://togithub.com/mojohaus/exec-maven-plugin/pull/412)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Execute mexec-137 also on unix family ([#​413](https://togithub.com/mojohaus/exec-maven-plugin/pull/413)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Remove unused test ([#​410](https://togithub.com/mojohaus/exec-maven-plugin/pull/410)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) ##### 🔧 Build - Bump release-drafter/release-drafter from 5 to 6 ([#​417](https://togithub.com/mojohaus/exec-maven-plugin/pull/417)) [@​dependabot](https://togithub.com/dependabot) ### [`v3.1.1`](https://togithub.com/mojohaus/exec-maven-plugin/releases/tag/3.1.1) ##### 🚀 New features and improvements - Remove unused killAfter options ([#​394](https://togithub.com/mojohaus/exec-maven-plugin/pull/394)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - \[[#​391](https://togithub.com/mojohaus/exec-maven-plugin/issues/391)] Cope with Thread::stop being unavailable in JDK 20+ ([#​393](https://togithub.com/mojohaus/exec-maven-plugin/pull/393)) [@​kriegaex](https://togithub.com/kriegaex) - Only prefix program output with thread name when running with multiple threads ([#​157](https://togithub.com/mojohaus/exec-maven-plugin/pull/157)) [@​hankolerd](https://togithub.com/hankolerd) - \[[#​389](https://togithub.com/mojohaus/exec-maven-plugin/issues/389)] Add option 'blockSystemExit' to 'java' mojo ([#​390](https://togithub.com/mojohaus/exec-maven-plugin/pull/390)) [@​kriegaex](https://togithub.com/kriegaex) - Require Maven 3.6.3+ ([#​385](https://togithub.com/mojohaus/exec-maven-plugin/pull/385)) [@​slachiewicz](https://togithub.com/slachiewicz) - Ensure maven.properties can be forwarded to system properties for exec:java ([#​346](https://togithub.com/mojohaus/exec-maven-plugin/pull/346)) [@​rmannibucau](https://togithub.com/rmannibucau) ##### 🐛 Bug Fixes - Fix [#​158](https://togithub.com/mojohaus/exec-maven-plugin/issues/158) - Fix non ascii character handling ([#​372](https://togithub.com/mojohaus/exec-maven-plugin/pull/372)) [@​jebeaudet](https://togithub.com/jebeaudet) - \[[#​323](https://togithub.com/mojohaus/exec-maven-plugin/issues/323)] exec arguments missing ([#​324](https://togithub.com/mojohaus/exec-maven-plugin/pull/324)) [@​bmarwell](https://togithub.com/bmarwell) ##### 📦 Dependency updates - Bump org.codehaus.plexus:plexus-utils from 3.0.16 to 3.0.24 in /src/it/projects/java_module-module+mainclass ([#​382](https://togithub.com/mojohaus/exec-maven-plugin/pull/382)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-utils from 3.0.16 to 3.0.24 in /src/it/projects/java_module-mainclass ([#​380](https://togithub.com/mojohaus/exec-maven-plugin/pull/380)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-utils from 3.0.16 to 3.0.24 in /src/it/projects/java_module-export ([#​379](https://togithub.com/mojohaus/exec-maven-plugin/pull/379)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-utils from 3.0.16 to 3.0.24 in /src/it/projects/longModulepath with spaces ([#​383](https://togithub.com/mojohaus/exec-maven-plugin/pull/383)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-utils from 3.0.16 to 3.0.24 in /src/it/projects/jigsaw ([#​381](https://togithub.com/mojohaus/exec-maven-plugin/pull/381)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-utils from 3.0.16 to 3.0.24 in /src/it/mrm/java_module ([#​378](https://togithub.com/mojohaus/exec-maven-plugin/pull/378)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.mojo:mojo-parent from 76 to 77 ([#​384](https://togithub.com/mojohaus/exec-maven-plugin/pull/384)) [@​dependabot](https://togithub.com/dependabot) - Require Maven 3.6.3+ ([#​385](https://togithub.com/mojohaus/exec-maven-plugin/pull/385)) [@​slachiewicz](https://togithub.com/slachiewicz) - Bump plexus-utils from 3.5.1 to 4.0.0 ([#​368](https://togithub.com/mojohaus/exec-maven-plugin/pull/368)) [@​dependabot](https://togithub.com/dependabot) - Bump parent from 70 to 76 ([#​375](https://togithub.com/mojohaus/exec-maven-plugin/pull/375)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Bump groovy from 3.0.17 to 3.0.18 ([#​371](https://togithub.com/mojohaus/exec-maven-plugin/pull/371)) [@​dependabot](https://togithub.com/dependabot) - Bump groovy from 3.0.16 to 3.0.17 ([#​365](https://togithub.com/mojohaus/exec-maven-plugin/pull/365)) [@​dependabot](https://togithub.com/dependabot) - Bump groovy from 3.0.15 to 3.0.16 ([#​363](https://togithub.com/mojohaus/exec-maven-plugin/pull/363)) [@​dependabot](https://togithub.com/dependabot) - Bump plexus-utils from 3.5.0 to 3.5.1 ([#​362](https://togithub.com/mojohaus/exec-maven-plugin/pull/362)) [@​dependabot](https://togithub.com/dependabot) - Bump groovy from 3.0.14 to 3.0.15 ([#​361](https://togithub.com/mojohaus/exec-maven-plugin/pull/361)) [@​dependabot](https://togithub.com/dependabot) - Bump groovy from 3.0.13 to 3.0.14 ([#​354](https://togithub.com/mojohaus/exec-maven-plugin/pull/354)) [@​dependabot](https://togithub.com/dependabot) - Bump mockito-core from 4.9.0 to 4.11.0 ([#​355](https://togithub.com/mojohaus/exec-maven-plugin/pull/355)) [@​dependabot](https://togithub.com/dependabot) - Bump mockito-core from 4.8.1 to 4.9.0 ([#​347](https://togithub.com/mojohaus/exec-maven-plugin/pull/347)) [@​dependabot](https://togithub.com/dependabot) - Bump groovy from 3.0.12 to 3.0.13 ([#​340](https://togithub.com/mojohaus/exec-maven-plugin/pull/340)) [@​dependabot](https://togithub.com/dependabot) - Bump plexus-utils from 3.4.2 to 3.5.0 ([#​343](https://togithub.com/mojohaus/exec-maven-plugin/pull/343)) [@​dependabot](https://togithub.com/dependabot) - Bump mockito-core from 4.7.0 to 4.8.1 ([#​344](https://togithub.com/mojohaus/exec-maven-plugin/pull/344)) [@​dependabot](https://togithub.com/dependabot) - Bump mojo-parent from 69 to 70 ([#​329](https://togithub.com/mojohaus/exec-maven-plugin/pull/329)) [@​dependabot](https://togithub.com/dependabot) - Bump mockito-core from 4.6.1 to 4.7.0 ([#​330](https://togithub.com/mojohaus/exec-maven-plugin/pull/330)) [@​dependabot](https://togithub.com/dependabot) - Bump groovy from 3.0.11 to 3.0.12 ([#​325](https://togithub.com/mojohaus/exec-maven-plugin/pull/325)) [@​dependabot](https://togithub.com/dependabot) ##### 👻 Maintenance - Code cleanups - use newer JDK features ([#​396](https://togithub.com/mojohaus/exec-maven-plugin/pull/396)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Enable spotless for code formatting ([#​395](https://togithub.com/mojohaus/exec-maven-plugin/pull/395)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Require Maven 3.6.3+ ([#​385](https://togithub.com/mojohaus/exec-maven-plugin/pull/385)) [@​slachiewicz](https://togithub.com/slachiewicz) - ITs cleanups ([#​374](https://togithub.com/mojohaus/exec-maven-plugin/pull/374)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Use Resolver Api for dependency resolving ([#​349](https://togithub.com/mojohaus/exec-maven-plugin/pull/349)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) ##### 🔧 Build - Workaround for concurrent access to local repository on Windows by ITs ([#​392](https://togithub.com/mojohaus/exec-maven-plugin/pull/392)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Use Maven 3.9.4, 3.8.8 in GitHub build ([#​377](https://togithub.com/mojohaus/exec-maven-plugin/pull/377)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski)
--- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/quickperf/pom.xml b/samples/quickperf/pom.xml index 031f4f26b..cf419f960 100644 --- a/samples/quickperf/pom.xml +++ b/samples/quickperf/pom.xml @@ -89,7 +89,7 @@ org.codehaus.mojo exec-maven-plugin - 3.1.0 + 3.4.1 com.google.cloud.jdbc.quickperf.QuickPerf From 80b4ec602bfa6d543ea0fb110ea06c17130f0434 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 15:30:24 +0200 Subject: [PATCH 16/32] chore(deps): update dependency com.google.cloud:libraries-bom to v26.44.0 (#1713) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:libraries-bom](https://cloud.google.com/java/docs/bom) ([source](https://togithub.com/googleapis/java-cloud-bom)) | `26.43.0` -> `26.44.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:libraries-bom/26.44.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:libraries-bom/26.44.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:libraries-bom/26.43.0/26.44.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:libraries-bom/26.43.0/26.44.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-cloud-bom (com.google.cloud:libraries-bom) ### [`v26.44.0`](https://togithub.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26440-2024-08-08) [Compare Source](https://togithub.com/googleapis/java-cloud-bom/compare/v26.43.0...v26.44.0) ##### Dependencies - update dependency com.google.cloud:first-party-dependencies to v3.33.0 ([#​6687](https://togithub.com/googleapis/java-cloud-bom/issues/6687)) ([d93c7c1](https://togithub.com/googleapis/java-cloud-bom/commit/d93c7c1e5c8cfea5f0bb3b570282af1d17ac9992)) - update dependency com.google.cloud:gapic-libraries-bom to v1.41.0 ([#​6689](https://togithub.com/googleapis/java-cloud-bom/issues/6689)) ([e5afcc8](https://togithub.com/googleapis/java-cloud-bom/commit/e5afcc8a5afd362f7cdb6d19f446c99db7832fb9)) - update dependency com.google.cloud:google-cloud-bigquery to v2.42.0 ([#​6688](https://togithub.com/googleapis/java-cloud-bom/issues/6688)) ([58ed9ce](https://togithub.com/googleapis/java-cloud-bom/commit/58ed9cef18361489756bafdf9b6159077f498608)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.8.0 ([#​6685](https://togithub.com/googleapis/java-cloud-bom/issues/6685)) ([c6968cb](https://togithub.com/googleapis/java-cloud-bom/commit/c6968cb3315c37d21539daa5001c6b297f600ba4)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.41.0 ([#​6686](https://togithub.com/googleapis/java-cloud-bom/issues/6686)) ([256f1b0](https://togithub.com/googleapis/java-cloud-bom/commit/256f1b0e97dc1c28453fd0c302e5ecc6958a5a55)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.42.0 ([9e666cf](https://togithub.com/googleapis/java-cloud-bom/commit/9e666cf1efb8ba694a945814060df0ccdb26f363)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.21.0 ([#​6697](https://togithub.com/googleapis/java-cloud-bom/issues/6697)) ([046ad04](https://togithub.com/googleapis/java-cloud-bom/commit/046ad04177bca0cfd2aecce6bc1170617939bfbb)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.21.1 ([9e666cf](https://togithub.com/googleapis/java-cloud-bom/commit/9e666cf1efb8ba694a945814060df0ccdb26f363)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.24.2 ([#​6681](https://togithub.com/googleapis/java-cloud-bom/issues/6681)) ([91673de](https://togithub.com/googleapis/java-cloud-bom/commit/91673debfaec89f2c6b49249966f9ed772acc3bd)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.24.3 ([9e666cf](https://togithub.com/googleapis/java-cloud-bom/commit/9e666cf1efb8ba694a945814060df0ccdb26f363)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.20.0 ([#​6694](https://togithub.com/googleapis/java-cloud-bom/issues/6694)) ([780736c](https://togithub.com/googleapis/java-cloud-bom/commit/780736c2b35f8f657b686bd1f4e61946835736ec)) - update dependency com.google.cloud:google-cloud-logging-logback to v0.131.10-alpha ([#​6695](https://togithub.com/googleapis/java-cloud-bom/issues/6695)) ([6ecff38](https://togithub.com/googleapis/java-cloud-bom/commit/6ecff38a39d0bbc2516ffcba64507afc9b4ac027)) - update dependency com.google.cloud:google-cloud-nio to v0.127.21 ([4534296](https://togithub.com/googleapis/java-cloud-bom/commit/4534296641ba101fae87219bbabc7efdd86f3fbc)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.132.0 ([#​6693](https://togithub.com/googleapis/java-cloud-bom/issues/6693)) ([b0483b9](https://togithub.com/googleapis/java-cloud-bom/commit/b0483b95065ae38522547c736a753c751279f014)) - update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.14.0 ([#​6696](https://togithub.com/googleapis/java-cloud-bom/issues/6696)) ([ad905cc](https://togithub.com/googleapis/java-cloud-bom/commit/ad905ccb7d41bd64cc519bd855dabb0523bd7fa8)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.72.0 ([9e666cf](https://togithub.com/googleapis/java-cloud-bom/commit/9e666cf1efb8ba694a945814060df0ccdb26f363)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.20.2 ([4534296](https://togithub.com/googleapis/java-cloud-bom/commit/4534296641ba101fae87219bbabc7efdd86f3fbc)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.41.0 ([#​6690](https://togithub.com/googleapis/java-cloud-bom/issues/6690)) ([43aef8e](https://togithub.com/googleapis/java-cloud-bom/commit/43aef8e9bf082ce98afd0c34163b016b8f315ee0)) - update dependency com.google.googlejavaformat:google-java-format to v1.23.0 ([#​6692](https://togithub.com/googleapis/java-cloud-bom/issues/6692)) ([b403c50](https://togithub.com/googleapis/java-cloud-bom/commit/b403c5040d47ba87dd32162e3be71ded6fdd127c))
--- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/quickperf/pom.xml b/samples/quickperf/pom.xml index cf419f960..e42e323ef 100644 --- a/samples/quickperf/pom.xml +++ b/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.43.0 + 26.44.0 pom import From dafb77d3c0def0ea99051bc31db98c72e874fcd2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 13:34:23 +0000 Subject: [PATCH 17/32] build(deps): bump com.fasterxml.jackson.core:jackson-databind from 2.13.4.1 to 2.13.4.2 in /samples/quickperf (#1709) Bumps [com.fasterxml.jackson.core:jackson-databind](https://togithub.com/FasterXML/jackson) from 2.13.4.1 to 2.13.4.2.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.fasterxml.jackson.core:jackson-databind&package-manager=maven&previous-version=2.13.4.1&new-version=2.13.4.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://togithub.com/googleapis/java-spanner-jdbc/network/alerts).
From 816f786d4a383ffd1677c889775b9c6d6b5b07c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 20 Aug 2024 15:49:57 +0200 Subject: [PATCH 18/32] test: add tests for named schemas (#1450) * chore: modify metadata queries to support named schemas Modify metadata queries so these are able to handle multiple named schemas in the same database, potentially with tables and indexes with the same names in different schemas. * test: add tests for named schemas Adds integration tests for metadata queries using multiple named schemas and tables and indexes with the same names in different schemas. --- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 802 +++++++++--------- .../jdbc/it/ITJdbcPgDatabaseMetaDataTest.java | 786 +++++++++-------- .../spanner/jdbc/it/CreateMusicTables_PG.sql | 5 + 3 files changed, 846 insertions(+), 747 deletions(-) diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 903df91db..efc3934d3 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -21,9 +21,13 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -31,7 +35,8 @@ import java.sql.Types; import java.util.Arrays; import java.util.List; -import org.junit.Before; +import java.util.stream.Collectors; +import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -53,11 +58,46 @@ public class ITJdbcDatabaseMetaDataTest extends ITAbstractJdbcTest { @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); - private Database database; - - @Before - public void setup() { - database = env.getOrCreateDatabase(getDialect(), getMusicTablesDdl(getDialect())); + private static Database database; + + @BeforeClass + public static void setup() throws Exception { + assumeFalse( + "Named schemas are not yet supported on the emulator", + EmulatorSpannerHelper.isUsingEmulator()); + + database = + env.getOrCreateDatabase( + Dialect.GOOGLE_STANDARD_SQL, getMusicTablesDdl(Dialect.GOOGLE_STANDARD_SQL)); + + // Create the same tables in an additional 'test' schema. + DatabaseAdminClient client = env.getTestHelper().getClient().getDatabaseAdminClient(); + List tables = + getMusicTablesDdl(Dialect.GOOGLE_STANDARD_SQL).stream() + .map(statement -> statement.replace("CREATE TABLE ", "CREATE TABLE test.")) + .map(statement -> statement.replace("CREATE INDEX ", "CREATE INDEX test.")) + .map( + statement -> statement.replace("CREATE UNIQUE INDEX ", "CREATE UNIQUE INDEX test.")) + .map(statement -> statement.replace("CREATE VIEW ", "CREATE VIEW test.")) + .map(statement -> statement.replace("FROM ", "FROM test.")) + .map( + statement -> + statement.replace("INTERLEAVE IN PARENT ", "INTERLEAVE IN PARENT test.")) + .map(statement -> statement.replace("INTERLEAVE IN ", "INTERLEAVE IN test.")) + .map( + statement -> statement.replace("INTERLEAVE IN test.PARENT", "INTERLEAVE IN PARENT")) + .map(statement -> statement.replace(" ON ", " ON test.")) + .map(statement -> statement.replace(" ON test.DELETE", " ON DELETE")) + .map(statement -> statement.replace(" REFERENCES ", " REFERENCES test.")) + .collect(Collectors.toList()); + tables.add(0, "create schema test"); + client + .updateDatabaseDdl( + database.getId().getInstanceId().getInstance(), + database.getId().getDatabase(), + tables, + null) + .get(); } private static final class Column { @@ -165,65 +205,65 @@ private Column( @Test public void testGetColumns() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getColumns(DEFAULT_CATALOG, DEFAULT_SCHEMA, TABLE_WITH_ALL_COLS, null)) { - int pos = 1; - for (Column col : EXPECTED_COLUMNS) { - assertTrue(rs.next()); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(TABLE_WITH_ALL_COLS, rs.getString("TABLE_NAME")); - assertEquals(col.name, rs.getString("COLUMN_NAME")); - assertEquals(col.type, rs.getInt("DATA_TYPE")); - assertEquals(col.typeName, rs.getString("TYPE_NAME")); - if (col.colSize == null) { - assertEquals(0, rs.getInt("COLUMN_SIZE")); - assertTrue(rs.wasNull()); - } else { - assertEquals(col.colSize.intValue(), rs.getInt("COLUMN_SIZE")); - } - rs.getObject("BUFFER_LENGTH"); // just assert that it exists - if (col.decimalDigits == null) { - assertEquals(0, rs.getInt("DECIMAL_DIGITS")); - assertTrue(rs.wasNull()); - } else { - assertEquals(col.decimalDigits.intValue(), rs.getInt("DECIMAL_DIGITS")); - } - if (col.radix == null) { - assertEquals(0, rs.getInt("NUM_PREC_RADIX")); - assertTrue(rs.wasNull()); - } else { - assertEquals(col.radix.intValue(), rs.getInt("NUM_PREC_RADIX")); - } - assertEquals( - col.nullable ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls, - rs.getInt("NULLABLE")); - assertNull(rs.getString("REMARKS")); - assertNull(rs.getString("COLUMN_DEF")); - assertEquals(0, rs.getInt("SQL_DATA_TYPE")); - assertEquals(0, rs.getInt("SQL_DATETIME_SUB")); - if (col.charOctetLength == null) { - assertEquals(0, rs.getInt("CHAR_OCTET_LENGTH")); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getColumns(DEFAULT_CATALOG, schema, TABLE_WITH_ALL_COLS, null)) { + int ordinalPosition = 0; + for (Column col : EXPECTED_COLUMNS) { + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("TABLE_NAME")); + assertEquals(col.name, rs.getString("COLUMN_NAME")); + assertEquals(col.type, rs.getInt("DATA_TYPE")); + assertEquals(col.typeName, rs.getString("TYPE_NAME")); + if (col.colSize == null) { + assertEquals(0, rs.getInt("COLUMN_SIZE")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.colSize.intValue(), rs.getInt("COLUMN_SIZE")); + } + rs.getObject("BUFFER_LENGTH"); // just assert that it exists + if (col.decimalDigits == null) { + assertEquals(0, rs.getInt("DECIMAL_DIGITS")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.decimalDigits.intValue(), rs.getInt("DECIMAL_DIGITS")); + } + if (col.radix == null) { + assertEquals(0, rs.getInt("NUM_PREC_RADIX")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.radix.intValue(), rs.getInt("NUM_PREC_RADIX")); + } + assertEquals( + col.nullable ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls, + rs.getInt("NULLABLE")); + assertNull(rs.getString("REMARKS")); + assertNull(rs.getString("COLUMN_DEF")); + assertEquals(0, rs.getInt("SQL_DATA_TYPE")); + assertEquals(0, rs.getInt("SQL_DATETIME_SUB")); + if (col.charOctetLength == null) { + assertEquals(0, rs.getInt("CHAR_OCTET_LENGTH")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.charOctetLength.intValue(), rs.getInt("CHAR_OCTET_LENGTH")); + } + assertEquals(++ordinalPosition, rs.getInt("ORDINAL_POSITION")); + assertEquals(col.nullable ? "YES" : "NO", rs.getString("IS_NULLABLE")); + assertNull(rs.getString("SCOPE_CATALOG")); + assertNull(rs.getString("SCOPE_SCHEMA")); + assertNull(rs.getString("SCOPE_TABLE")); + assertEquals(0, rs.getShort("SOURCE_DATA_TYPE")); assertTrue(rs.wasNull()); - } else { - assertEquals(col.charOctetLength.intValue(), rs.getInt("CHAR_OCTET_LENGTH")); + assertEquals("NO", rs.getString("IS_AUTOINCREMENT")); + assertEquals(col.computed ? "YES" : "NO", rs.getString("IS_GENERATEDCOLUMN")); + assertEquals(24, rs.getMetaData().getColumnCount()); } - assertEquals(pos, rs.getInt("ORDINAL_POSITION")); - assertEquals(col.nullable ? "YES" : "NO", rs.getString("IS_NULLABLE")); - assertNull(rs.getString("SCOPE_CATALOG")); - assertNull(rs.getString("SCOPE_SCHEMA")); - assertNull(rs.getString("SCOPE_TABLE")); - assertEquals(0, rs.getShort("SOURCE_DATA_TYPE")); - assertTrue(rs.wasNull()); - assertEquals("NO", rs.getString("IS_AUTOINCREMENT")); - assertEquals(col.computed ? "YES" : "NO", rs.getString("IS_GENERATEDCOLUMN")); - assertEquals(24, rs.getMetaData().getColumnCount()); - - pos++; + assertFalse(rs.next()); } - assertFalse(rs.next()); } } } @@ -231,181 +271,173 @@ public void testGetColumns() throws SQLException { @Test public void testGetCrossReferences() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - SINGERS_TABLE, - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - ALBUMS_TABLE)) { - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals("Singers", rs.getString("PKTABLE_NAME")); - assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals("Albums", rs.getString("FKTABLE_NAME")); - assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); - assertEquals(1, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); - assertNull(rs.getString("FK_NAME")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - } - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - ALBUMS_TABLE, - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - SONGS_TABLE)) { - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals("Albums", rs.getString("PKTABLE_NAME")); - assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals("Songs", rs.getString("FKTABLE_NAME")); - assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); - assertEquals(1, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); - assertNull(rs.getString("FK_NAME")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals("Albums", rs.getString("PKTABLE_NAME")); - assertEquals("AlbumId", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals("Songs", rs.getString("FKTABLE_NAME")); - assertEquals("AlbumId", rs.getString("FKCOLUMN_NAME")); - assertEquals(2, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); - assertNull(rs.getString("FK_NAME")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - } + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, + schema, + SINGERS_TABLE, + DEFAULT_CATALOG, + schema, + ALBUMS_TABLE)) { + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("Singers", rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("Albums", rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); + assertNull(rs.getString("FK_NAME")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + } + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, schema, ALBUMS_TABLE, DEFAULT_CATALOG, schema, SONGS_TABLE)) { + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("Albums", rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("Songs", rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); + assertNull(rs.getString("FK_NAME")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - SINGERS_TABLE, - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - CONCERTS_TABLE)) { - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals("Singers", rs.getString("PKTABLE_NAME")); - assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals("Concerts", rs.getString("FKTABLE_NAME")); - assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); - assertEquals(1, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("Fk_Concerts_Singer", rs.getString("FK_NAME")); - assertEquals("PK_Singers", rs.getString("PK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - assertFalse(rs.next()); - } + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("Albums", rs.getString("PKTABLE_NAME")); + assertEquals("AlbumId", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("Songs", rs.getString("FKTABLE_NAME")); + assertEquals("AlbumId", rs.getString("FKCOLUMN_NAME")); + assertEquals(2, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); + assertNull(rs.getString("FK_NAME")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + } - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - TABLE_WITH_ALL_COLS, - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - TABLE_WITH_REF)) { + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, + schema, + SINGERS_TABLE, + DEFAULT_CATALOG, + schema, + CONCERTS_TABLE)) { + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("Singers", rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("Concerts", rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("Fk_Concerts_Singer", rs.getString("FK_NAME")); + assertEquals("PK_Singers", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + assertFalse(rs.next()); + } - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); - assertEquals("ColFloat64", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); - assertEquals("RefFloat", rs.getString("FKCOLUMN_NAME")); - assertEquals(1, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, + schema, + TABLE_WITH_ALL_COLS, + DEFAULT_CATALOG, + schema, + TABLE_WITH_REF)) { - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); - assertEquals("ColString", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); - assertEquals("RefString", rs.getString("FKCOLUMN_NAME")); - assertEquals(2, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); + assertEquals("ColFloat64", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); + assertEquals("RefFloat", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); - assertEquals("ColDate", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); - assertEquals("RefDate", rs.getString("FKCOLUMN_NAME")); - assertEquals(3, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); + assertEquals("ColString", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); + assertEquals("RefString", rs.getString("FKCOLUMN_NAME")); + assertEquals(2, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - assertFalse(rs.next()); - } - // try getting self-references - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - ALBUMS_TABLE, - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - ALBUMS_TABLE)) { - assertFalse(rs.next()); - } - // try getting all cross-references in the database - try (ResultSet rs = - connection.getMetaData().getCrossReference(null, null, null, null, null, null)) { - for (int i = 0; i < 7; i++) { assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); + assertEquals("ColDate", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); + assertEquals("RefDate", rs.getString("FKCOLUMN_NAME")); + assertEquals(3, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + + assertFalse(rs.next()); + } + // try getting self-references + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, schema, ALBUMS_TABLE, DEFAULT_CATALOG, schema, ALBUMS_TABLE)) { + assertFalse(rs.next()); + } + // try getting all cross-references in the database + try (ResultSet rs = + connection.getMetaData().getCrossReference(null, null, null, null, null, null)) { + for (int i = 0; i < 14; i++) { + assertTrue(rs.next()); + } + assertFalse(rs.next()); } - assertFalse(rs.next()); } } } @@ -480,39 +512,39 @@ private IndexInfo( @Test public void testGetIndexInfo() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getIndexInfo(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, false, false)) { - - for (IndexInfo index : EXPECTED_INDICES) { - assertTrue(rs.next()); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(index.tableName, rs.getString("TABLE_NAME")); - assertEquals(index.nonUnique, rs.getBoolean("NON_UNIQUE")); - assertEquals(DEFAULT_CATALOG, rs.getString("INDEX_QUALIFIER")); - // Foreign key index names are automatically generated. - if (!"FOREIGN_KEY".equals(index.indexName) && !"GENERATED".equals(index.indexName)) { - assertEquals(index.indexName, rs.getString("INDEX_NAME")); - } - if (index.indexName.equals("PRIMARY_KEY")) { - assertEquals(DatabaseMetaData.tableIndexClustered, rs.getShort("TYPE")); - } else { - assertEquals(DatabaseMetaData.tableIndexHashed, rs.getShort("TYPE")); - } - assertEquals(index.ordinalPosition, rs.getShort("ORDINAL_POSITION")); - if (index.ordinalPosition == 0) { - assertTrue(rs.wasNull()); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection.getMetaData().getIndexInfo(DEFAULT_CATALOG, schema, null, false, false)) { + + for (IndexInfo index : EXPECTED_INDICES) { + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(index.tableName, rs.getString("TABLE_NAME")); + assertEquals(index.nonUnique, rs.getBoolean("NON_UNIQUE")); + assertEquals(DEFAULT_CATALOG, rs.getString("INDEX_QUALIFIER")); + // Foreign key index names are automatically generated. + if (!"FOREIGN_KEY".equals(index.indexName) && !"GENERATED".equals(index.indexName)) { + assertEquals(index.indexName, rs.getString("INDEX_NAME")); + } + if (index.indexName.equals("PRIMARY_KEY")) { + assertEquals(DatabaseMetaData.tableIndexClustered, rs.getShort("TYPE")); + } else { + assertEquals(DatabaseMetaData.tableIndexHashed, rs.getShort("TYPE")); + } + assertEquals(index.ordinalPosition, rs.getShort("ORDINAL_POSITION")); + if (index.ordinalPosition == 0) { + assertTrue(rs.wasNull()); + } + assertEquals(index.columnName, rs.getString("COLUMN_NAME")); + assertEquals(index.ascDesc, rs.getString("ASC_OR_DESC")); + assertEquals(-1, rs.getInt("CARDINALITY")); + assertEquals(-1, rs.getInt("PAGES")); + assertNull(rs.getString("FILTER_CONDITION")); } - assertEquals(index.columnName, rs.getString("COLUMN_NAME")); - assertEquals(index.ascDesc, rs.getString("ASC_OR_DESC")); - assertEquals(-1, rs.getInt("CARDINALITY")); - assertEquals(-1, rs.getInt("PAGES")); - assertNull(rs.getString("FILTER_CONDITION")); + // all indices found + assertFalse(rs.next()); } - // all indices found - assertFalse(rs.next()); } } } @@ -520,15 +552,15 @@ public void testGetIndexInfo() throws SQLException { @Test public void testGetExportedKeys() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getExportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertExportedKeysSingers(rs); - } - try (ResultSet rs = - connection.getMetaData().getExportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertKeysAlbumsSongs(rs); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection.getMetaData().getExportedKeys(DEFAULT_CATALOG, schema, SINGERS_TABLE)) { + assertExportedKeysSingers(schema, rs); + } + try (ResultSet rs = + connection.getMetaData().getExportedKeys(DEFAULT_CATALOG, schema, ALBUMS_TABLE)) { + assertKeysAlbumsSongs(schema, rs); + } } } } @@ -536,31 +568,27 @@ public void testGetExportedKeys() throws SQLException { @Test public void testGetImportedKeys() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertImportedKeysSingers(rs); - } - try (ResultSet rs = - connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertImportedKeysAlbums(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, CONCERTS_TABLE)) { - assertImportedKeysConcerts(rs); - } - try (ResultSet rs = - connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SONGS_TABLE)) { - assertKeysAlbumsSongs(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, TABLE_WITH_REF)) { - assertImportedKeysTableWithRef(rs); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, schema, SINGERS_TABLE)) { + assertImportedKeysSingers(rs); + } + try (ResultSet rs = + connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, schema, ALBUMS_TABLE)) { + assertImportedKeysAlbums(schema, rs); + } + try (ResultSet rs = + connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, schema, CONCERTS_TABLE)) { + assertImportedKeysConcerts(schema, rs); + } + try (ResultSet rs = + connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, schema, SONGS_TABLE)) { + assertKeysAlbumsSongs(schema, rs); + } + try (ResultSet rs = + connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, schema, TABLE_WITH_REF)) { + assertImportedKeysTableWithRef(schema, rs); + } } } } @@ -569,14 +597,14 @@ private void assertImportedKeysSingers(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { + private void assertImportedKeysTableWithRef(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); assertEquals("ColFloat64", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); assertEquals("RefFloat", rs.getString("FKCOLUMN_NAME")); assertEquals(1, rs.getShort("KEY_SEQ")); @@ -588,11 +616,11 @@ private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); assertEquals("ColString", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); assertEquals("RefString", rs.getString("FKCOLUMN_NAME")); assertEquals(2, rs.getShort("KEY_SEQ")); @@ -604,11 +632,11 @@ private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); assertEquals("ColDate", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); assertEquals("RefDate", rs.getString("FKCOLUMN_NAME")); assertEquals(3, rs.getShort("KEY_SEQ")); @@ -621,14 +649,14 @@ private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertImportedKeysAlbums(ResultSet rs) throws SQLException { + private void assertImportedKeysAlbums(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(SINGERS_TABLE, rs.getString("PKTABLE_NAME")); assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(ALBUMS_TABLE, rs.getString("FKTABLE_NAME")); assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); assertEquals(1, rs.getShort("KEY_SEQ")); @@ -641,14 +669,14 @@ private void assertImportedKeysAlbums(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertImportedKeysConcerts(ResultSet rs) throws SQLException { + private void assertImportedKeysConcerts(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(SINGERS_TABLE, rs.getString("PKTABLE_NAME")); assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(CONCERTS_TABLE, rs.getString("FKTABLE_NAME")); assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); assertEquals(1, rs.getShort("KEY_SEQ")); @@ -661,14 +689,14 @@ private void assertImportedKeysConcerts(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertExportedKeysSingers(ResultSet rs) throws SQLException { + private void assertExportedKeysSingers(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(SINGERS_TABLE, rs.getString("PKTABLE_NAME")); assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(ALBUMS_TABLE, rs.getString("FKTABLE_NAME")); assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); assertEquals(1, rs.getShort("KEY_SEQ")); @@ -680,11 +708,11 @@ private void assertExportedKeysSingers(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(SINGERS_TABLE, rs.getString("PKTABLE_NAME")); assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(CONCERTS_TABLE, rs.getString("FKTABLE_NAME")); assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); assertEquals(1, rs.getShort("KEY_SEQ")); @@ -697,14 +725,14 @@ private void assertExportedKeysSingers(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { + private void assertKeysAlbumsSongs(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(ALBUMS_TABLE, rs.getString("PKTABLE_NAME")); assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(SONGS_TABLE, rs.getString("FKTABLE_NAME")); assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); assertEquals(1, rs.getShort("KEY_SEQ")); @@ -716,11 +744,11 @@ private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(ALBUMS_TABLE, rs.getString("PKTABLE_NAME")); assertEquals("AlbumId", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(SONGS_TABLE, rs.getString("FKTABLE_NAME")); assertEquals("AlbumId", rs.getString("FKCOLUMN_NAME")); assertEquals(2, rs.getShort("KEY_SEQ")); @@ -735,48 +763,54 @@ private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { @Test public void testGetPrimaryKeys() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection.getMetaData().getPrimaryKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertTrue(rs.next()); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(SINGERS_TABLE, rs.getString("TABLE_NAME")); - assertEquals("SingerId", rs.getString("COLUMN_NAME")); - assertEquals(1, rs.getInt("KEY_SEQ")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertFalse(rs.next()); - } - try (ResultSet rs = - connection.getMetaData().getPrimaryKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertTrue(rs.next()); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(ALBUMS_TABLE, rs.getString("TABLE_NAME")); - assertEquals("SingerId", rs.getString("COLUMN_NAME")); - assertEquals(1, rs.getInt("KEY_SEQ")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertTrue(rs.next()); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(ALBUMS_TABLE, rs.getString("TABLE_NAME")); - assertEquals("AlbumId", rs.getString("COLUMN_NAME")); - assertEquals(2, rs.getInt("KEY_SEQ")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertFalse(rs.next()); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection.getMetaData().getPrimaryKeys(DEFAULT_CATALOG, schema, SINGERS_TABLE)) { + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(SINGERS_TABLE, rs.getString("TABLE_NAME")); + assertEquals("SingerId", rs.getString("COLUMN_NAME")); + assertEquals(1, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertFalse(rs.next()); + } + try (ResultSet rs = + connection.getMetaData().getPrimaryKeys(DEFAULT_CATALOG, schema, ALBUMS_TABLE)) { + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(ALBUMS_TABLE, rs.getString("TABLE_NAME")); + assertEquals("SingerId", rs.getString("COLUMN_NAME")); + assertEquals(1, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(ALBUMS_TABLE, rs.getString("TABLE_NAME")); + assertEquals("AlbumId", rs.getString("COLUMN_NAME")); + assertEquals(2, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertFalse(rs.next()); + } } } } @Test public void testGetViews() throws SQLException { - // assumeFalse("Emulator does not yet support views", EmulatorSpannerHelper.isUsingEmulator()); try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = connection.getMetaData().getTables("", "", null, new String[] {"VIEW"})) { - assertTrue(rs.next()); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals("SingersView", rs.getString("TABLE_NAME")); - assertFalse(rs.next()); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getTables(DEFAULT_CATALOG, schema, null, new String[] {"VIEW"})) { + assertTrue(rs.next()); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals("SingersView", rs.getString("TABLE_NAME")); + assertFalse(rs.next()); + } } } } @@ -785,17 +819,24 @@ public void testGetViews() throws SQLException { public void testGetSchemas() throws SQLException { try (Connection connection = createConnection(env, database)) { assertEquals("", connection.getSchema()); - try (ResultSet rs = connection.getMetaData().getSchemas()) { - assertTrue(rs.next()); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CATALOG")); - assertTrue(rs.next()); - assertEquals("INFORMATION_SCHEMA", rs.getString("TABLE_SCHEM")); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CATALOG")); - assertTrue(rs.next()); - assertEquals("SPANNER_SYS", rs.getString("TABLE_SCHEM")); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CATALOG")); - assertFalse(rs.next()); + try (ResultSet schemas = connection.getMetaData().getSchemas()) { + assertTrue(schemas.next()); + assertEquals(DEFAULT_SCHEMA, schemas.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, schemas.getString("TABLE_CATALOG")); + + assertTrue(schemas.next()); + assertEquals("INFORMATION_SCHEMA", schemas.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, schemas.getString("TABLE_CATALOG")); + + assertTrue(schemas.next()); + assertEquals("SPANNER_SYS", schemas.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, schemas.getString("TABLE_CATALOG")); + + assertTrue(schemas.next()); + assertEquals("test", schemas.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, schemas.getString("TABLE_CATALOG")); + + assertFalse(schemas.next()); } } } @@ -841,22 +882,27 @@ private Table(String name, String type) { @Test public void testGetTables() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection.getMetaData().getTables(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, null)) { - for (Table table : EXPECTED_TABLES) { - assertTrue(rs.next()); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(table.name, rs.getString("TABLE_NAME")); - assertEquals(table.type, rs.getString("TABLE_TYPE")); - assertNull(rs.getString("REMARKS")); - assertNull(rs.getString("TYPE_CAT")); - assertNull(rs.getString("TYPE_SCHEM")); - assertNull(rs.getString("TYPE_NAME")); - assertNull(rs.getString("SELF_REFERENCING_COL_NAME")); - assertNull(rs.getString("REF_GENERATION")); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection.getMetaData().getTables(DEFAULT_CATALOG, schema, null, null)) { + for (Table table : EXPECTED_TABLES) { + if (EmulatorSpannerHelper.isUsingEmulator() && table.name.equals("SingersView")) { + continue; + } + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(table.name, rs.getString("TABLE_NAME")); + assertEquals(table.type, rs.getString("TABLE_TYPE")); + assertNull(rs.getString("REMARKS")); + assertNull(rs.getString("TYPE_CAT")); + assertNull(rs.getString("TYPE_SCHEM")); + assertNull(rs.getString("TYPE_NAME")); + assertNull(rs.getString("SELF_REFERENCING_COL_NAME")); + assertNull(rs.getString("REF_GENERATION")); + } + assertFalse(rs.next()); } - assertFalse(rs.next()); } } } diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java index 1b96e9569..033ff27e4 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java @@ -21,10 +21,13 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -32,9 +35,9 @@ import java.sql.Types; import java.util.Arrays; import java.util.List; -import org.junit.Before; +import java.util.stream.Collectors; +import org.junit.BeforeClass; import org.junit.ClassRule; -import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -54,11 +57,41 @@ public class ITJdbcPgDatabaseMetaDataTest extends ITAbstractJdbcTest { private static final String TABLE_WITH_ALL_COLS = "TableWithAllColumnTypes"; private static final String TABLE_WITH_REF = "TableWithRef"; - private Database database; - - @Before - public void setup() { - database = env.getOrCreateDatabase(getDialect(), getMusicTablesDdl(getDialect())); + private static Database database; + + @BeforeClass + public static void setup() throws Exception { + assumeFalse( + "PostgreSQL dialect is not yet supported on the emulator", + EmulatorSpannerHelper.isUsingEmulator()); + + database = env.getOrCreateDatabase(Dialect.POSTGRESQL, getMusicTablesDdl(Dialect.POSTGRESQL)); + + // Create the same tables in an additional 'test' schema. + DatabaseAdminClient client = env.getTestHelper().getClient().getDatabaseAdminClient(); + List tables = + getMusicTablesDdl(Dialect.POSTGRESQL).stream() + .map(statement -> statement.replace("CREATE TABLE ", "CREATE TABLE test.")) + .map(statement -> statement.replace("CREATE VIEW ", "CREATE VIEW test.")) + .map(statement -> statement.replace("FROM ", "FROM test.")) + .map( + statement -> + statement.replace("INTERLEAVE IN PARENT ", "INTERLEAVE IN PARENT test.")) + .map(statement -> statement.replace("INTERLEAVE IN ", "INTERLEAVE IN test.")) + .map( + statement -> statement.replace("INTERLEAVE IN test.PARENT", "INTERLEAVE IN PARENT")) + .map(statement -> statement.replace(" ON ", " ON test.")) + .map(statement -> statement.replace(" ON test.DELETE", " ON DELETE")) + .map(statement -> statement.replace(" REFERENCES ", " REFERENCES test.")) + .collect(Collectors.toList()); + tables.add(0, "create schema test"); + client + .updateDatabaseDdl( + database.getId().getInstanceId().getInstance(), + database.getId().getDatabase(), + tables, + null) + .get(); } @Override @@ -138,68 +171,70 @@ private Column( @Test public void testGetColumns() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getColumns(getDefaultCatalog(database), DEFAULT_SCHEMA, TABLE_WITH_ALL_COLS, null)) { - int pos = 1; - for (Column col : EXPECTED_COLUMNS) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals("tablewithallcolumntypes", rs.getString("TABLE_NAME")); - assertEquals(col.name, rs.getString("COLUMN_NAME")); - assertEquals(col.type, rs.getInt("DATA_TYPE")); - assertEquals(col.typeName, rs.getString("TYPE_NAME")); - if (col.colSize == null) { - assertEquals(0, rs.getInt("COLUMN_SIZE")); - assertTrue(rs.wasNull()); - } else { - assertEquals(col.colSize.intValue(), rs.getInt("COLUMN_SIZE")); - } - rs.getObject("BUFFER_LENGTH"); // just assert that it exists - if (col.decimalDigits == null) { - assertEquals(0, rs.getInt("DECIMAL_DIGITS")); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getColumns(getDefaultCatalog(database), schema, TABLE_WITH_ALL_COLS, null)) { + int pos = 1; + for (Column col : EXPECTED_COLUMNS) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals("tablewithallcolumntypes", rs.getString("TABLE_NAME")); + assertEquals(col.name, rs.getString("COLUMN_NAME")); + assertEquals(col.type, rs.getInt("DATA_TYPE")); + assertEquals(col.typeName, rs.getString("TYPE_NAME")); + if (col.colSize == null) { + assertEquals(0, rs.getInt("COLUMN_SIZE")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.colSize.intValue(), rs.getInt("COLUMN_SIZE")); + } + rs.getObject("BUFFER_LENGTH"); // just assert that it exists + if (col.decimalDigits == null) { + assertEquals(0, rs.getInt("DECIMAL_DIGITS")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.decimalDigits.intValue(), rs.getInt("DECIMAL_DIGITS")); + } + if (col.radix == null) { + assertEquals(0, rs.getInt("NUM_PREC_RADIX")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.radix.intValue(), rs.getInt("NUM_PREC_RADIX")); + } + assertEquals( + "Nullable difference for " + col.name, + col.nullable ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls, + rs.getInt("NULLABLE")); + assertNull(rs.getString("REMARKS")); + assertNull(rs.getString("COLUMN_DEF")); + assertEquals(0, rs.getInt("SQL_DATA_TYPE")); + assertEquals(0, rs.getInt("SQL_DATETIME_SUB")); + if (col.charOctetLength == null) { + assertEquals(0, rs.getInt("CHAR_OCTET_LENGTH")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.charOctetLength.intValue(), rs.getInt("CHAR_OCTET_LENGTH")); + } + assertEquals(pos, rs.getInt("ORDINAL_POSITION")); + assertEquals(col.nullable ? "YES" : "NO", rs.getString("IS_NULLABLE")); + assertNull(rs.getString("SCOPE_CATALOG")); + assertNull(rs.getString("SCOPE_SCHEMA")); + assertNull(rs.getString("SCOPE_TABLE")); + + assertEquals((short) 0, rs.getShort("SOURCE_DATA_TYPE")); assertTrue(rs.wasNull()); - } else { - assertEquals(col.decimalDigits.intValue(), rs.getInt("DECIMAL_DIGITS")); - } - if (col.radix == null) { - assertEquals(0, rs.getInt("NUM_PREC_RADIX")); - assertTrue(rs.wasNull()); - } else { - assertEquals(col.radix.intValue(), rs.getInt("NUM_PREC_RADIX")); - } - assertEquals( - "Nullable difference for " + col.name, - col.nullable ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls, - rs.getInt("NULLABLE")); - assertNull(rs.getString("REMARKS")); - assertNull(rs.getString("COLUMN_DEF")); - assertEquals(0, rs.getInt("SQL_DATA_TYPE")); - assertEquals(0, rs.getInt("SQL_DATETIME_SUB")); - if (col.charOctetLength == null) { - assertEquals(0, rs.getInt("CHAR_OCTET_LENGTH")); - assertTrue(rs.wasNull()); - } else { - assertEquals(col.charOctetLength.intValue(), rs.getInt("CHAR_OCTET_LENGTH")); - } - assertEquals(pos, rs.getInt("ORDINAL_POSITION")); - assertEquals(col.nullable ? "YES" : "NO", rs.getString("IS_NULLABLE")); - assertNull(rs.getString("SCOPE_CATALOG")); - assertNull(rs.getString("SCOPE_SCHEMA")); - assertNull(rs.getString("SCOPE_TABLE")); - assertEquals((short) 0, rs.getShort("SOURCE_DATA_TYPE")); - assertTrue(rs.wasNull()); + assertEquals("NO", rs.getString("IS_AUTOINCREMENT")); + assertEquals(col.computed ? "YES" : "NO", rs.getString("IS_GENERATEDCOLUMN")); + assertEquals(24, rs.getMetaData().getColumnCount()); - assertEquals("NO", rs.getString("IS_AUTOINCREMENT")); - assertEquals(col.computed ? "YES" : "NO", rs.getString("IS_GENERATEDCOLUMN")); - assertEquals(24, rs.getMetaData().getColumnCount()); - - pos++; + pos++; + } + assertFalse(rs.next()); } - assertFalse(rs.next()); } } } @@ -207,168 +242,170 @@ public void testGetColumns() throws SQLException { @Test public void testGetCrossReferences() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - getDefaultCatalog(database), - DEFAULT_SCHEMA, - SINGERS_TABLE, - getDefaultCatalog(database), - DEFAULT_SCHEMA, - ALBUMS_TABLE)) { - assertTrue(rs.next()); - - assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); - assertEquals("singers", rs.getString("PKTABLE_NAME")); - assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); - assertEquals("albums", rs.getString("FKTABLE_NAME")); - assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); - assertEquals((short) 1, rs.getShort("KEY_SEQ")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertNotNull(rs.getString("FK_NAME")); - assertEquals("PK_singers", rs.getString("PK_NAME")); - assertEquals( - (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - } - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - getDefaultCatalog(database), - DEFAULT_SCHEMA, - ALBUMS_TABLE, - getDefaultCatalog(database), - DEFAULT_SCHEMA, - SONGS_TABLE)) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); - assertEquals("albums", rs.getString("PKTABLE_NAME")); - assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); - assertEquals("songs", rs.getString("FKTABLE_NAME")); - assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); - assertEquals((short) 1, rs.getShort("KEY_SEQ")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertNotNull(rs.getString("FK_NAME")); - assertEquals("PK_albums", rs.getString("PK_NAME")); - assertEquals( - (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + getDefaultCatalog(database), + schema, + SINGERS_TABLE, + getDefaultCatalog(database), + schema, + ALBUMS_TABLE)) { + assertTrue(rs.next()); - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); - assertEquals("albums", rs.getString("PKTABLE_NAME")); - assertEquals("albumid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); - assertEquals("songs", rs.getString("FKTABLE_NAME")); - assertEquals("albumid", rs.getString("FKCOLUMN_NAME")); - assertEquals((short) 2, rs.getShort("KEY_SEQ")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertNotNull(rs.getString("FK_NAME")); - assertEquals("PK_albums", rs.getString("PK_NAME")); - assertEquals( - (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("singers", rs.getString("PKTABLE_NAME")); + assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("albums", rs.getString("FKTABLE_NAME")); + assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); + assertEquals((short) 1, rs.getShort("KEY_SEQ")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertNotNull(rs.getString("FK_NAME")); + assertEquals("PK_singers", rs.getString("PK_NAME")); + assertEquals( + (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + } + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + getDefaultCatalog(database), + schema, + ALBUMS_TABLE, + getDefaultCatalog(database), + schema, + SONGS_TABLE)) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("albums", rs.getString("PKTABLE_NAME")); + assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("songs", rs.getString("FKTABLE_NAME")); + assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); + assertEquals((short) 1, rs.getShort("KEY_SEQ")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertNotNull(rs.getString("FK_NAME")); + assertEquals("PK_albums", rs.getString("PK_NAME")); + assertEquals( + (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - assertFalse(rs.next()); - } + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("albums", rs.getString("PKTABLE_NAME")); + assertEquals("albumid", rs.getString("PKCOLUMN_NAME")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("songs", rs.getString("FKTABLE_NAME")); + assertEquals("albumid", rs.getString("FKCOLUMN_NAME")); + assertEquals((short) 2, rs.getShort("KEY_SEQ")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertNotNull(rs.getString("FK_NAME")); + assertEquals("PK_albums", rs.getString("PK_NAME")); + assertEquals( + (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - getDefaultCatalog(database), - DEFAULT_SCHEMA, - SINGERS_TABLE, - getDefaultCatalog(database), - DEFAULT_SCHEMA, - CONCERTS_TABLE)) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); - assertEquals("singers", rs.getString("PKTABLE_NAME")); - assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); - assertEquals("concerts", rs.getString("FKTABLE_NAME")); - assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); - assertEquals((short) 1, rs.getShort("KEY_SEQ")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertNotNull(rs.getString("FK_NAME")); - assertEquals("PK_singers", rs.getString("PK_NAME")); - assertEquals( - (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + assertFalse(rs.next()); + } - assertFalse(rs.next()); - } + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + getDefaultCatalog(database), + schema, + SINGERS_TABLE, + getDefaultCatalog(database), + schema, + CONCERTS_TABLE)) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("singers", rs.getString("PKTABLE_NAME")); + assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("concerts", rs.getString("FKTABLE_NAME")); + assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); + assertEquals((short) 1, rs.getShort("KEY_SEQ")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertNotNull(rs.getString("FK_NAME")); + assertEquals("PK_singers", rs.getString("PK_NAME")); + assertEquals( + (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - getDefaultCatalog(database), - DEFAULT_SCHEMA, - TABLE_WITH_ALL_COLS, - getDefaultCatalog(database), - DEFAULT_SCHEMA, - TABLE_WITH_REF)) { + assertFalse(rs.next()); + } - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); - assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); - assertEquals("colfloat64", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); - assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); - assertEquals("reffloat", rs.getString("FKCOLUMN_NAME")); - assertEquals((short) 1, rs.getShort("KEY_SEQ")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("fk_tablewithref_tablewithallcolumntypes", rs.getString("FK_NAME")); - assertEquals( - (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + getDefaultCatalog(database), + schema, + TABLE_WITH_ALL_COLS, + getDefaultCatalog(database), + schema, + TABLE_WITH_REF)) { + + assertTrue(schema, rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); + assertEquals("colfloat64", rs.getString("PKCOLUMN_NAME")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); + assertEquals("reffloat", rs.getString("FKCOLUMN_NAME")); + assertEquals((short) 1, rs.getShort("KEY_SEQ")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("fk_tablewithref_tablewithallcolumntypes", rs.getString("FK_NAME")); + assertEquals( + (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); - assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); - assertEquals("colstring", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); - assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); - assertEquals("refstring", rs.getString("FKCOLUMN_NAME")); - assertEquals((short) 2, rs.getShort("KEY_SEQ")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("fk_tablewithref_tablewithallcolumntypes", rs.getString("FK_NAME")); - assertEquals( - (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); + assertEquals("colstring", rs.getString("PKCOLUMN_NAME")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); + assertEquals("refstring", rs.getString("FKCOLUMN_NAME")); + assertEquals((short) 2, rs.getShort("KEY_SEQ")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("fk_tablewithref_tablewithallcolumntypes", rs.getString("FK_NAME")); + assertEquals( + (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - assertFalse(rs.next()); - } - // try getting self-references - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - getDefaultCatalog(database), - DEFAULT_SCHEMA, - ALBUMS_TABLE, - getDefaultCatalog(database), - DEFAULT_SCHEMA, - ALBUMS_TABLE)) { - assertFalse(rs.next()); + assertFalse(rs.next()); + } + // try getting self-references + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + getDefaultCatalog(database), + schema, + ALBUMS_TABLE, + getDefaultCatalog(database), + schema, + ALBUMS_TABLE)) { + assertFalse(rs.next()); + } } // try getting all cross-references in the database try (ResultSet rs = @@ -377,7 +414,7 @@ public void testGetCrossReferences() throws SQLException { while (rs.next()) { count++; } - assertEquals(6, count); + assertEquals(12, count); } } } @@ -442,36 +479,38 @@ private IndexInfo( @Test public void testGetIndexInfo() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getIndexInfo(getDefaultCatalog(database), DEFAULT_SCHEMA, null, false, false)) { - - for (IndexInfo index : EXPECTED_INDICES) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(index.tableName, rs.getString("TABLE_NAME")); - assertEquals(index.nonUnique, rs.getBoolean("NON_UNIQUE")); - assertEquals(getDefaultCatalog(database), rs.getString("INDEX_QUALIFIER")); - - // Foreign key index names are automatically generated. - if (!"FOREIGN_KEY".equals(index.indexName) && !"GENERATED".equals(index.indexName)) { - assertEquals(index.indexName, rs.getString("INDEX_NAME")); - } - assertEquals(DatabaseMetaData.tableIndexHashed, rs.getShort("TYPE")); - assertEquals(index.ordinalPosition, rs.getShort("ORDINAL_POSITION")); - if (index.ordinalPosition == 0) { - assertTrue(rs.wasNull()); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getIndexInfo(getDefaultCatalog(database), schema, null, false, false)) { + + for (IndexInfo index : EXPECTED_INDICES) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(index.tableName, rs.getString("TABLE_NAME")); + assertEquals(index.nonUnique, rs.getBoolean("NON_UNIQUE")); + assertEquals(getDefaultCatalog(database), rs.getString("INDEX_QUALIFIER")); + + // Foreign key index names are automatically generated. + if (!"FOREIGN_KEY".equals(index.indexName) && !"GENERATED".equals(index.indexName)) { + assertEquals(index.indexName, rs.getString("INDEX_NAME")); + } + assertEquals(DatabaseMetaData.tableIndexHashed, rs.getShort("TYPE")); + assertEquals(index.ordinalPosition, rs.getShort("ORDINAL_POSITION")); + if (index.ordinalPosition == 0) { + assertTrue(rs.wasNull()); + } + assertEquals(index.columnName, rs.getString("COLUMN_NAME")); + assertEquals(index.ascDesc, rs.getString("ASC_OR_DESC")); + assertEquals(-1, rs.getInt("CARDINALITY")); + assertEquals(-1, rs.getInt("PAGES")); + assertNull(rs.getString("FILTER_CONDITION")); } - assertEquals(index.columnName, rs.getString("COLUMN_NAME")); - assertEquals(index.ascDesc, rs.getString("ASC_OR_DESC")); - assertEquals(-1, rs.getInt("CARDINALITY")); - assertEquals(-1, rs.getInt("PAGES")); - assertNull(rs.getString("FILTER_CONDITION")); + // all indices found + assertFalse(rs.next()); } - // all indices found - assertFalse(rs.next()); } } } @@ -479,17 +518,19 @@ public void testGetIndexInfo() throws SQLException { @Test public void testGetExportedKeys() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getExportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertExportedKeysSingers(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getExportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertKeysAlbumsSongs(rs); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getExportedKeys(getDefaultCatalog(database), schema, SINGERS_TABLE)) { + assertExportedKeysSingers(schema, rs); + } + try (ResultSet rs = + connection + .getMetaData() + .getExportedKeys(getDefaultCatalog(database), schema, ALBUMS_TABLE)) { + assertKeysAlbumsSongs(schema, rs); + } } } } @@ -497,51 +538,53 @@ public void testGetExportedKeys() throws SQLException { @Test public void testGetImportedKeys() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertImportedKeysSingers(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertImportedKeysAlbums(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, CONCERTS_TABLE)) { - assertImportedKeysConcerts(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, SONGS_TABLE)) { - assertKeysAlbumsSongs(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, TABLE_WITH_REF)) { - assertImportedKeysTableWithRef(rs); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getImportedKeys(getDefaultCatalog(database), schema, SINGERS_TABLE)) { + assertImportedKeysSingers(schema, rs); + } + try (ResultSet rs = + connection + .getMetaData() + .getImportedKeys(getDefaultCatalog(database), schema, ALBUMS_TABLE)) { + assertImportedKeysAlbums(schema, rs); + } + try (ResultSet rs = + connection + .getMetaData() + .getImportedKeys(getDefaultCatalog(database), schema, CONCERTS_TABLE)) { + assertImportedKeysConcerts(schema, rs); + } + try (ResultSet rs = + connection + .getMetaData() + .getImportedKeys(getDefaultCatalog(database), schema, SONGS_TABLE)) { + assertKeysAlbumsSongs(schema, rs); + } + try (ResultSet rs = + connection + .getMetaData() + .getImportedKeys(getDefaultCatalog(database), schema, TABLE_WITH_REF)) { + assertImportedKeysTableWithRef(schema, rs); + } } } } - private void assertImportedKeysSingers(ResultSet rs) throws SQLException { + private void assertImportedKeysSingers(String schema, ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { + private void assertImportedKeysTableWithRef(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); assertEquals("colfloat64", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); assertEquals("reffloat", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 1, rs.getShort("KEY_SEQ")); @@ -553,11 +596,11 @@ private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); assertEquals("colstring", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); assertEquals("refstring", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 2, rs.getShort("KEY_SEQ")); @@ -570,14 +613,14 @@ private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertImportedKeysAlbums(ResultSet rs) throws SQLException { + private void assertImportedKeysAlbums(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("albums", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 1, rs.getShort("KEY_SEQ")); @@ -590,14 +633,14 @@ private void assertImportedKeysAlbums(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertImportedKeysConcerts(ResultSet rs) throws SQLException { + private void assertImportedKeysConcerts(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("concerts", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 1, rs.getShort("KEY_SEQ")); @@ -609,14 +652,14 @@ private void assertImportedKeysConcerts(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertExportedKeysSingers(ResultSet rs) throws SQLException { + private void assertExportedKeysSingers(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("albums", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 1, rs.getShort("KEY_SEQ")); @@ -628,11 +671,11 @@ private void assertExportedKeysSingers(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("concerts", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 1, rs.getShort("KEY_SEQ")); @@ -645,14 +688,14 @@ private void assertExportedKeysSingers(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { + private void assertKeysAlbumsSongs(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("albums", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("songs", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 1, rs.getShort("KEY_SEQ")); @@ -664,11 +707,11 @@ private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("albums", rs.getString("PKTABLE_NAME")); assertEquals("albumid", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("songs", rs.getString("FKTABLE_NAME")); assertEquals("albumid", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 2, rs.getShort("KEY_SEQ")); @@ -684,58 +727,60 @@ private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { @Test public void testGetPrimaryKeys() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getPrimaryKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals("singers", rs.getString("TABLE_NAME")); - assertEquals("singerid", rs.getString("COLUMN_NAME")); - assertEquals(1, rs.getInt("KEY_SEQ")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertFalse(rs.next()); - } + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getPrimaryKeys(getDefaultCatalog(database), schema, SINGERS_TABLE)) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals("singers", rs.getString("TABLE_NAME")); + assertEquals("singerid", rs.getString("COLUMN_NAME")); + assertEquals(1, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertFalse(rs.next()); + } - try (ResultSet rs = - connection - .getMetaData() - .getPrimaryKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals("albums", rs.getString("TABLE_NAME")); - assertEquals("singerid", rs.getString("COLUMN_NAME")); - assertEquals(1, rs.getInt("KEY_SEQ")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals("albums", rs.getString("TABLE_NAME")); - assertEquals("albumid", rs.getString("COLUMN_NAME")); - assertEquals(2, rs.getInt("KEY_SEQ")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + try (ResultSet rs = + connection + .getMetaData() + .getPrimaryKeys(getDefaultCatalog(database), schema, ALBUMS_TABLE)) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals("albums", rs.getString("TABLE_NAME")); + assertEquals("singerid", rs.getString("COLUMN_NAME")); + assertEquals(1, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals("albums", rs.getString("TABLE_NAME")); + assertEquals("albumid", rs.getString("COLUMN_NAME")); + assertEquals(2, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertFalse(rs.next()); + assertFalse(rs.next()); + } } } } - @Ignore("Views are not yet supported for PostgreSQL") @Test public void testGetViews() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getTables( - getDefaultCatalog(database), DEFAULT_SCHEMA, null, new String[] {"VIEW"})) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals("SingersView", rs.getString("TABLE_NAME")); - assertFalse(rs.next()); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getTables(getDefaultCatalog(database), schema, null, new String[] {"VIEW"})) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals("singersview", rs.getString("TABLE_NAME")); + assertFalse(rs.next()); + } } } } @@ -744,24 +789,28 @@ public void testGetViews() throws SQLException { public void testGetSchemas() throws SQLException { try (Connection connection = createConnection(env, database)) { assertEquals("public", connection.getSchema()); - try (ResultSet rs = connection.getMetaData().getSchemas()) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); - assertEquals("information_schema", rs.getString("TABLE_SCHEM")); + try (ResultSet schemas = connection.getMetaData().getSchemas()) { + assertTrue(schemas.next()); + assertEquals(getDefaultCatalog(database), schemas.getString("TABLE_CATALOG")); + assertEquals("information_schema", schemas.getString("TABLE_SCHEM")); - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); - assertEquals("pg_catalog", rs.getString("TABLE_SCHEM")); + assertTrue(schemas.next()); + assertEquals(getDefaultCatalog(database), schemas.getString("TABLE_CATALOG")); + assertEquals("pg_catalog", schemas.getString("TABLE_SCHEM")); - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); - assertEquals("public", rs.getString("TABLE_SCHEM")); + assertTrue(schemas.next()); + assertEquals(getDefaultCatalog(database), schemas.getString("TABLE_CATALOG")); + assertEquals("public", schemas.getString("TABLE_SCHEM")); - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); - assertEquals("spanner_sys", rs.getString("TABLE_SCHEM")); + assertTrue(schemas.next()); + assertEquals(getDefaultCatalog(database), schemas.getString("TABLE_CATALOG")); + assertEquals("spanner_sys", schemas.getString("TABLE_SCHEM")); - assertFalse(rs.next()); + assertTrue(schemas.next()); + assertEquals(getDefaultCatalog(database), schemas.getString("TABLE_CATALOG")); + assertEquals("test", schemas.getString("TABLE_SCHEM")); + + assertFalse(schemas.next()); } } } @@ -799,8 +848,7 @@ private Table(String name, String type) { new Table("all_nullable_types"), new Table("concerts"), new Table("singers"), - // TODO: Enable when views are supported for PostgreSQL dialect databases. - // new Table("singersview", "VIEW"), + new Table("singersview", "VIEW"), new Table("songs"), new Table("tablewithallcolumntypes"), new Table("tablewithref")); diff --git a/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql b/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql index abecd9fad..3aafc5722 100644 --- a/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql +++ b/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql @@ -26,6 +26,11 @@ CREATE TABLE Singers ( CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName); +CREATE VIEW SingersView SQL SECURITY INVOKER AS +SELECT s.SingerId AS SingerId, s.FirstName AS FirstName, s.LastName AS LastName +FROM Singers s +ORDER BY s.LastName, s.FirstName; + CREATE TABLE Albums ( SingerId BIGINT NOT NULL, AlbumId BIGINT NOT NULL, From e5ffdb83fe2c9a2b71557e2c0ae7682f3eb76076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 20 Aug 2024 16:51:43 +0200 Subject: [PATCH 19/32] chore: update version numbers in README when releasing (#1714) Fixes #1317 --- .github/release-please.yml | 2 +- README.md | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/release-please.yml b/.github/release-please.yml index cbc451149..bd2014774 100644 --- a/.github/release-please.yml +++ b/.github/release-please.yml @@ -6,4 +6,4 @@ branches: releaseType: java-yoshi bumpMinorPreMajor: true handleGHRelease: true - +extraFiles: ["README.md"] diff --git a/README.md b/README.md index e7c6e9e6c..6ced7a57e 100644 --- a/README.md +++ b/README.md @@ -15,25 +15,32 @@ Java idiomatic client for [Google Cloud Spanner JDBC][product-docs]. If you are using Maven, add this to your pom.xml file: + ```xml com.google.cloud google-cloud-spanner-jdbc - 2.4.1 + 2.20.2 ``` + + If you are using Gradle without BOM, add this to your dependencies + ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.4.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.20.2' ``` + If you are using SBT, add this to your dependencies + ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.4.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.20.2" ``` + ## Authentication From 21aa19970cee5ee0525c5eaae8bc334cf81d8f25 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 18:08:47 +0200 Subject: [PATCH 20/32] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.17.2 (#1715) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.fasterxml.jackson.core:jackson-databind](https://togithub.com/FasterXML/jackson) ([source](https://togithub.com/FasterXML/jackson-databind)) | `2.13.4.2` -> `2.17.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.fasterxml.jackson.core:jackson-databind/2.17.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.fasterxml.jackson.core:jackson-databind/2.17.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.fasterxml.jackson.core:jackson-databind/2.13.4.2/2.17.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.fasterxml.jackson.core:jackson-databind/2.13.4.2/2.17.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/quickperf/pom.xml b/samples/quickperf/pom.xml index e42e323ef..66380a757 100644 --- a/samples/quickperf/pom.xml +++ b/samples/quickperf/pom.xml @@ -61,7 +61,7 @@ com.fasterxml.jackson.core jackson-databind - 2.13.4.2 + 2.17.2 From 6f48065952c2fc2716c911a45959326a6bafaa13 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 18:10:23 +0200 Subject: [PATCH 21/32] deps: update dependency commons-cli:commons-cli to v1.9.0 (#1716) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [commons-cli:commons-cli](https://commons.apache.org/proper/commons-cli/) ([source](https://gitbox.apache.org/repos/asf?p=commons-cli.git)) | `1.5.0` -> `1.9.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/commons-cli:commons-cli/1.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/commons-cli:commons-cli/1.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/commons-cli:commons-cli/1.5.0/1.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/commons-cli:commons-cli/1.5.0/1.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/quickperf/pom.xml b/samples/quickperf/pom.xml index 66380a757..6bb8bc299 100644 --- a/samples/quickperf/pom.xml +++ b/samples/quickperf/pom.xml @@ -47,7 +47,7 @@ commons-cli commons-cli - 1.5.0 + 1.9.0 com.google.cloud From ede72113801de4a27492cf672a4c5e3edb37bc5e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 18:34:28 +0200 Subject: [PATCH 22/32] deps: update dependency org.springframework.boot:spring-boot to v3.3.2 (#1718) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot](https://spring.io/projects/spring-boot) ([source](https://togithub.com/spring-projects/spring-boot)) | `3.2.5` -> `3.3.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot/3.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot/3.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot/3.2.5/3.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot/3.2.5/3.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
spring-projects/spring-boot (org.springframework.boot:spring-boot) ### [`v3.3.2`](https://togithub.com/spring-projects/spring-boot/compare/v3.3.1...v3.3.2) ### [`v3.3.1`](https://togithub.com/spring-projects/spring-boot/compare/v3.3.0...v3.3.1) ### [`v3.3.0`](https://togithub.com/spring-projects/spring-boot/compare/v3.2.6...v3.3.0) [Compare Source](https://togithub.com/spring-projects/spring-boot/compare/v3.2.8...v3.3.0) ### [`v3.2.8`](https://togithub.com/spring-projects/spring-boot/compare/v3.2.7...v3.2.8) ### [`v3.2.7`](https://togithub.com/spring-projects/spring-boot/compare/v3.2.6...v3.2.7) ### [`v3.2.6`](https://togithub.com/spring-projects/spring-boot/compare/v3.2.5...v3.2.6)
--- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/quickperf/pom.xml b/samples/quickperf/pom.xml index 6bb8bc299..f10c1d0c3 100644 --- a/samples/quickperf/pom.xml +++ b/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.springframework.boot spring-boot - 3.2.5 + 3.3.2 test From f5229ce5099b6d2d2b7c099ff4ac1319f21860df Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 18:36:28 +0200 Subject: [PATCH 23/32] deps: update dependency org.apache.commons:commons-lang3 to v3.16.0 (#1717) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.commons:commons-lang3](https://commons.apache.org/proper/commons-lang/) ([source](https://gitbox.apache.org/repos/asf?p=commons-lang.git)) | `3.13.0` -> `3.16.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.apache.commons:commons-lang3/3.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.apache.commons:commons-lang3/3.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.apache.commons:commons-lang3/3.13.0/3.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.apache.commons:commons-lang3/3.13.0/3.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/quickperf/pom.xml b/samples/quickperf/pom.xml index f10c1d0c3..b1d48dfff 100644 --- a/samples/quickperf/pom.xml +++ b/samples/quickperf/pom.xml @@ -56,7 +56,7 @@ org.apache.commons commons-lang3 - 3.13.0 + 3.16.0 com.fasterxml.jackson.core From f5f80517425969f4c1bab4ec1c72afa1ccbb842c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:21:59 +0200 Subject: [PATCH 24/32] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.73.0 (#1726) --- pom.xml | 2 +- samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index fc46b2952..1b76e799c 100644 --- a/pom.xml +++ b/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.72.0 + 6.73.0 pom import diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 6a138bbcf..6d6583413 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.72.0 + 6.73.0 import pom From a40606c2ef75388cfa0733c6955329225f28c71b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:22:15 +0200 Subject: [PATCH 25/32] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.48.0 (#1719) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1b76e799c..1e75e532d 100644 --- a/pom.xml +++ b/pom.xml @@ -238,7 +238,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.47.0 + 2.48.0 test From c9b646d1b9c0ccef9cf8ba3bc58da686fae34bc1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:36:04 +0200 Subject: [PATCH 26/32] deps: update dependency com.google.cloud:google-cloud-trace to v2.48.0 (#1720) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1e75e532d..2430f9363 100644 --- a/pom.xml +++ b/pom.xml @@ -232,7 +232,7 @@ com.google.cloud google-cloud-trace - 2.47.0 + 2.48.0 test From 13282136921d0167c19cac38df0a652cc5477faa Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:38:23 +0200 Subject: [PATCH 27/32] deps: update dependency org.postgresql:postgresql to v42.7.4 (#1722) --- samples/spring-data-jdbc/pom.xml | 2 +- samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 6d6583413..81225b589 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -67,7 +67,7 @@ org.postgresql postgresql - 42.7.3 + 42.7.4 diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index 87793be8d..733957e3a 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -62,7 +62,7 @@ org.postgresql postgresql - 42.7.3 + 42.7.4 From 47fda8f9b8cf639fe11fb3241256490f660e0d8b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:40:22 +0200 Subject: [PATCH 28/32] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.3 (#1725) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot-starter-parent](https://spring.io/projects/spring-boot) ([source](https://togithub.com/spring-projects/spring-boot)) | `3.3.2` -> `3.3.3` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot-starter-parent/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot-starter-parent/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot-starter-parent/3.3.2/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot-starter-parent/3.3.2/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
spring-projects/spring-boot (org.springframework.boot:spring-boot-starter-parent) ### [`v3.3.3`](https://togithub.com/spring-projects/spring-boot/compare/v3.3.2...v3.3.3) [Compare Source](https://togithub.com/spring-projects/spring-boot/compare/v3.3.2...v3.3.3)
--- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index 733957e3a..8a13c6bb8 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.3.2 + 3.3.3 From 2d8c423515f9600f02a8efd9e0f5e0e66cd80618 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:48:21 +0200 Subject: [PATCH 29/32] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.7.0 (#1721) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-project-info-reports-plugin](https://maven.apache.org/plugins/) | `3.6.2` -> `3.7.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.6.2/3.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.6.2/3.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2430f9363..e8d77e30a 100644 --- a/pom.xml +++ b/pom.xml @@ -459,7 +459,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.6.2 + 3.7.0 From 55112ac5f00d4a8d7726fa8bc5e9428d08d21227 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:52:18 +0200 Subject: [PATCH 30/32] deps: update dependency org.springframework.boot:spring-boot to v3.3.3 (#1723) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot](https://spring.io/projects/spring-boot) ([source](https://togithub.com/spring-projects/spring-boot)) | `3.3.2` -> `3.3.3` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot/3.3.2/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot/3.3.2/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
spring-projects/spring-boot (org.springframework.boot:spring-boot) ### [`v3.3.3`](https://togithub.com/spring-projects/spring-boot/compare/v3.3.2...v3.3.3)
--- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/quickperf/pom.xml b/samples/quickperf/pom.xml index b1d48dfff..181a7639f 100644 --- a/samples/quickperf/pom.xml +++ b/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.springframework.boot spring-boot - 3.3.2 + 3.3.3 test From db60f4f4f8713a30c1fe275266ff455fd03d84a4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:52:22 +0200 Subject: [PATCH 31/32] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.3 (#1724) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot-starter-data-jdbc](https://spring.io/projects/spring-boot) ([source](https://togithub.com/spring-projects/spring-boot)) | `3.3.2` -> `3.3.3` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.3.2/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.3.2/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
spring-projects/spring-boot (org.springframework.boot:spring-boot-starter-data-jdbc) ### [`v3.3.3`](https://togithub.com/spring-projects/spring-boot/compare/v3.3.2...v3.3.3) [Compare Source](https://togithub.com/spring-projects/spring-boot/compare/v3.3.2...v3.3.3)
--- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 81225b589..cf4c573b7 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.3.2 + 3.3.3 From 7f22202b9d6f0482f4b26b2e319ffd3bcbf817a5 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 10:06:59 +0200 Subject: [PATCH 32/32] chore(main): release 2.21.0 (#1706) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ README.md | 6 +++--- pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- versions.txt | 2 +- 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 424389937..e48516502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## [2.21.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.20.2...v2.21.0) (2024-08-23) + + +### Features + +* Add Quickperf for simple performance testing with JDBC ([#1619](https://github.com/googleapis/java-spanner-jdbc/issues/1619)) ([b6bbd8f](https://github.com/googleapis/java-spanner-jdbc/commit/b6bbd8f40c1ce61914e2c7b80be04abbf4e346ab)) + + +### Dependencies + +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.13.4.2 [security] ([#1710](https://github.com/googleapis/java-spanner-jdbc/issues/1710)) ([eff5df2](https://github.com/googleapis/java-spanner-jdbc/commit/eff5df22785e55a8f0974f028678883ef404b4e6)) +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.17.2 ([#1715](https://github.com/googleapis/java-spanner-jdbc/issues/1715)) ([21aa199](https://github.com/googleapis/java-spanner-jdbc/commit/21aa19970cee5ee0525c5eaae8bc334cf81d8f25)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.48.0 ([#1719](https://github.com/googleapis/java-spanner-jdbc/issues/1719)) ([a40606c](https://github.com/googleapis/java-spanner-jdbc/commit/a40606c2ef75388cfa0733c6955329225f28c71b)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.72.0 ([#1702](https://github.com/googleapis/java-spanner-jdbc/issues/1702)) ([31a961d](https://github.com/googleapis/java-spanner-jdbc/commit/31a961d29c7b51e9dcd5aac8a8a66444abbd9088)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.73.0 ([#1726](https://github.com/googleapis/java-spanner-jdbc/issues/1726)) ([f5f8051](https://github.com/googleapis/java-spanner-jdbc/commit/f5f80517425969f4c1bab4ec1c72afa1ccbb842c)) +* Update dependency com.google.cloud:google-cloud-trace to v2.48.0 ([#1720](https://github.com/googleapis/java-spanner-jdbc/issues/1720)) ([c9b646d](https://github.com/googleapis/java-spanner-jdbc/commit/c9b646d1b9c0ccef9cf8ba3bc58da686fae34bc1)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.34.0 ([#1705](https://github.com/googleapis/java-spanner-jdbc/issues/1705)) ([f3f0c10](https://github.com/googleapis/java-spanner-jdbc/commit/f3f0c10394e76389dbc4a62e5702fd5f80c57b1a)) +* Update dependency com.spotify.fmt:fmt-maven-plugin to v2.24 ([#1708](https://github.com/googleapis/java-spanner-jdbc/issues/1708)) ([6881512](https://github.com/googleapis/java-spanner-jdbc/commit/68815128ae2c40c224b4ab155b942e8f5313024f)) +* Update dependency commons-cli:commons-cli to v1.9.0 ([#1716](https://github.com/googleapis/java-spanner-jdbc/issues/1716)) ([6f48065](https://github.com/googleapis/java-spanner-jdbc/commit/6f48065952c2fc2716c911a45959326a6bafaa13)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.41.0 ([#1703](https://github.com/googleapis/java-spanner-jdbc/issues/1703)) ([af58b7a](https://github.com/googleapis/java-spanner-jdbc/commit/af58b7a882edae9a50fbc0d4084cb74b3727d5a6)) +* Update dependency org.apache.commons:commons-lang3 to v3.16.0 ([#1717](https://github.com/googleapis/java-spanner-jdbc/issues/1717)) ([f5229ce](https://github.com/googleapis/java-spanner-jdbc/commit/f5229ce5099b6d2d2b7c099ff4ac1319f21860df)) +* Update dependency org.postgresql:postgresql to v42.7.4 ([#1722](https://github.com/googleapis/java-spanner-jdbc/issues/1722)) ([1328213](https://github.com/googleapis/java-spanner-jdbc/commit/13282136921d0167c19cac38df0a652cc5477faa)) +* Update dependency org.springframework.boot:spring-boot to v3.3.2 ([#1718](https://github.com/googleapis/java-spanner-jdbc/issues/1718)) ([ede7211](https://github.com/googleapis/java-spanner-jdbc/commit/ede72113801de4a27492cf672a4c5e3edb37bc5e)) +* Update dependency org.springframework.boot:spring-boot to v3.3.3 ([#1723](https://github.com/googleapis/java-spanner-jdbc/issues/1723)) ([55112ac](https://github.com/googleapis/java-spanner-jdbc/commit/55112ac5f00d4a8d7726fa8bc5e9428d08d21227)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.3 ([#1724](https://github.com/googleapis/java-spanner-jdbc/issues/1724)) ([db60f4f](https://github.com/googleapis/java-spanner-jdbc/commit/db60f4f4f8713a30c1fe275266ff455fd03d84a4)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.3 ([#1725](https://github.com/googleapis/java-spanner-jdbc/issues/1725)) ([47fda8f](https://github.com/googleapis/java-spanner-jdbc/commit/47fda8f9b8cf639fe11fb3241256490f660e0d8b)) +* Update dependency org.springframework.data:spring-data-bom to v2024.0.3 ([#1704](https://github.com/googleapis/java-spanner-jdbc/issues/1704)) ([e82d839](https://github.com/googleapis/java-spanner-jdbc/commit/e82d8398eede11469c966aa11c2188c671a5f02b)) +* Update dependency org.testcontainers:testcontainers to v1.20.1 ([#1684](https://github.com/googleapis/java-spanner-jdbc/issues/1684)) ([0907305](https://github.com/googleapis/java-spanner-jdbc/commit/09073057df2cff41b7a62f56dc0cf57ed62f4801)) + ## [2.20.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.20.1...v2.20.2) (2024-08-07) diff --git a/README.md b/README.md index 6ced7a57e..80eb44152 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.20.2 + 2.21.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.20.2' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.21.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.20.2" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.21.0" ``` diff --git a/pom.xml b/pom.xml index e8d77e30a..220e0dcea 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 google-cloud-spanner-jdbc - 2.20.3-SNAPSHOT + 2.21.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index fcfad34c9..751a517e9 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.3-SNAPSHOT + 2.21.0 diff --git a/versions.txt b/versions.txt index 716f29f11..05d8b85f0 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.20.2:2.20.3-SNAPSHOT +google-cloud-spanner-jdbc:2.21.0:2.21.0