Date: Tue, 4 Jul 2023 12:15:25 +0200
Subject: [PATCH 024/173] chore(deps): update dependency
com.google.cloud:google-cloud-spanner-jdbc to v2.11.2 (#1273)
---
samples/install-without-bom/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 3902fadfa..1ef1d77c7 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.11.0
+ 2.11.2
From bd4dedd4ec7c9960c202ed5ff920f942f0baf4bc Mon Sep 17 00:00:00 2001
From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com>
Date: Sat, 8 Jul 2023 19:18:42 -0400
Subject: [PATCH 025/173] ci: javadoc job (JDK 17) in ci.yaml (#1819) (#1276)
---
.github/.OwlBot.lock.yaml | 4 +--
.github/workflows/ci.yaml | 26 ++++++++++++++-----
.github/workflows/samples.yaml | 2 +-
.../jdbc/CloudSpannerJdbcConnection.java | 2 +-
4 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml
index 47a70ea40..258389d1a 100644
--- a/.github/.OwlBot.lock.yaml
+++ b/.github/.OwlBot.lock.yaml
@@ -13,5 +13,5 @@
# limitations under the License.
docker:
image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest
- digest: sha256:32851debfefed2b66038e0141f1b5c2103bb59ba80b7475adbc10ef7abab3de7
-# created: 2023-06-22T15:06:52.039318836Z
+ digest: sha256:31c8276a1bfb43766597d32645721c029cb94571f1b8d996cb2c290744fe52f9
+# created: 2023-06-27T18:51:58.922150125Z
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 65436cde4..e27b2c575 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -30,7 +30,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
- distribution: zulu
+ distribution: temurin
java-version: ${{matrix.java}}
- run: java -version
- run: .kokoro/build.sh
@@ -45,7 +45,7 @@ jobs:
- uses: actions/setup-java@v3
with:
java-version: 8
- distribution: zulu
+ distribution: temurin
- name: "Set jvm system property environment variable for surefire plugin (unit tests)"
# Maven surefire plugin (unit tests) allows us to specify JVM to run the tests.
# https://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#jvm
@@ -54,7 +54,7 @@ jobs:
- uses: actions/setup-java@v3
with:
java-version: 17
- distribution: zulu
+ distribution: temurin
- run: .kokoro/build.sh
env:
JOB_TYPE: test
@@ -66,7 +66,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
- distribution: zulu
+ distribution: temurin
java-version: 8
- run: java -version
- run: .kokoro/build.bat
@@ -81,17 +81,29 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
- distribution: zulu
+ distribution: temurin
java-version: ${{matrix.java}}
- run: java -version
- run: .kokoro/dependencies.sh
+ javadoc:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-java@v3
+ with:
+ distribution: temurin
+ java-version: 17
+ - run: java -version
+ - run: .kokoro/build.sh
+ env:
+ JOB_TYPE: javadoc
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
- distribution: zulu
+ distribution: temurin
java-version: 11
- run: java -version
- run: .kokoro/build.sh
@@ -103,7 +115,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
- distribution: zulu
+ distribution: temurin
java-version: 8
- run: java -version
- run: .kokoro/build.sh
diff --git a/.github/workflows/samples.yaml b/.github/workflows/samples.yaml
index 912ed8b2b..10d252d77 100644
--- a/.github/workflows/samples.yaml
+++ b/.github/workflows/samples.yaml
@@ -23,7 +23,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
- distribution: zulu
+ distribution: temurin
java-version: 8
- name: Run checkstyle
run: mvn -P lint --quiet --batch-mode checkstyle:check
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java
index 588e8e768..cf368f618 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java
@@ -36,7 +36,7 @@
* JDBC connection with a number of additional Cloud Spanner specific methods. JDBC connections that
* are returned by the Cloud Spanner {@link JdbcDriver} will implement this interface.
*
- * Calling {@link Connection#unwrap(Class)} with {@link CloudSpannerJdbcConnection#getClass()} as
+ *
Calling {@link Connection#unwrap(Class)} with {@code CloudSpannerJdbcConnection} class as
* input on a {@link Connection} returned by the Cloud Spanner JDBC Driver will return a {@link
* CloudSpannerJdbcConnection} instance.
*/
From acb2626a6d34f876da8e552cf98ef5a75c57b758 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Sun, 9 Jul 2023 05:55:18 +0200
Subject: [PATCH 026/173] deps: update dependency
com.google.cloud:google-cloud-shared-dependencies to v3.13.0 (#1278)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 9827c001d..9e467f4f9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,7 +69,7 @@
com.google.cloud
google-cloud-shared-dependencies
- 3.12.0
+ 3.13.0
pom
import
From cbf6eb47702d261f36271b25122aea4ceab4bddd Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Sun, 9 Jul 2023 05:55:41 +0200
Subject: [PATCH 027/173] chore(deps): update dependency
com.google.cloud:libraries-bom to v26.18.0 (#1277)
---
samples/snippets/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index fe2761c64..0d6ea2d4b 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -30,7 +30,7 @@
com.google.cloud
libraries-bom
- 26.17.0
+ 26.18.0
pom
import
From 2fe4e52d55bc44b1dca2cc945cb3b0f39cb9d38e Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Sun, 9 Jul 2023 05:20:13 +0000
Subject: [PATCH 028/173] chore(main): release 2.11.3 (#1279)
:robot: I have created a release *beep* *boop*
---
## [2.11.3](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.11.2...v2.11.3) (2023-07-09)
### Dependencies
* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.13.0 ([#1278](https://togithub.com/googleapis/java-spanner-jdbc/issues/1278)) ([acb2626](https://togithub.com/googleapis/java-spanner-jdbc/commit/acb2626a6d34f876da8e552cf98ef5a75c57b758))
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
CHANGELOG.md | 7 +++++++
pom.xml | 2 +-
samples/snapshot/pom.xml | 2 +-
samples/snippets/pom.xml | 2 +-
versions.txt | 2 +-
5 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ff5ec7274..83a4d2f1d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog
+## [2.11.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.2...v2.11.3) (2023-07-09)
+
+
+### Dependencies
+
+* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.13.0 ([#1278](https://github.com/googleapis/java-spanner-jdbc/issues/1278)) ([acb2626](https://github.com/googleapis/java-spanner-jdbc/commit/acb2626a6d34f876da8e552cf98ef5a75c57b758))
+
## [2.11.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.1...v2.11.2) (2023-06-26)
diff --git a/pom.xml b/pom.xml
index 9e467f4f9..b676d22d3 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.11.3-SNAPSHOT
+ 2.11.3
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 8c6952781..ffe49a773 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.3-SNAPSHOT
+ 2.11.3
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index 0d6ea2d4b..fe2761c64 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -30,7 +30,7 @@
com.google.cloud
libraries-bom
- 26.18.0
+ 26.17.0
pom
import
diff --git a/versions.txt b/versions.txt
index 0ba2d4e46..acd558c67 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.2:2.11.3-SNAPSHOT
+google-cloud-spanner-jdbc:2.11.3:2.11.3
From 6eef86bdfdb0354a050b4e9504a1cbd8a1d38464 Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Sun, 9 Jul 2023 06:46:39 +0000
Subject: [PATCH 029/173] chore(main): release 2.11.4-SNAPSHOT (#1281)
:robot: I have created a release *beep* *boop*
---
### Updating meta-information for bleeding-edge SNAPSHOT release.
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
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 b676d22d3..b83d2d1d7 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.11.3
+ 2.11.4-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 ffe49a773..822a348ad 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.3
+ 2.11.4-SNAPSHOT
diff --git a/versions.txt b/versions.txt
index acd558c67..b6f4fdd38 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.3:2.11.3
+google-cloud-spanner-jdbc:2.11.3:2.11.4-SNAPSHOT
From 8572e5cc8b9291872f45f5bbf4441cc0e4357a25 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Tue, 11 Jul 2023 22:43:54 +0200
Subject: [PATCH 030/173] chore(deps): update dependency
com.google.cloud:google-cloud-spanner-jdbc to v2.11.3 (#1282)
---
samples/install-without-bom/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 1ef1d77c7..6fc24a99b 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.11.2
+ 2.11.3
From c694c32aa3f20c2ac3fac23c014e6b15919b1c4c Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Tue, 11 Jul 2023 22:44:35 +0200
Subject: [PATCH 031/173] chore(deps): update dependency
com.google.cloud:libraries-bom to v26.18.0 (#1280)
---
samples/snippets/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index fe2761c64..0d6ea2d4b 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -30,7 +30,7 @@
com.google.cloud
libraries-bom
- 26.17.0
+ 26.18.0
pom
import
From 5d7c3a55a3b37d7268222672fe21a75d019512fb Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Wed, 12 Jul 2023 08:08:31 +0200
Subject: [PATCH 032/173] deps: update dependency
com.google.cloud:google-cloud-spanner-bom to v6.43.2 (#1284)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index b83d2d1d7..133992aa1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,7 @@
com.google.cloud
google-cloud-spanner-bom
- 6.43.1
+ 6.43.2
pom
import
From 532c576b1b976885dfcbd7152e8d94c0eaecf0cf Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Wed, 12 Jul 2023 07:32:13 +0000
Subject: [PATCH 033/173] chore(main): release 2.11.4 (#1285)
:robot: I have created a release *beep* *boop*
---
## [2.11.4](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.11.3...v2.11.4) (2023-07-12)
### Dependencies
* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.43.2 ([#1284](https://togithub.com/googleapis/java-spanner-jdbc/issues/1284)) ([5d7c3a5](https://togithub.com/googleapis/java-spanner-jdbc/commit/5d7c3a55a3b37d7268222672fe21a75d019512fb))
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
CHANGELOG.md | 7 +++++++
pom.xml | 2 +-
samples/snapshot/pom.xml | 2 +-
versions.txt | 2 +-
4 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 83a4d2f1d..afaa6625d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog
+## [2.11.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.3...v2.11.4) (2023-07-12)
+
+
+### Dependencies
+
+* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.43.2 ([#1284](https://github.com/googleapis/java-spanner-jdbc/issues/1284)) ([5d7c3a5](https://github.com/googleapis/java-spanner-jdbc/commit/5d7c3a55a3b37d7268222672fe21a75d019512fb))
+
## [2.11.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.2...v2.11.3) (2023-07-09)
diff --git a/pom.xml b/pom.xml
index 133992aa1..7c00c29c2 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.11.4-SNAPSHOT
+ 2.11.4
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 822a348ad..9fc70aace 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.4-SNAPSHOT
+ 2.11.4
diff --git a/versions.txt b/versions.txt
index b6f4fdd38..e1aefccd3 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.3:2.11.4-SNAPSHOT
+google-cloud-spanner-jdbc:2.11.4:2.11.4
From f2f2db6d5859f919405d078fcfa881f0e0d4e27c Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Wed, 12 Jul 2023 09:00:23 +0000
Subject: [PATCH 034/173] chore(main): release 2.11.5-SNAPSHOT (#1286)
:robot: I have created a release *beep* *boop*
---
### Updating meta-information for bleeding-edge SNAPSHOT release.
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
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 7c00c29c2..0960a2c62 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.11.4
+ 2.11.5-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 9fc70aace..a107a1997 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.4
+ 2.11.5-SNAPSHOT
diff --git a/versions.txt b/versions.txt
index e1aefccd3..66cc4b7e4 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.4:2.11.4
+google-cloud-spanner-jdbc:2.11.4:2.11.5-SNAPSHOT
From 581a39cb86636a23a404b9d90a26607f8dbd2df6 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Mon, 17 Jul 2023 06:50:09 +0200
Subject: [PATCH 035/173] chore(deps): update dependency
com.google.cloud:google-cloud-spanner-jdbc to v2.11.4 (#1287)
---
samples/install-without-bom/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 6fc24a99b..756be62c1 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.11.3
+ 2.11.4
From 83d9fc955e0e60422e7b9b699fb7a3ca0f965323 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Wed, 26 Jul 2023 17:14:35 +0200
Subject: [PATCH 036/173] chore(deps): update dependency
com.google.cloud:libraries-bom to v26.19.0 (#1289)
---
samples/snippets/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index 0d6ea2d4b..69f126379 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -30,7 +30,7 @@
com.google.cloud
libraries-bom
- 26.18.0
+ 26.19.0
pom
import
From b4b05014884c1ba97e294a04f441d4c107788053 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Wed, 26 Jul 2023 17:14:55 +0200
Subject: [PATCH 037/173] build(deps): update dependency
com.google.cloud:google-cloud-shared-config to v1.5.7 (#1290)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 0960a2c62..0d2399a26 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,7 +14,7 @@
com.google.cloud
google-cloud-shared-config
- 1.5.6
+ 1.5.7
From 6ec48c037e94a7e0a54f8c24583d33c304c8a68c Mon Sep 17 00:00:00 2001
From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com>
Date: Wed, 26 Jul 2023 20:47:09 +0530
Subject: [PATCH 038/173] chore: update requirements.txt to address dependabot
security alerts (#1829) (#1292)
* chore: update dependencies in requirements.txt to address dependabot security alerts
* update dependencies within gcp/templates
---------
Source-Link: https://github.com/googleapis/synthtool/commit/af76aa51249c5f6d8efb66e8ac390ec651f9f2f6
Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:46d2d262cd285c638656c8bde468011b723dc0c7ffd6a5ecc2650fe639c82e8f
Co-authored-by: Owl Bot
Co-authored-by: Anthonios Partheniou
---
.github/.OwlBot.lock.yaml | 4 +-
.kokoro/requirements.txt | 573 ++++++++++++++++++++++----------------
2 files changed, 332 insertions(+), 245 deletions(-)
diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml
index 258389d1a..d5500ef44 100644
--- a/.github/.OwlBot.lock.yaml
+++ b/.github/.OwlBot.lock.yaml
@@ -13,5 +13,5 @@
# limitations under the License.
docker:
image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest
- digest: sha256:31c8276a1bfb43766597d32645721c029cb94571f1b8d996cb2c290744fe52f9
-# created: 2023-06-27T18:51:58.922150125Z
+ digest: sha256:46d2d262cd285c638656c8bde468011b723dc0c7ffd6a5ecc2650fe639c82e8f
+# created: 2023-07-24T14:21:17.707234503Z
diff --git a/.kokoro/requirements.txt b/.kokoro/requirements.txt
index c80f0a87c..32989051e 100644
--- a/.kokoro/requirements.txt
+++ b/.kokoro/requirements.txt
@@ -1,20 +1,20 @@
#
-# This file is autogenerated by pip-compile with Python 3.11
+# This file is autogenerated by pip-compile with Python 3.9
# by the following command:
#
-# pip-compile --allow-unsafe --generate-hashes requirements.in
+# pip-compile requirements.in --generate-hashes --upgrade
#
-attrs==22.1.0 \
- --hash=sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6 \
- --hash=sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c
+attrs==23.1.0 \
+ --hash=sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04 \
+ --hash=sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015
# via gcp-releasetool
-cachetools==4.2.4 \
- --hash=sha256:89ea6f1b638d5a73a4f9226be57ac5e4f399d22770b92355f92dcb0f7f001693 \
- --hash=sha256:92971d3cb7d2a97efff7c7bb1657f21a8f5fb309a37530537c71b1774189f2d1
+cachetools==5.3.1 \
+ --hash=sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590 \
+ --hash=sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b
# via google-auth
-certifi==2022.12.7 \
- --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \
- --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18
+certifi==2023.5.7 \
+ --hash=sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7 \
+ --hash=sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716
# via requests
cffi==1.15.1 \
--hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \
@@ -82,9 +82,82 @@ cffi==1.15.1 \
--hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \
--hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0
# via cryptography
-charset-normalizer==2.0.12 \
- --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 \
- --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df
+charset-normalizer==3.2.0 \
+ --hash=sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96 \
+ --hash=sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c \
+ --hash=sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710 \
+ --hash=sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706 \
+ --hash=sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020 \
+ --hash=sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252 \
+ --hash=sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad \
+ --hash=sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329 \
+ --hash=sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a \
+ --hash=sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f \
+ --hash=sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6 \
+ --hash=sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4 \
+ --hash=sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a \
+ --hash=sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46 \
+ --hash=sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2 \
+ --hash=sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23 \
+ --hash=sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace \
+ --hash=sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd \
+ --hash=sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982 \
+ --hash=sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10 \
+ --hash=sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2 \
+ --hash=sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea \
+ --hash=sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09 \
+ --hash=sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5 \
+ --hash=sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149 \
+ --hash=sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489 \
+ --hash=sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9 \
+ --hash=sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80 \
+ --hash=sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592 \
+ --hash=sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3 \
+ --hash=sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6 \
+ --hash=sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed \
+ --hash=sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c \
+ --hash=sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200 \
+ --hash=sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a \
+ --hash=sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e \
+ --hash=sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d \
+ --hash=sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6 \
+ --hash=sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623 \
+ --hash=sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669 \
+ --hash=sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3 \
+ --hash=sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa \
+ --hash=sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9 \
+ --hash=sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2 \
+ --hash=sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f \
+ --hash=sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1 \
+ --hash=sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4 \
+ --hash=sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a \
+ --hash=sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8 \
+ --hash=sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3 \
+ --hash=sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029 \
+ --hash=sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f \
+ --hash=sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959 \
+ --hash=sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22 \
+ --hash=sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7 \
+ --hash=sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952 \
+ --hash=sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346 \
+ --hash=sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e \
+ --hash=sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d \
+ --hash=sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299 \
+ --hash=sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd \
+ --hash=sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a \
+ --hash=sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3 \
+ --hash=sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037 \
+ --hash=sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94 \
+ --hash=sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c \
+ --hash=sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858 \
+ --hash=sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a \
+ --hash=sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449 \
+ --hash=sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c \
+ --hash=sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918 \
+ --hash=sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1 \
+ --hash=sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c \
+ --hash=sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac \
+ --hash=sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa
# via requests
click==8.0.4 \
--hash=sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1 \
@@ -97,121 +170,152 @@ colorlog==6.7.0 \
--hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \
--hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5
# via gcp-docuploader
-cryptography==39.0.1 \
- --hash=sha256:0f8da300b5c8af9f98111ffd512910bc792b4c77392a9523624680f7956a99d4 \
- --hash=sha256:35f7c7d015d474f4011e859e93e789c87d21f6f4880ebdc29896a60403328f1f \
- --hash=sha256:5aa67414fcdfa22cf052e640cb5ddc461924a045cacf325cd164e65312d99502 \
- --hash=sha256:5d2d8b87a490bfcd407ed9d49093793d0f75198a35e6eb1a923ce1ee86c62b41 \
- --hash=sha256:6687ef6d0a6497e2b58e7c5b852b53f62142cfa7cd1555795758934da363a965 \
- --hash=sha256:6f8ba7f0328b79f08bdacc3e4e66fb4d7aab0c3584e0bd41328dce5262e26b2e \
- --hash=sha256:706843b48f9a3f9b9911979761c91541e3d90db1ca905fd63fee540a217698bc \
- --hash=sha256:807ce09d4434881ca3a7594733669bd834f5b2c6d5c7e36f8c00f691887042ad \
- --hash=sha256:83e17b26de248c33f3acffb922748151d71827d6021d98c70e6c1a25ddd78505 \
- --hash=sha256:96f1157a7c08b5b189b16b47bc9db2332269d6680a196341bf30046330d15388 \
- --hash=sha256:aec5a6c9864be7df2240c382740fcf3b96928c46604eaa7f3091f58b878c0bb6 \
- --hash=sha256:b0afd054cd42f3d213bf82c629efb1ee5f22eba35bf0eec88ea9ea7304f511a2 \
- --hash=sha256:ced4e447ae29ca194449a3f1ce132ded8fcab06971ef5f618605aacaa612beac \
- --hash=sha256:d1f6198ee6d9148405e49887803907fe8962a23e6c6f83ea7d98f1c0de375695 \
- --hash=sha256:e124352fd3db36a9d4a21c1aa27fd5d051e621845cb87fb851c08f4f75ce8be6 \
- --hash=sha256:e422abdec8b5fa8462aa016786680720d78bdce7a30c652b7fadf83a4ba35336 \
- --hash=sha256:ef8b72fa70b348724ff1218267e7f7375b8de4e8194d1636ee60510aae104cd0 \
- --hash=sha256:f0c64d1bd842ca2633e74a1a28033d139368ad959872533b1bab8c80e8240a0c \
- --hash=sha256:f24077a3b5298a5a06a8e0536e3ea9ec60e4c7ac486755e5fb6e6ea9b3500106 \
- --hash=sha256:fdd188c8a6ef8769f148f88f859884507b954cc64db6b52f66ef199bb9ad660a \
- --hash=sha256:fe913f20024eb2cb2f323e42a64bdf2911bb9738a15dba7d3cce48151034e3a8
+cryptography==41.0.2 \
+ --hash=sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711 \
+ --hash=sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7 \
+ --hash=sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd \
+ --hash=sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e \
+ --hash=sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58 \
+ --hash=sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0 \
+ --hash=sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d \
+ --hash=sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83 \
+ --hash=sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831 \
+ --hash=sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766 \
+ --hash=sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b \
+ --hash=sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c \
+ --hash=sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182 \
+ --hash=sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f \
+ --hash=sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa \
+ --hash=sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4 \
+ --hash=sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a \
+ --hash=sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2 \
+ --hash=sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76 \
+ --hash=sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5 \
+ --hash=sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee \
+ --hash=sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f \
+ --hash=sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14
# via
# gcp-releasetool
# secretstorage
-gcp-docuploader==0.6.4 \
- --hash=sha256:01486419e24633af78fd0167db74a2763974765ee8078ca6eb6964d0ebd388af \
- --hash=sha256:70861190c123d907b3b067da896265ead2eeb9263969d6955c9e0bb091b5ccbf
+gcp-docuploader==0.6.5 \
+ --hash=sha256:30221d4ac3e5a2b9c69aa52fdbef68cc3f27d0e6d0d90e220fc024584b8d2318 \
+ --hash=sha256:b7458ef93f605b9d46a4bf3a8dc1755dad1f31d030c8679edf304e343b347eea
# via -r requirements.in
-gcp-releasetool==1.10.5 \
- --hash=sha256:174b7b102d704b254f2a26a3eda2c684fd3543320ec239baf771542a2e58e109 \
- --hash=sha256:e29d29927fe2ca493105a82958c6873bb2b90d503acac56be2c229e74de0eec9
+gcp-releasetool==1.16.0 \
+ --hash=sha256:27bf19d2e87aaa884096ff941aa3c592c482be3d6a2bfe6f06afafa6af2353e3 \
+ --hash=sha256:a316b197a543fd036209d0caba7a8eb4d236d8e65381c80cbc6d7efaa7606d63
# via -r requirements.in
-google-api-core==2.8.2 \
- --hash=sha256:06f7244c640322b508b125903bb5701bebabce8832f85aba9335ec00b3d02edc \
- --hash=sha256:93c6a91ccac79079ac6bbf8b74ee75db970cc899278b97d53bc012f35908cf50
+google-api-core==2.11.1 \
+ --hash=sha256:25d29e05a0058ed5f19c61c0a78b1b53adea4d9364b464d014fbda941f6d1c9a \
+ --hash=sha256:d92a5a92dc36dd4f4b9ee4e55528a90e432b059f93aee6ad857f9de8cc7ae94a
# via
# google-cloud-core
# google-cloud-storage
-google-auth==2.14.1 \
- --hash=sha256:ccaa901f31ad5cbb562615eb8b664b3dd0bf5404a67618e642307f00613eda4d \
- --hash=sha256:f5d8701633bebc12e0deea4df8abd8aff31c28b355360597f7f2ee60f2e4d016
+google-auth==2.22.0 \
+ --hash=sha256:164cba9af4e6e4e40c3a4f90a1a6c12ee56f14c0b4868d1ca91b32826ab334ce \
+ --hash=sha256:d61d1b40897407b574da67da1a833bdc10d5a11642566e506565d1b1a46ba873
# via
# gcp-releasetool
# google-api-core
# google-cloud-core
# google-cloud-storage
-google-cloud-core==2.3.1 \
- --hash=sha256:113ba4f492467d5bd442c8d724c1a25ad7384045c3178369038840ecdd19346c \
- --hash=sha256:34334359cb04187bdc80ddcf613e462dfd7a3aabbc3fe4d118517ab4b9303d53
+google-cloud-core==2.3.3 \
+ --hash=sha256:37b80273c8d7eee1ae816b3a20ae43585ea50506cb0e60f3cf5be5f87f1373cb \
+ --hash=sha256:fbd11cad3e98a7e5b0343dc07cb1039a5ffd7a5bb96e1f1e27cee4bda4a90863
# via google-cloud-storage
-google-cloud-storage==2.0.0 \
- --hash=sha256:a57a15aead0f9dfbd4381f1bfdbe8bf89818a4bd75bab846cafcefb2db846c47 \
- --hash=sha256:ec4be60bb223a3a960f0d01697d849b86d91cad815a84915a32ed3635e93a5e7
+google-cloud-storage==2.10.0 \
+ --hash=sha256:934b31ead5f3994e5360f9ff5750982c5b6b11604dc072bc452c25965e076dc7 \
+ --hash=sha256:9433cf28801671de1c80434238fb1e7e4a1ba3087470e90f70c928ea77c2b9d7
# via gcp-docuploader
-google-crc32c==1.3.0 \
- --hash=sha256:04e7c220798a72fd0f08242bc8d7a05986b2a08a0573396187fd32c1dcdd58b3 \
- --hash=sha256:05340b60bf05b574159e9bd940152a47d38af3fb43803ffe71f11d704b7696a6 \
- --hash=sha256:12674a4c3b56b706153a358eaa1018c4137a5a04635b92b4652440d3d7386206 \
- --hash=sha256:127f9cc3ac41b6a859bd9dc4321097b1a4f6aa7fdf71b4f9227b9e3ebffb4422 \
- --hash=sha256:13af315c3a0eec8bb8b8d80b8b128cb3fcd17d7e4edafc39647846345a3f003a \
- --hash=sha256:1926fd8de0acb9d15ee757175ce7242e235482a783cd4ec711cc999fc103c24e \
- --hash=sha256:226f2f9b8e128a6ca6a9af9b9e8384f7b53a801907425c9a292553a3a7218ce0 \
- --hash=sha256:276de6273eb074a35bc598f8efbc00c7869c5cf2e29c90748fccc8c898c244df \
- --hash=sha256:318f73f5484b5671f0c7f5f63741ab020a599504ed81d209b5c7129ee4667407 \
- --hash=sha256:3bbce1be3687bbfebe29abdb7631b83e6b25da3f4e1856a1611eb21854b689ea \
- --hash=sha256:42ae4781333e331a1743445931b08ebdad73e188fd554259e772556fc4937c48 \
- --hash=sha256:58be56ae0529c664cc04a9c76e68bb92b091e0194d6e3c50bea7e0f266f73713 \
- --hash=sha256:5da2c81575cc3ccf05d9830f9e8d3c70954819ca9a63828210498c0774fda1a3 \
- --hash=sha256:6311853aa2bba4064d0c28ca54e7b50c4d48e3de04f6770f6c60ebda1e975267 \
- --hash=sha256:650e2917660e696041ab3dcd7abac160b4121cd9a484c08406f24c5964099829 \
- --hash=sha256:6a4db36f9721fdf391646685ecffa404eb986cbe007a3289499020daf72e88a2 \
- --hash=sha256:779cbf1ce375b96111db98fca913c1f5ec11b1d870e529b1dc7354b2681a8c3a \
- --hash=sha256:7f6fe42536d9dcd3e2ffb9d3053f5d05221ae3bbcefbe472bdf2c71c793e3183 \
- --hash=sha256:891f712ce54e0d631370e1f4997b3f182f3368179198efc30d477c75d1f44942 \
- --hash=sha256:95c68a4b9b7828ba0428f8f7e3109c5d476ca44996ed9a5f8aac6269296e2d59 \
- --hash=sha256:96a8918a78d5d64e07c8ea4ed2bc44354e3f93f46a4866a40e8db934e4c0d74b \
- --hash=sha256:9c3cf890c3c0ecfe1510a452a165431b5831e24160c5fcf2071f0f85ca5a47cd \
- --hash=sha256:9f58099ad7affc0754ae42e6d87443299f15d739b0ce03c76f515153a5cda06c \
- --hash=sha256:a0b9e622c3b2b8d0ce32f77eba617ab0d6768b82836391e4f8f9e2074582bf02 \
- --hash=sha256:a7f9cbea4245ee36190f85fe1814e2d7b1e5f2186381b082f5d59f99b7f11328 \
- --hash=sha256:bab4aebd525218bab4ee615786c4581952eadc16b1ff031813a2fd51f0cc7b08 \
- --hash=sha256:c124b8c8779bf2d35d9b721e52d4adb41c9bfbde45e6a3f25f0820caa9aba73f \
- --hash=sha256:c9da0a39b53d2fab3e5467329ed50e951eb91386e9d0d5b12daf593973c3b168 \
- --hash=sha256:ca60076c388728d3b6ac3846842474f4250c91efbfe5afa872d3ffd69dd4b318 \
- --hash=sha256:cb6994fff247987c66a8a4e550ef374671c2b82e3c0d2115e689d21e511a652d \
- --hash=sha256:d1c1d6236feab51200272d79b3d3e0f12cf2cbb12b208c835b175a21efdb0a73 \
- --hash=sha256:dd7760a88a8d3d705ff562aa93f8445ead54f58fd482e4f9e2bafb7e177375d4 \
- --hash=sha256:dda4d8a3bb0b50f540f6ff4b6033f3a74e8bf0bd5320b70fab2c03e512a62812 \
- --hash=sha256:e0f1ff55dde0ebcfbef027edc21f71c205845585fffe30d4ec4979416613e9b3 \
- --hash=sha256:e7a539b9be7b9c00f11ef16b55486141bc2cdb0c54762f84e3c6fc091917436d \
- --hash=sha256:eb0b14523758e37802f27b7f8cd973f5f3d33be7613952c0df904b68c4842f0e \
- --hash=sha256:ed447680ff21c14aaceb6a9f99a5f639f583ccfe4ce1a5e1d48eb41c3d6b3217 \
- --hash=sha256:f52a4ad2568314ee713715b1e2d79ab55fab11e8b304fd1462ff5cccf4264b3e \
- --hash=sha256:fbd60c6aaa07c31d7754edbc2334aef50601b7f1ada67a96eb1eb57c7c72378f \
- --hash=sha256:fc28e0db232c62ca0c3600884933178f0825c99be4474cdd645e378a10588125 \
- --hash=sha256:fe31de3002e7b08eb20823b3735b97c86c5926dd0581c7710a680b418a8709d4 \
- --hash=sha256:fec221a051150eeddfdfcff162e6db92c65ecf46cb0f7bb1bf812a1520ec026b \
- --hash=sha256:ff71073ebf0e42258a42a0b34f2c09ec384977e7f6808999102eedd5b49920e3
+google-crc32c==1.5.0 \
+ --hash=sha256:024894d9d3cfbc5943f8f230e23950cd4906b2fe004c72e29b209420a1e6b05a \
+ --hash=sha256:02c65b9817512edc6a4ae7c7e987fea799d2e0ee40c53ec573a692bee24de876 \
+ --hash=sha256:02ebb8bf46c13e36998aeaad1de9b48f4caf545e91d14041270d9dca767b780c \
+ --hash=sha256:07eb3c611ce363c51a933bf6bd7f8e3878a51d124acfc89452a75120bc436289 \
+ --hash=sha256:1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 \
+ --hash=sha256:116a7c3c616dd14a3de8c64a965828b197e5f2d121fedd2f8c5585c547e87b02 \
+ --hash=sha256:19e0a019d2c4dcc5e598cd4a4bc7b008546b0358bd322537c74ad47a5386884f \
+ --hash=sha256:1c7abdac90433b09bad6c43a43af253e688c9cfc1c86d332aed13f9a7c7f65e2 \
+ --hash=sha256:1e986b206dae4476f41bcec1faa057851f3889503a70e1bdb2378d406223994a \
+ --hash=sha256:272d3892a1e1a2dbc39cc5cde96834c236d5327e2122d3aaa19f6614531bb6eb \
+ --hash=sha256:278d2ed7c16cfc075c91378c4f47924c0625f5fc84b2d50d921b18b7975bd210 \
+ --hash=sha256:2ad40e31093a4af319dadf503b2467ccdc8f67c72e4bcba97f8c10cb078207b5 \
+ --hash=sha256:2e920d506ec85eb4ba50cd4228c2bec05642894d4c73c59b3a2fe20346bd00ee \
+ --hash=sha256:3359fc442a743e870f4588fcf5dcbc1bf929df1fad8fb9905cd94e5edb02e84c \
+ --hash=sha256:37933ec6e693e51a5b07505bd05de57eee12f3e8c32b07da7e73669398e6630a \
+ --hash=sha256:398af5e3ba9cf768787eef45c803ff9614cc3e22a5b2f7d7ae116df8b11e3314 \
+ --hash=sha256:3b747a674c20a67343cb61d43fdd9207ce5da6a99f629c6e2541aa0e89215bcd \
+ --hash=sha256:461665ff58895f508e2866824a47bdee72497b091c730071f2b7575d5762ab65 \
+ --hash=sha256:4c6fdd4fccbec90cc8a01fc00773fcd5fa28db683c116ee3cb35cd5da9ef6c37 \
+ --hash=sha256:5829b792bf5822fd0a6f6eb34c5f81dd074f01d570ed7f36aa101d6fc7a0a6e4 \
+ --hash=sha256:596d1f98fc70232fcb6590c439f43b350cb762fb5d61ce7b0e9db4539654cc13 \
+ --hash=sha256:5ae44e10a8e3407dbe138984f21e536583f2bba1be9491239f942c2464ac0894 \
+ --hash=sha256:635f5d4dd18758a1fbd1049a8e8d2fee4ffed124462d837d1a02a0e009c3ab31 \
+ --hash=sha256:64e52e2b3970bd891309c113b54cf0e4384762c934d5ae56e283f9a0afcd953e \
+ --hash=sha256:66741ef4ee08ea0b2cc3c86916ab66b6aef03768525627fd6a1b34968b4e3709 \
+ --hash=sha256:67b741654b851abafb7bc625b6d1cdd520a379074e64b6a128e3b688c3c04740 \
+ --hash=sha256:6ac08d24c1f16bd2bf5eca8eaf8304812f44af5cfe5062006ec676e7e1d50afc \
+ --hash=sha256:6f998db4e71b645350b9ac28a2167e6632c239963ca9da411523bb439c5c514d \
+ --hash=sha256:72218785ce41b9cfd2fc1d6a017dc1ff7acfc4c17d01053265c41a2c0cc39b8c \
+ --hash=sha256:74dea7751d98034887dbd821b7aae3e1d36eda111d6ca36c206c44478035709c \
+ --hash=sha256:759ce4851a4bb15ecabae28f4d2e18983c244eddd767f560165563bf9aefbc8d \
+ --hash=sha256:77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 \
+ --hash=sha256:7c074fece789b5034b9b1404a1f8208fc2d4c6ce9decdd16e8220c5a793e6f61 \
+ --hash=sha256:7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 \
+ --hash=sha256:7f57f14606cd1dd0f0de396e1e53824c371e9544a822648cd76c034d209b559c \
+ --hash=sha256:83c681c526a3439b5cf94f7420471705bbf96262f49a6fe546a6db5f687a3d4a \
+ --hash=sha256:8485b340a6a9e76c62a7dce3c98e5f102c9219f4cfbf896a00cf48caf078d438 \
+ --hash=sha256:84e6e8cd997930fc66d5bb4fde61e2b62ba19d62b7abd7a69920406f9ecca946 \
+ --hash=sha256:89284716bc6a5a415d4eaa11b1726d2d60a0cd12aadf5439828353662ede9dd7 \
+ --hash=sha256:8b87e1a59c38f275c0e3676fc2ab6d59eccecfd460be267ac360cc31f7bcde96 \
+ --hash=sha256:8f24ed114432de109aa9fd317278518a5af2d31ac2ea6b952b2f7782b43da091 \
+ --hash=sha256:98cb4d057f285bd80d8778ebc4fde6b4d509ac3f331758fb1528b733215443ae \
+ --hash=sha256:998679bf62b7fb599d2878aa3ed06b9ce688b8974893e7223c60db155f26bd8d \
+ --hash=sha256:9ba053c5f50430a3fcfd36f75aff9caeba0440b2d076afdb79a318d6ca245f88 \
+ --hash=sha256:9c99616c853bb585301df6de07ca2cadad344fd1ada6d62bb30aec05219c45d2 \
+ --hash=sha256:a1fd716e7a01f8e717490fbe2e431d2905ab8aa598b9b12f8d10abebb36b04dd \
+ --hash=sha256:a2355cba1f4ad8b6988a4ca3feed5bff33f6af2d7f134852cf279c2aebfde541 \
+ --hash=sha256:b1f8133c9a275df5613a451e73f36c2aea4fe13c5c8997e22cf355ebd7bd0728 \
+ --hash=sha256:b8667b48e7a7ef66afba2c81e1094ef526388d35b873966d8a9a447974ed9178 \
+ --hash=sha256:ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 \
+ --hash=sha256:be82c3c8cfb15b30f36768797a640e800513793d6ae1724aaaafe5bf86f8f346 \
+ --hash=sha256:c02ec1c5856179f171e032a31d6f8bf84e5a75c45c33b2e20a3de353b266ebd8 \
+ --hash=sha256:c672d99a345849301784604bfeaeba4db0c7aae50b95be04dd651fd2a7310b93 \
+ --hash=sha256:c6c777a480337ac14f38564ac88ae82d4cd238bf293f0a22295b66eb89ffced7 \
+ --hash=sha256:cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 \
+ --hash=sha256:cd67cf24a553339d5062eff51013780a00d6f97a39ca062781d06b3a73b15462 \
+ --hash=sha256:d3515f198eaa2f0ed49f8819d5732d70698c3fa37384146079b3799b97667a94 \
+ --hash=sha256:d5280312b9af0976231f9e317c20e4a61cd2f9629b7bfea6a693d1878a264ebd \
+ --hash=sha256:de06adc872bcd8c2a4e0dc51250e9e65ef2ca91be023b9d13ebd67c2ba552e1e \
+ --hash=sha256:e1674e4307fa3024fc897ca774e9c7562c957af85df55efe2988ed9056dc4e57 \
+ --hash=sha256:e2096eddb4e7c7bdae4bd69ad364e55e07b8316653234a56552d9c988bd2d61b \
+ --hash=sha256:e560628513ed34759456a416bf86b54b2476c59144a9138165c9a1575801d0d9 \
+ --hash=sha256:edfedb64740750e1a3b16152620220f51d58ff1b4abceb339ca92e934775c27a \
+ --hash=sha256:f13cae8cc389a440def0c8c52057f37359014ccbc9dc1f0827936bcd367c6100 \
+ --hash=sha256:f314013e7dcd5cf45ab1945d92e713eec788166262ae8deb2cfacd53def27325 \
+ --hash=sha256:f583edb943cf2e09c60441b910d6a20b4d9d626c75a36c8fcac01a6c96c01183 \
+ --hash=sha256:fd8536e902db7e365f49e7d9029283403974ccf29b13fc7028b97e2295b33556 \
+ --hash=sha256:fe70e325aa68fa4b5edf7d1a4b6f691eb04bbccac0ace68e34820d283b5f80d4
# via google-resumable-media
-google-resumable-media==2.3.3 \
- --hash=sha256:27c52620bd364d1c8116eaac4ea2afcbfb81ae9139fb3199652fcac1724bfb6c \
- --hash=sha256:5b52774ea7a829a8cdaa8bd2d4c3d4bc660c91b30857ab2668d0eb830f4ea8c5
+google-resumable-media==2.5.0 \
+ --hash=sha256:218931e8e2b2a73a58eb354a288e03a0fd5fb1c4583261ac6e4c078666468c93 \
+ --hash=sha256:da1bd943e2e114a56d85d6848497ebf9be6a14d3db23e9fc57581e7c3e8170ec
# via google-cloud-storage
-googleapis-common-protos==1.56.3 \
- --hash=sha256:6f1369b58ed6cf3a4b7054a44ebe8d03b29c309257583a2bbdc064cd1e4a1442 \
- --hash=sha256:87955d7b3a73e6e803f2572a33179de23989ebba725e05ea42f24838b792e461
+googleapis-common-protos==1.59.1 \
+ --hash=sha256:0cbedb6fb68f1c07e18eb4c48256320777707e7d0c55063ae56c15db3224a61e \
+ --hash=sha256:b35d530fe825fb4227857bc47ad84c33c809ac96f312e13182bdeaa2abe1178a
# via google-api-core
idna==3.4 \
--hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \
--hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
# via requests
-importlib-metadata==4.8.3 \
- --hash=sha256:65a9576a5b2d58ca44d133c42a241905cc45e34d2c06fd5ba2bafa221e5d7b5e \
- --hash=sha256:766abffff765960fcc18003801f7044eb6755ffae4521c8e8ce8e83b9c9b0668
+importlib-metadata==6.8.0 \
+ --hash=sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb \
+ --hash=sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743
+ # via keyring
+jaraco-classes==3.3.0 \
+ --hash=sha256:10afa92b6743f25c0cf5f37c6bb6e18e2c5bb84a16527ccfc0040ea377e7aaeb \
+ --hash=sha256:c063dd08e89217cee02c8d5e5ec560f2c8ce6cdc2fcdc2e68f7b2e5547ed3621
# via keyring
jeepney==0.8.0 \
--hash=sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806 \
@@ -219,139 +323,119 @@ jeepney==0.8.0 \
# via
# keyring
# secretstorage
-jinja2==3.0.3 \
- --hash=sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8 \
- --hash=sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7
+jinja2==3.1.2 \
+ --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \
+ --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61
# via gcp-releasetool
-keyring==23.4.1 \
- --hash=sha256:17e49fb0d6883c2b4445359434dba95aad84aabb29bbff044ad0ed7100232eca \
- --hash=sha256:89cbd74d4683ed164c8082fb38619341097741323b3786905c6dac04d6915a55
+keyring==24.2.0 \
+ --hash=sha256:4901caaf597bfd3bbd78c9a0c7c4c29fcd8310dab2cffefe749e916b6527acd6 \
+ --hash=sha256:ca0746a19ec421219f4d713f848fa297a661a8a8c1504867e55bfb5e09091509
# via gcp-releasetool
-markupsafe==2.0.1 \
- --hash=sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298 \
- --hash=sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64 \
- --hash=sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b \
- --hash=sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194 \
- --hash=sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567 \
- --hash=sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff \
- --hash=sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724 \
- --hash=sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74 \
- --hash=sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646 \
- --hash=sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35 \
- --hash=sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6 \
- --hash=sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a \
- --hash=sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6 \
- --hash=sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad \
- --hash=sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26 \
- --hash=sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38 \
- --hash=sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac \
- --hash=sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7 \
- --hash=sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6 \
- --hash=sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047 \
- --hash=sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75 \
- --hash=sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f \
- --hash=sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b \
- --hash=sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135 \
- --hash=sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8 \
- --hash=sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a \
- --hash=sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a \
- --hash=sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1 \
- --hash=sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9 \
- --hash=sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864 \
- --hash=sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914 \
- --hash=sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee \
- --hash=sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f \
- --hash=sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18 \
- --hash=sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8 \
- --hash=sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2 \
- --hash=sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d \
- --hash=sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b \
- --hash=sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b \
- --hash=sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86 \
- --hash=sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6 \
- --hash=sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f \
- --hash=sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb \
- --hash=sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833 \
- --hash=sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28 \
- --hash=sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e \
- --hash=sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415 \
- --hash=sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902 \
- --hash=sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f \
- --hash=sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d \
- --hash=sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9 \
- --hash=sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d \
- --hash=sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145 \
- --hash=sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066 \
- --hash=sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c \
- --hash=sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1 \
- --hash=sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a \
- --hash=sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207 \
- --hash=sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f \
- --hash=sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53 \
- --hash=sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd \
- --hash=sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134 \
- --hash=sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85 \
- --hash=sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9 \
- --hash=sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5 \
- --hash=sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94 \
- --hash=sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509 \
- --hash=sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51 \
- --hash=sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872
+markupsafe==2.1.3 \
+ --hash=sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e \
+ --hash=sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e \
+ --hash=sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431 \
+ --hash=sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686 \
+ --hash=sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559 \
+ --hash=sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc \
+ --hash=sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c \
+ --hash=sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0 \
+ --hash=sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4 \
+ --hash=sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9 \
+ --hash=sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575 \
+ --hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba \
+ --hash=sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d \
+ --hash=sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3 \
+ --hash=sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00 \
+ --hash=sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155 \
+ --hash=sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac \
+ --hash=sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52 \
+ --hash=sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f \
+ --hash=sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8 \
+ --hash=sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b \
+ --hash=sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24 \
+ --hash=sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea \
+ --hash=sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198 \
+ --hash=sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0 \
+ --hash=sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee \
+ --hash=sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be \
+ --hash=sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2 \
+ --hash=sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707 \
+ --hash=sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6 \
+ --hash=sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58 \
+ --hash=sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779 \
+ --hash=sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636 \
+ --hash=sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c \
+ --hash=sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad \
+ --hash=sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee \
+ --hash=sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc \
+ --hash=sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2 \
+ --hash=sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48 \
+ --hash=sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7 \
+ --hash=sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e \
+ --hash=sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b \
+ --hash=sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa \
+ --hash=sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5 \
+ --hash=sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e \
+ --hash=sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb \
+ --hash=sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9 \
+ --hash=sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57 \
+ --hash=sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc \
+ --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2
# via jinja2
-packaging==21.3 \
- --hash=sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb \
- --hash=sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522
+more-itertools==9.1.0 \
+ --hash=sha256:cabaa341ad0389ea83c17a94566a53ae4c9d07349861ecb14dc6d0345cf9ac5d \
+ --hash=sha256:d2bc7f02446e86a68911e58ded76d6561eea00cddfb2a91e7019bbb586c799f3
+ # via jaraco-classes
+packaging==23.1 \
+ --hash=sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61 \
+ --hash=sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f
# via gcp-releasetool
-protobuf==3.20.2 \
- --hash=sha256:03d76b7bd42ac4a6e109742a4edf81ffe26ffd87c5993126d894fe48a120396a \
- --hash=sha256:09e25909c4297d71d97612f04f41cea8fa8510096864f2835ad2f3b3df5a5559 \
- --hash=sha256:18e34a10ae10d458b027d7638a599c964b030c1739ebd035a1dfc0e22baa3bfe \
- --hash=sha256:291fb4307094bf5ccc29f424b42268640e00d5240bf0d9b86bf3079f7576474d \
- --hash=sha256:2c0b040d0b5d5d207936ca2d02f00f765906622c07d3fa19c23a16a8ca71873f \
- --hash=sha256:384164994727f274cc34b8abd41a9e7e0562801361ee77437099ff6dfedd024b \
- --hash=sha256:3cb608e5a0eb61b8e00fe641d9f0282cd0eedb603be372f91f163cbfbca0ded0 \
- --hash=sha256:5d9402bf27d11e37801d1743eada54372f986a372ec9679673bfcc5c60441151 \
- --hash=sha256:712dca319eee507a1e7df3591e639a2b112a2f4a62d40fe7832a16fd19151750 \
- --hash=sha256:7a5037af4e76c975b88c3becdf53922b5ffa3f2cddf657574a4920a3b33b80f3 \
- --hash=sha256:8228e56a865c27163d5d1d1771d94b98194aa6917bcfb6ce139cbfa8e3c27334 \
- --hash=sha256:84a1544252a933ef07bb0b5ef13afe7c36232a774affa673fc3636f7cee1db6c \
- --hash=sha256:84fe5953b18a383fd4495d375fe16e1e55e0a3afe7b4f7b4d01a3a0649fcda9d \
- --hash=sha256:9c673c8bfdf52f903081816b9e0e612186684f4eb4c17eeb729133022d6032e3 \
- --hash=sha256:a9e5ae5a8e8985c67e8944c23035a0dff2c26b0f5070b2f55b217a1c33bbe8b1 \
- --hash=sha256:b4fdb29c5a7406e3f7ef176b2a7079baa68b5b854f364c21abe327bbeec01cdb \
- --hash=sha256:c184485e0dfba4dfd451c3bd348c2e685d6523543a0f91b9fd4ae90eb09e8422 \
- --hash=sha256:c9cdf251c582c16fd6a9f5e95836c90828d51b0069ad22f463761d27c6c19019 \
- --hash=sha256:e39cf61bb8582bda88cdfebc0db163b774e7e03364bbf9ce1ead13863e81e359 \
- --hash=sha256:e8fbc522303e09036c752a0afcc5c0603e917222d8bedc02813fd73b4b4ed804 \
- --hash=sha256:f34464ab1207114e73bba0794d1257c150a2b89b7a9faf504e00af7c9fd58978 \
- --hash=sha256:f52dabc96ca99ebd2169dadbe018824ebda08a795c7684a0b7d203a290f3adb0
+protobuf==3.20.3 \
+ --hash=sha256:03038ac1cfbc41aa21f6afcbcd357281d7521b4157926f30ebecc8d4ea59dcb7 \
+ --hash=sha256:28545383d61f55b57cf4df63eebd9827754fd2dc25f80c5253f9184235db242c \
+ --hash=sha256:2e3427429c9cffebf259491be0af70189607f365c2f41c7c3764af6f337105f2 \
+ --hash=sha256:398a9e0c3eaceb34ec1aee71894ca3299605fa8e761544934378bbc6c97de23b \
+ --hash=sha256:44246bab5dd4b7fbd3c0c80b6f16686808fab0e4aca819ade6e8d294a29c7050 \
+ --hash=sha256:447d43819997825d4e71bf5769d869b968ce96848b6479397e29fc24c4a5dfe9 \
+ --hash=sha256:67a3598f0a2dcbc58d02dd1928544e7d88f764b47d4a286202913f0b2801c2e7 \
+ --hash=sha256:74480f79a023f90dc6e18febbf7b8bac7508420f2006fabd512013c0c238f454 \
+ --hash=sha256:819559cafa1a373b7096a482b504ae8a857c89593cf3a25af743ac9ecbd23480 \
+ --hash=sha256:899dc660cd599d7352d6f10d83c95df430a38b410c1b66b407a6b29265d66469 \
+ --hash=sha256:8c0c984a1b8fef4086329ff8dd19ac77576b384079247c770f29cc8ce3afa06c \
+ --hash=sha256:9aae4406ea63d825636cc11ffb34ad3379335803216ee3a856787bcf5ccc751e \
+ --hash=sha256:a7ca6d488aa8ff7f329d4c545b2dbad8ac31464f1d8b1c87ad1346717731e4db \
+ --hash=sha256:b6cc7ba72a8850621bfec987cb72623e703b7fe2b9127a161ce61e61558ad905 \
+ --hash=sha256:bf01b5720be110540be4286e791db73f84a2b721072a3711efff6c324cdf074b \
+ --hash=sha256:c02ce36ec760252242a33967d51c289fd0e1c0e6e5cc9397e2279177716add86 \
+ --hash=sha256:d9e4432ff660d67d775c66ac42a67cf2453c27cb4d738fc22cb53b5d84c135d4 \
+ --hash=sha256:daa564862dd0d39c00f8086f88700fdbe8bc717e993a21e90711acfed02f2402 \
+ --hash=sha256:de78575669dddf6099a8a0f46a27e82a1783c557ccc38ee620ed8cc96d3be7d7 \
+ --hash=sha256:e64857f395505ebf3d2569935506ae0dfc4a15cb80dc25261176c784662cdcc4 \
+ --hash=sha256:f4bd856d702e5b0d96a00ec6b307b0f51c1982c2bf9c0052cf9019e9a544ba99 \
+ --hash=sha256:f4c42102bc82a51108e449cbb32b19b180022941c727bac0cfd50170341f16ee
# via
# gcp-docuploader
# gcp-releasetool
# google-api-core
- # google-cloud-storage
-pyasn1==0.4.8 \
- --hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \
- --hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba
+pyasn1==0.5.0 \
+ --hash=sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57 \
+ --hash=sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde
# via
# pyasn1-modules
# rsa
-pyasn1-modules==0.2.8 \
- --hash=sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e \
- --hash=sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74
+pyasn1-modules==0.3.0 \
+ --hash=sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c \
+ --hash=sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d
# via google-auth
pycparser==2.21 \
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
# via cffi
-pyjwt==2.4.0 \
- --hash=sha256:72d1d253f32dbd4f5c88eaf1fdc62f3a19f676ccbadb9dbc5d07e951b2b26daf \
- --hash=sha256:d42908208c699b3b973cbeb01a969ba6a96c821eefb1c5bfe4c390c01d67abba
+pyjwt==2.7.0 \
+ --hash=sha256:ba2b425b15ad5ef12f200dc67dd56af4e26de2331f965c5439994dad075876e1 \
+ --hash=sha256:bd6ca4a3c4285c1a2d4349e5a035fdf8fb94e04ccd0fcbe6ba289dae9cc3e074
# via gcp-releasetool
-pyparsing==3.0.9 \
- --hash=sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb \
- --hash=sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc
- # via packaging
pyperclip==1.8.2 \
--hash=sha256:105254a8b04934f0bc84e9c24eb360a591aaf6535c9def5f29d92af107a9bf57
# via gcp-releasetool
@@ -359,9 +443,9 @@ python-dateutil==2.8.2 \
--hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \
--hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9
# via gcp-releasetool
-requests==2.27.1 \
- --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 \
- --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d
+requests==2.31.0 \
+ --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \
+ --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1
# via
# gcp-releasetool
# google-api-core
@@ -374,10 +458,6 @@ secretstorage==3.3.3 \
--hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \
--hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99
# via keyring
-setuptools==67.3.2 \
- --hash=sha256:95f00380ef2ffa41d9bba85d95b27689d923c93dfbafed4aecd7cf988a25e012 \
- --hash=sha256:bb6d8e508de562768f2027902929f8523932fcd1fb784e6d573d2cafac995a48
- # via -r requirements.in
six==1.16.0 \
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
@@ -385,19 +465,26 @@ six==1.16.0 \
# gcp-docuploader
# google-auth
# python-dateutil
-typing-extensions==4.4.0 \
- --hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \
- --hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e
+typing-extensions==4.7.1 \
+ --hash=sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36 \
+ --hash=sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2
# via -r requirements.in
-urllib3==1.26.12 \
- --hash=sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e \
- --hash=sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997
- # via requests
-wheel==0.38.4 \
- --hash=sha256:965f5259b566725405b05e7cf774052044b1ed30119b5d586b2703aafe8719ac \
- --hash=sha256:b60533f3f5d530e971d6737ca6d58681ee434818fab630c83a734bb10c083ce8
+urllib3==1.26.16 \
+ --hash=sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f \
+ --hash=sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14
+ # via
+ # google-auth
+ # requests
+wheel==0.40.0 \
+ --hash=sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873 \
+ --hash=sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247
# via -r requirements.in
-zipp==3.6.0 \
- --hash=sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832 \
- --hash=sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc
+zipp==3.16.1 \
+ --hash=sha256:0b37c326d826d5ca35f2b9685cd750292740774ef16190008b00a0227c256fe0 \
+ --hash=sha256:857b158da2cbf427b376da1c24fd11faecbac5a4ac7523c3607f8a01f94c2ec0
# via importlib-metadata
+
+# WARNING: The following packages were not pinned, but pip requires them to be
+# pinned when the requirements file includes hashes and the requirement is not
+# satisfied by a package already installed. Consider using the --allow-unsafe flag.
+# setuptools
From d832b1fad785774a20badabd7462a639c04a83f1 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:38:14 +0000
Subject: [PATCH 039/173] build(deps): bump certifi from 2022.12.7 to 2023.7.22
in /.kokoro (#1293)
Bumps [certifi](https://togithub.com/certifi/python-certifi) from 2022.12.7 to 2023.7.22.
Commits
[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=certifi&package-manager=pip&previous-version=2022.12.7&new-version=2023.7.22)](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 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 aa40c60df7dcf7fbf45c4c942be2dc31130a3d6b Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Thu, 27 Jul 2023 10:56:46 +0200
Subject: [PATCH 040/173] deps: update dependency
com.google.cloud:google-cloud-shared-dependencies to v3.13.1 (#1291)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 0d2399a26..858e36e5e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,7 +69,7 @@
com.google.cloud
google-cloud-shared-dependencies
- 3.13.0
+ 3.13.1
pom
import
From 861f82e9097bac7b03271865347807223c084471 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 27 Jul 2023 15:49:49 +0530
Subject: [PATCH 041/173] build(deps): bump cryptography from 39.0.1 to 41.0.2
in /.kokoro (#1288)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* build(deps): bump cryptography from 39.0.1 to 41.0.2 in /.kokoro
Bumps [cryptography](https://github.com/pyca/cryptography) from 39.0.1 to 41.0.2.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/39.0.1...41.0.2)
---
updated-dependencies:
- dependency-name: cryptography
dependency-type: indirect
...
Signed-off-by: dependabot[bot]
* 🦉 Updates from OwlBot post-processor
See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md
---------
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Owl Bot
From ce257f8acad39581770a28a81d902251673db79f Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Thu, 27 Jul 2023 18:06:08 +0200
Subject: [PATCH 042/173] deps: update dependency
com.google.cloud:google-cloud-spanner-bom to v6.44.0 (#1295)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 858e36e5e..937b824ff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,7 @@
com.google.cloud
google-cloud-spanner-bom
- 6.43.2
+ 6.44.0
pom
import
From 85aab072ddb6c9c0eec8bdf8425bb9f70f8c4c2b Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Thu, 27 Jul 2023 17:30:13 +0000
Subject: [PATCH 043/173] chore(main): release 2.11.5 (#1294)
:robot: I have created a release *beep* *boop*
---
## [2.11.5](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.11.4...v2.11.5) (2023-07-27)
### Dependencies
* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.13.1 ([#1291](https://togithub.com/googleapis/java-spanner-jdbc/issues/1291)) ([aa40c60](https://togithub.com/googleapis/java-spanner-jdbc/commit/aa40c60df7dcf7fbf45c4c942be2dc31130a3d6b))
* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.44.0 ([#1295](https://togithub.com/googleapis/java-spanner-jdbc/issues/1295)) ([ce257f8](https://togithub.com/googleapis/java-spanner-jdbc/commit/ce257f8acad39581770a28a81d902251673db79f))
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
CHANGELOG.md | 8 ++++++++
pom.xml | 2 +-
samples/snapshot/pom.xml | 2 +-
versions.txt | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index afaa6625d..92adec688 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## [2.11.5](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.4...v2.11.5) (2023-07-27)
+
+
+### Dependencies
+
+* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.13.1 ([#1291](https://github.com/googleapis/java-spanner-jdbc/issues/1291)) ([aa40c60](https://github.com/googleapis/java-spanner-jdbc/commit/aa40c60df7dcf7fbf45c4c942be2dc31130a3d6b))
+* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.44.0 ([#1295](https://github.com/googleapis/java-spanner-jdbc/issues/1295)) ([ce257f8](https://github.com/googleapis/java-spanner-jdbc/commit/ce257f8acad39581770a28a81d902251673db79f))
+
## [2.11.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.3...v2.11.4) (2023-07-12)
diff --git a/pom.xml b/pom.xml
index 937b824ff..05d182805 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.11.5-SNAPSHOT
+ 2.11.5
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 a107a1997..770fdcf51 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.5-SNAPSHOT
+ 2.11.5
diff --git a/versions.txt b/versions.txt
index 66cc4b7e4..62f87e024 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.4:2.11.5-SNAPSHOT
+google-cloud-spanner-jdbc:2.11.5:2.11.5
From a7ff70192153807be04503f04ff2c5f6b032fa7a Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Thu, 27 Jul 2023 18:56:13 +0000
Subject: [PATCH 044/173] chore(main): release 2.11.6-SNAPSHOT (#1296)
:robot: I have created a release *beep* *boop*
---
### Updating meta-information for bleeding-edge SNAPSHOT release.
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
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 05d182805..aaf948e0a 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.11.5
+ 2.11.6-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 770fdcf51..85c28b901 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.5
+ 2.11.6-SNAPSHOT
diff --git a/versions.txt b/versions.txt
index 62f87e024..25e212cc7 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.5:2.11.5
+google-cloud-spanner-jdbc:2.11.5:2.11.6-SNAPSHOT
From cf121de62b6e8ea4ed52bcd369da6ae12da4cbe0 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Fri, 28 Jul 2023 07:04:38 +0200
Subject: [PATCH 045/173] chore(deps): update dependency
com.google.cloud:libraries-bom to v26.20.0 (#1299)
---
samples/snippets/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index 69f126379..2c5ee2778 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -30,7 +30,7 @@
com.google.cloud
libraries-bom
- 26.19.0
+ 26.20.0
pom
import
From 3e0a8327382ac74139686da78b9e097e4a458c06 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Fri, 28 Jul 2023 07:04:56 +0200
Subject: [PATCH 046/173] chore(deps): update dependency
com.google.cloud:google-cloud-spanner-jdbc to v2.11.5 (#1298)
---
samples/install-without-bom/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 756be62c1..df6772824 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.11.4
+ 2.11.5
From 0baed7a4f0358bc856646ed0a90b3fde17926d81 Mon Sep 17 00:00:00 2001
From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com>
Date: Fri, 28 Jul 2023 10:35:16 +0530
Subject: [PATCH 047/173] build(deps): bump certifi from 2023.5.7 to 2023.7.22
in /synthtool/gcp/templates/java_library/.kokoro (#1837) (#1297)
build(deps): bump certifi
Bumps [certifi](https://github.com/certifi/python-certifi) from 2023.5.7 to 2023.7.22.
- [Commits](https://github.com/certifi/python-certifi/compare/2023.05.07...2023.07.22)
---
updated-dependencies:
- dependency-name: certifi
dependency-type: indirect
...
Source-Link: https://github.com/googleapis/synthtool/commit/d85e1d678a829da6f2f5664392a6cd8e95ba8341
Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:3a95f1b9b1102865ca551b76be51d2bdb850900c4db2f6d79269e7af81ac8f84
Signed-off-by: dependabot[bot]
Co-authored-by: Owl Bot
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/.OwlBot.lock.yaml | 4 ++--
.kokoro/requirements.txt | 9 ++++-----
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml
index d5500ef44..fa335912b 100644
--- a/.github/.OwlBot.lock.yaml
+++ b/.github/.OwlBot.lock.yaml
@@ -13,5 +13,5 @@
# limitations under the License.
docker:
image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest
- digest: sha256:46d2d262cd285c638656c8bde468011b723dc0c7ffd6a5ecc2650fe639c82e8f
-# created: 2023-07-24T14:21:17.707234503Z
+ digest: sha256:3a95f1b9b1102865ca551b76be51d2bdb850900c4db2f6d79269e7af81ac8f84
+# created: 2023-07-27T18:37:44.251188775Z
diff --git a/.kokoro/requirements.txt b/.kokoro/requirements.txt
index 32989051e..a73256ab8 100644
--- a/.kokoro/requirements.txt
+++ b/.kokoro/requirements.txt
@@ -12,9 +12,9 @@ cachetools==5.3.1 \
--hash=sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590 \
--hash=sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b
# via google-auth
-certifi==2023.5.7 \
- --hash=sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7 \
- --hash=sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716
+certifi==2023.7.22 \
+ --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \
+ --hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9
# via requests
cffi==1.15.1 \
--hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \
@@ -485,6 +485,5 @@ zipp==3.16.1 \
# via importlib-metadata
# WARNING: The following packages were not pinned, but pip requires them to be
-# pinned when the requirements file includes hashes and the requirement is not
-# satisfied by a package already installed. Consider using the --allow-unsafe flag.
+# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag.
# setuptools
From 1c85dc290486c58d108761fbf580e577ff99ad67 Mon Sep 17 00:00:00 2001
From: Rajat Bhatta <93644539+rajatbhatta@users.noreply.github.com>
Date: Mon, 31 Jul 2023 16:52:15 +0530
Subject: [PATCH 048/173] chore: update owner to olavloite (#1301)
---
.github/blunderbuss.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/blunderbuss.yml b/.github/blunderbuss.yml
index 5e0aa64f7..73448c1b0 100644
--- a/.github/blunderbuss.yml
+++ b/.github/blunderbuss.yml
@@ -1,7 +1,7 @@
# Configuration for the Blunderbuss GitHub app. For more info see
# https://github.com/googleapis/repo-automation-bots/tree/main/packages/blunderbuss
assign_issues:
- - rajatbhatta
+ - olavloite
assign_prs_by:
- labels:
- samples
From 5e56ed6f140cb075e5d09b5c9f2e9944411b4776 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Sat, 5 Aug 2023 13:38:04 +0200
Subject: [PATCH 049/173] chore(deps): update dependency
com.google.cloud:libraries-bom to v26.21.0 (#1302)
---
samples/snippets/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index 2c5ee2778..7590dbb98 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -30,7 +30,7 @@
com.google.cloud
libraries-bom
- 26.20.0
+ 26.21.0
pom
import
From 8afb5ba0db1e21e317799db8e82f96820c01c6dd Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Sat, 5 Aug 2023 15:06:14 +0200
Subject: [PATCH 050/173] deps: update dependency
com.google.cloud:google-cloud-shared-dependencies to v3.14.0 (#1303)
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:google-cloud-shared-dependencies](https://togithub.com/googleapis/sdk-platform-java) | `3.13.1` -> `3.14.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-shared-dependencies/3.14.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-shared-dependencies/3.14.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-shared-dependencies/3.13.1/3.14.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-shared-dependencies/3.13.1/3.14.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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](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 aaf948e0a..3add37db3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,7 +69,7 @@
com.google.cloud
google-cloud-shared-dependencies
- 3.13.1
+ 3.14.0
pom
import
From aac0d68c11bada6d338483208be631cbb9ef8ed7 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Sat, 5 Aug 2023 18:23:09 +0200
Subject: [PATCH 051/173] deps: update dependency
com.google.cloud:google-cloud-spanner-bom to v6.45.0 (#1305)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 3add37db3..bd6012d74 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,7 @@
com.google.cloud
google-cloud-spanner-bom
- 6.44.0
+ 6.45.0
pom
import
From 36b5762eaff6aa60cb5f01513337df545ee66cfb Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Sat, 5 Aug 2023 17:46:13 +0000
Subject: [PATCH 052/173] chore(main): release 2.11.6 (#1306)
:robot: I have created a release *beep* *boop*
---
## [2.11.6](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.11.5...v2.11.6) (2023-08-05)
### Dependencies
* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.14.0 ([#1303](https://togithub.com/googleapis/java-spanner-jdbc/issues/1303)) ([8afb5ba](https://togithub.com/googleapis/java-spanner-jdbc/commit/8afb5ba0db1e21e317799db8e82f96820c01c6dd))
* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.0 ([#1305](https://togithub.com/googleapis/java-spanner-jdbc/issues/1305)) ([aac0d68](https://togithub.com/googleapis/java-spanner-jdbc/commit/aac0d68c11bada6d338483208be631cbb9ef8ed7))
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
CHANGELOG.md | 8 ++++++++
pom.xml | 2 +-
samples/snapshot/pom.xml | 2 +-
versions.txt | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 92adec688..e888c604b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## [2.11.6](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.5...v2.11.6) (2023-08-05)
+
+
+### Dependencies
+
+* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.14.0 ([#1303](https://github.com/googleapis/java-spanner-jdbc/issues/1303)) ([8afb5ba](https://github.com/googleapis/java-spanner-jdbc/commit/8afb5ba0db1e21e317799db8e82f96820c01c6dd))
+* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.0 ([#1305](https://github.com/googleapis/java-spanner-jdbc/issues/1305)) ([aac0d68](https://github.com/googleapis/java-spanner-jdbc/commit/aac0d68c11bada6d338483208be631cbb9ef8ed7))
+
## [2.11.5](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.4...v2.11.5) (2023-07-27)
diff --git a/pom.xml b/pom.xml
index bd6012d74..832c8ff43 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.11.6-SNAPSHOT
+ 2.11.6
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 85c28b901..81d144448 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.6-SNAPSHOT
+ 2.11.6
diff --git a/versions.txt b/versions.txt
index 25e212cc7..7cc99e114 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.5:2.11.6-SNAPSHOT
+google-cloud-spanner-jdbc:2.11.6:2.11.6
From 1026403346c9e0d22504e9bb4df8dfa3d17247be Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Sat, 5 Aug 2023 19:12:14 +0000
Subject: [PATCH 053/173] chore(main): release 2.11.7-SNAPSHOT (#1307)
:robot: I have created a release *beep* *boop*
---
### Updating meta-information for bleeding-edge SNAPSHOT release.
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
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 832c8ff43..27f45c539 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.11.6
+ 2.11.7-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 81d144448..05252d3e4 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.6
+ 2.11.7-SNAPSHOT
diff --git a/versions.txt b/versions.txt
index 7cc99e114..5f18f19fd 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.6:2.11.6
+google-cloud-spanner-jdbc:2.11.6:2.11.7-SNAPSHOT
From 0081631eab39f2c91a47b0f5136987f0de0fc026 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Sun, 6 Aug 2023 07:14:27 +0200
Subject: [PATCH 054/173] chore(deps): update dependency
com.google.cloud:google-cloud-spanner-jdbc to v2.11.6 (#1308)
---
samples/install-without-bom/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index df6772824..e5c2fd93b 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.11.5
+ 2.11.6
From 53668f9b6898e0f17b94f62639cba41a5e5b01a3 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Fri, 11 Aug 2023 09:24:09 +0200
Subject: [PATCH 055/173] chore(deps): update dependency
com.google.cloud:libraries-bom to v26.22.0 (#1309)
---
samples/snippets/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index 7590dbb98..b0a7026a7 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -30,7 +30,7 @@
com.google.cloud
libraries-bom
- 26.21.0
+ 26.22.0
pom
import
From 2e99e357c9688c89881433e77b3167924442abaa Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Sun, 13 Aug 2023 14:18:12 +0200
Subject: [PATCH 056/173] deps: update dependency
com.google.cloud:google-cloud-spanner-bom to v6.45.1 (#1312)
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:google-cloud-spanner-bom](https://togithub.com/googleapis/java-spanner) | `6.45.0` -> `6.45.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.45.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-spanner-bom/6.45.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-spanner-bom/6.45.0/6.45.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-spanner-bom/6.45.0/6.45.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
---
### Release Notes
googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom)
### [`v6.45.1`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6451-2023-08-11)
[Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.45.0...v6.45.1)
##### Bug Fixes
- Always allow metadata queries ([#2580](https://togithub.com/googleapis/java-spanner/issues/2580)) ([ebb17fc](https://togithub.com/googleapis/java-spanner/commit/ebb17fc8aeac5fc75e4f135f33dba970f2480585))
---
### 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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](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 27f45c539..a05a7daff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,7 @@
com.google.cloud
google-cloud-spanner-bom
- 6.45.0
+ 6.45.1
pom
import
From e07fa07b7e23c2f450aa47b68fc598f2fbe714a1 Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Sun, 13 Aug 2023 13:42:13 +0000
Subject: [PATCH 057/173] chore(main): release 2.11.7 (#1313)
:robot: I have created a release *beep* *boop*
---
## [2.11.7](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.11.6...v2.11.7) (2023-08-13)
### Dependencies
* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.1 ([#1312](https://togithub.com/googleapis/java-spanner-jdbc/issues/1312)) ([2e99e35](https://togithub.com/googleapis/java-spanner-jdbc/commit/2e99e357c9688c89881433e77b3167924442abaa))
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
CHANGELOG.md | 7 +++++++
pom.xml | 2 +-
samples/snapshot/pom.xml | 2 +-
versions.txt | 2 +-
4 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e888c604b..af3d292a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog
+## [2.11.7](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.6...v2.11.7) (2023-08-13)
+
+
+### Dependencies
+
+* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.1 ([#1312](https://github.com/googleapis/java-spanner-jdbc/issues/1312)) ([2e99e35](https://github.com/googleapis/java-spanner-jdbc/commit/2e99e357c9688c89881433e77b3167924442abaa))
+
## [2.11.6](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.5...v2.11.6) (2023-08-05)
diff --git a/pom.xml b/pom.xml
index a05a7daff..4847ce9d5 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.11.7-SNAPSHOT
+ 2.11.7
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 05252d3e4..74c89c6c2 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.7-SNAPSHOT
+ 2.11.7
diff --git a/versions.txt b/versions.txt
index 5f18f19fd..874269315 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.6:2.11.7-SNAPSHOT
+google-cloud-spanner-jdbc:2.11.7:2.11.7
From eea6c9e8901e29ff998d7996c819f3aa793ce2df Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Sun, 13 Aug 2023 15:08:13 +0000
Subject: [PATCH 058/173] chore(main): release 2.11.8-SNAPSHOT (#1314)
:robot: I have created a release *beep* *boop*
---
### Updating meta-information for bleeding-edge SNAPSHOT release.
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
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 4847ce9d5..3378a232f 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.11.7
+ 2.11.8-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 74c89c6c2..99c50943d 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.7
+ 2.11.8-SNAPSHOT
diff --git a/versions.txt b/versions.txt
index 874269315..5459f1d3b 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.7:2.11.7
+google-cloud-spanner-jdbc:2.11.7:2.11.8-SNAPSHOT
From aaf89de2b569cf5f86c456c18fcc79643cc6c94b Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Sun, 13 Aug 2023 18:32:12 +0200
Subject: [PATCH 059/173] chore(deps): update dependency
com.google.cloud:google-cloud-spanner-jdbc to v2.11.7 (#1315)
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:google-cloud-spanner-jdbc](https://togithub.com/googleapis/java-spanner-jdbc) | `2.11.6` -> `2.11.7` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.11.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-spanner-jdbc/2.11.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-spanner-jdbc/2.11.6/2.11.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-spanner-jdbc/2.11.6/2.11.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
---
### Release Notes
googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc)
### [`v2.11.7`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2117-2023-08-13)
[Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.11.6...v2.11.7)
##### Dependencies
- Update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.1 ([#1312](https://togithub.com/googleapis/java-spanner-jdbc/issues/1312)) ([2e99e35](https://togithub.com/googleapis/java-spanner-jdbc/commit/2e99e357c9688c89881433e77b3167924442abaa))
---
### 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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/googleapis/java-spanner-jdbc).
---
samples/install-without-bom/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index e5c2fd93b..192263619 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.11.6
+ 2.11.7
From 1953ea245889f54e3c803d6bf5e739141a48678e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?=
Date: Mon, 14 Aug 2023 21:01:45 +0200
Subject: [PATCH 060/173] chore: method for adding returning clause to
statements (#1311)
* chore: method for adding returning clause to statements
Adds a method to JdbcStatement for appending a THEN RETURN/RETURNING
clause to the statement. This will be used to modify statements that
request generated keys to be returned.
* feat: support return all columns
* fix: only add THEN RETURN * from DML
---
.../cloud/spanner/jdbc/JdbcStatement.java | 81 +++++++++
.../cloud/spanner/jdbc/JdbcStatementTest.java | 156 ++++++++++++++++++
2 files changed, 237 insertions(+)
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java
index 051ed9d6d..3e7c86f9f 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java
@@ -23,9 +23,11 @@
import com.google.cloud.spanner.Statement;
import com.google.cloud.spanner.Type;
import com.google.cloud.spanner.Type.StructField;
+import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement;
import com.google.cloud.spanner.connection.StatementResult;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
import com.google.rpc.Code;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -33,9 +35,13 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
/** Implementation of {@link java.sql.Statement} for Google Cloud Spanner. */
class JdbcStatement extends AbstractJdbcStatement {
+ static final ImmutableList ALL_COLUMNS = ImmutableList.of("*");
+
enum BatchType {
NONE,
DML,
@@ -98,6 +104,81 @@ public long executeLargeUpdate(String sql) throws SQLException {
}
}
+ /**
+ * Adds a THEN RETURN/RETURNING clause to the given statement if the following conditions are all
+ * met:
+ *
+ *
+ * - The generatedKeysColumns is not null or empty
+ *
- The statement is a DML statement
+ *
- The DML statement does not already contain a THEN RETURN/RETURNING clause
+ *
+ */
+ Statement addReturningToStatement(
+ Statement statement, @Nullable ImmutableList generatedKeysColumns)
+ throws SQLException {
+ if (generatedKeysColumns == null || generatedKeysColumns.isEmpty()) {
+ return statement;
+ }
+ // Check if the statement is a DML statement or not.
+ ParsedStatement parsedStatement = getConnection().getParser().parse(statement);
+ if (parsedStatement.isUpdate() && !parsedStatement.hasReturningClause()) {
+ if (generatedKeysColumns.size() == 1
+ && ALL_COLUMNS.get(0).equals(generatedKeysColumns.get(0))) {
+ // Add a 'THEN RETURN/RETURNING *' clause to the statement.
+ return statement
+ .toBuilder()
+ .replace(statement.getSql() + getReturningAllColumnsClause())
+ .build();
+ }
+ // Add a 'THEN RETURN/RETURNING col1, col2, ...' to the statement.
+ // The column names will be quoted using the dialect-specific identifier quoting character.
+ return statement
+ .toBuilder()
+ .replace(
+ generatedKeysColumns.stream()
+ .map(this::quoteColumn)
+ .collect(
+ Collectors.joining(
+ ", ", statement.getSql() + getReturningClause() + " ", "")))
+ .build();
+ }
+ return statement;
+ }
+
+ /** Returns the dialect-specific clause for returning values from a DML statement. */
+ String getReturningAllColumnsClause() {
+ switch (getConnection().getDialect()) {
+ case POSTGRESQL:
+ return "\nRETURNING *";
+ case GOOGLE_STANDARD_SQL:
+ default:
+ return "\nTHEN RETURN *";
+ }
+ }
+
+ /** Returns the dialect-specific clause for returning values from a DML statement. */
+ String getReturningClause() {
+ switch (getConnection().getDialect()) {
+ case POSTGRESQL:
+ return "\nRETURNING";
+ case GOOGLE_STANDARD_SQL:
+ default:
+ return "\nTHEN RETURN";
+ }
+ }
+
+ /** Adds dialect-specific quotes to the given column name. */
+ String quoteColumn(String column) {
+ switch (getConnection().getDialect()) {
+ case POSTGRESQL:
+ return "\"" + column + "\"";
+ case GOOGLE_STANDARD_SQL:
+ default:
+ return "`" + column + "`";
+ }
+ }
+
@Override
public boolean execute(String sql) throws SQLException {
checkClosed();
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java
index c7b6a6cbd..d44583587 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -39,6 +40,7 @@
import com.google.cloud.spanner.connection.StatementResult;
import com.google.cloud.spanner.connection.StatementResult.ResultType;
import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl;
+import com.google.common.collect.ImmutableList;
import com.google.rpc.Code;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -47,6 +49,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
+import javax.annotation.Nullable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -599,4 +602,157 @@ public void testConvertUpdateCountsToSuccessNoInfo() throws SQLException {
(long) Statement.SUCCESS_NO_INFO);
}
}
+
+ @Test
+ public void testAddReturningToStatement() throws SQLException {
+ JdbcConnection connection = mock(JdbcConnection.class);
+ when(connection.getDialect()).thenReturn(dialect);
+ when(connection.getParser()).thenReturn(AbstractStatementParser.getInstance(dialect));
+ try (JdbcStatement statement = new JdbcStatement(connection)) {
+ assertAddReturningSame(statement, "insert into test (id, value) values (1, 'One')", null);
+ assertAddReturningSame(
+ statement, "insert into test (id, value) values (1, 'One')", ImmutableList.of());
+ assertAddReturningEquals(
+ statement,
+ dialect == Dialect.POSTGRESQL
+ ? "insert into test (id, value) values (1, 'One')\nRETURNING \"id\""
+ : "insert into test (id, value) values (1, 'One')\nTHEN RETURN `id`",
+ "insert into test (id, value) values (1, 'One')",
+ ImmutableList.of("id"));
+ assertAddReturningEquals(
+ statement,
+ dialect == Dialect.POSTGRESQL
+ ? "insert into test (id, value) values (1, 'One')\nRETURNING \"id\", \"value\""
+ : "insert into test (id, value) values (1, 'One')\nTHEN RETURN `id`, `value`",
+ "insert into test (id, value) values (1, 'One')",
+ ImmutableList.of("id", "value"));
+ assertAddReturningEquals(
+ statement,
+ dialect == Dialect.POSTGRESQL
+ ? "insert into test (id, value) values (1, 'One')\nRETURNING *"
+ : "insert into test (id, value) values (1, 'One')\nTHEN RETURN *",
+ "insert into test (id, value) values (1, 'One')",
+ ImmutableList.of("*"));
+ // Requesting generated keys for a DML statement that already contains a returning clause is a
+ // no-op.
+ assertAddReturningSame(
+ statement,
+ "insert into test (id, value) values (1, 'One') "
+ + statement.getReturningClause()
+ + " value",
+ ImmutableList.of("id"));
+ // Requesting generated keys for a query is a no-op.
+ for (ImmutableList keys :
+ ImmutableList.of(
+ ImmutableList.of("id"), ImmutableList.of("id", "value"), ImmutableList.of("*"))) {
+ assertAddReturningSame(statement, "select id, value from test", keys);
+ }
+
+ // Update statements may also request generated keys.
+ assertAddReturningSame(statement, "update test set value='Two' where id=1", null);
+ assertAddReturningSame(
+ statement, "update test set value='Two' where id=1", ImmutableList.of());
+ assertAddReturningEquals(
+ statement,
+ dialect == Dialect.POSTGRESQL
+ ? "update test set value='Two' where id=1\nRETURNING \"value\""
+ : "update test set value='Two' where id=1\nTHEN RETURN `value`",
+ "update test set value='Two' where id=1",
+ ImmutableList.of("value"));
+ assertAddReturningEquals(
+ statement,
+ dialect == Dialect.POSTGRESQL
+ ? "update test set value='Two' where id=1\nRETURNING \"value\", \"id\""
+ : "update test set value='Two' where id=1\nTHEN RETURN `value`, `id`",
+ "update test set value='Two' where id=1",
+ ImmutableList.of("value", "id"));
+ assertAddReturningEquals(
+ statement,
+ dialect == Dialect.POSTGRESQL
+ ? "update test set value='Two' where id=1\nRETURNING *"
+ : "update test set value='Two' where id=1\nTHEN RETURN *",
+ "update test set value='Two' where id=1",
+ ImmutableList.of("*"));
+ // Requesting generated keys for a DML statement that already contains a returning clause is a
+ // no-op.
+ assertAddReturningSame(
+ statement,
+ "update test set value='Two' where id=1 " + statement.getReturningClause() + " value",
+ ImmutableList.of("value"));
+
+ // Delete statements may also request generated keys.
+ assertAddReturningSame(statement, "delete test where id=1", null);
+ assertAddReturningSame(statement, "delete test where id=1", ImmutableList.of());
+ assertAddReturningEquals(
+ statement,
+ dialect == Dialect.POSTGRESQL
+ ? "delete test where id=1\nRETURNING \"value\""
+ : "delete test where id=1\nTHEN RETURN `value`",
+ "delete test where id=1",
+ ImmutableList.of("value"));
+ assertAddReturningEquals(
+ statement,
+ dialect == Dialect.POSTGRESQL
+ ? "delete test where id=1\nRETURNING \"id\", \"value\""
+ : "delete test where id=1\nTHEN RETURN `id`, `value`",
+ "delete test where id=1",
+ ImmutableList.of("id", "value"));
+ assertAddReturningEquals(
+ statement,
+ dialect == Dialect.POSTGRESQL
+ ? "delete test where id=1\nRETURNING *"
+ : "delete test where id=1\nTHEN RETURN *",
+ "delete test where id=1",
+ ImmutableList.of("*"));
+ // Requesting generated keys for a DML statement that already contains a returning clause is a
+ // no-op.
+ for (ImmutableList keys :
+ ImmutableList.of(
+ ImmutableList.of("id"), ImmutableList.of("id", "value"), ImmutableList.of("*"))) {
+ assertAddReturningSame(
+ statement,
+ "delete test where id=1 "
+ + (dialect == Dialect.POSTGRESQL
+ ? "delete test where id=1\nRETURNING"
+ : "delete test where id=1\nTHEN RETURN")
+ + " value",
+ keys);
+ }
+
+ // Requesting generated keys for DDL is a no-op.
+ for (ImmutableList keys :
+ ImmutableList.of(
+ ImmutableList.of("id"), ImmutableList.of("id", "value"), ImmutableList.of("*"))) {
+ assertAddReturningSame(
+ statement,
+ dialect == Dialect.POSTGRESQL
+ ? "create table test (id bigint primary key, value varchar)"
+ : "create table test (id int64, value string(max)) primary key (id)",
+ keys);
+ }
+ }
+ }
+
+ private void assertAddReturningSame(
+ JdbcStatement statement, String sql, @Nullable ImmutableList generatedKeysColumns)
+ throws SQLException {
+ com.google.cloud.spanner.Statement spannerStatement =
+ com.google.cloud.spanner.Statement.of(sql);
+ assertSame(
+ spannerStatement,
+ statement.addReturningToStatement(spannerStatement, generatedKeysColumns));
+ }
+
+ private void assertAddReturningEquals(
+ JdbcStatement statement,
+ String expectedSql,
+ String sql,
+ @Nullable ImmutableList generatedKeysColumns)
+ throws SQLException {
+ com.google.cloud.spanner.Statement spannerStatement =
+ com.google.cloud.spanner.Statement.of(sql);
+ assertEquals(
+ com.google.cloud.spanner.Statement.of(expectedSql),
+ statement.addReturningToStatement(spannerStatement, generatedKeysColumns));
+ }
}
From e9241787b94cb614f658f5e6c977ffc008fd3397 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Tue, 15 Aug 2023 07:08:48 +0200
Subject: [PATCH 061/173] deps: update dependency
com.google.cloud:google-cloud-spanner-bom to v6.45.2 (#1318)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 3378a232f..9cc747b20 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,7 @@
com.google.cloud
google-cloud-spanner-bom
- 6.45.1
+ 6.45.2
pom
import
From 4f1472705f8642a8227d9a42bdb2b3285dd942f4 Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Tue, 15 Aug 2023 06:32:13 +0000
Subject: [PATCH 062/173] chore(main): release 2.11.8 (#1319)
:robot: I have created a release *beep* *boop*
---
## [2.11.8](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.11.7...v2.11.8) (2023-08-15)
### Dependencies
* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.2 ([#1318](https://togithub.com/googleapis/java-spanner-jdbc/issues/1318)) ([e924178](https://togithub.com/googleapis/java-spanner-jdbc/commit/e9241787b94cb614f658f5e6c977ffc008fd3397))
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
CHANGELOG.md | 7 +++++++
pom.xml | 2 +-
samples/snapshot/pom.xml | 2 +-
versions.txt | 2 +-
4 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index af3d292a3..a1f93aa82 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog
+## [2.11.8](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.7...v2.11.8) (2023-08-15)
+
+
+### Dependencies
+
+* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.2 ([#1318](https://github.com/googleapis/java-spanner-jdbc/issues/1318)) ([e924178](https://github.com/googleapis/java-spanner-jdbc/commit/e9241787b94cb614f658f5e6c977ffc008fd3397))
+
## [2.11.7](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.6...v2.11.7) (2023-08-13)
diff --git a/pom.xml b/pom.xml
index 9cc747b20..7e85f5a45 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.11.8-SNAPSHOT
+ 2.11.8
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 99c50943d..73e594f27 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.8-SNAPSHOT
+ 2.11.8
diff --git a/versions.txt b/versions.txt
index 5459f1d3b..e9d28b678 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.7:2.11.8-SNAPSHOT
+google-cloud-spanner-jdbc:2.11.8:2.11.8
From a393458d3ae70d55d84d180193e5de32d520a3f0 Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Tue, 15 Aug 2023 07:58:13 +0000
Subject: [PATCH 063/173] chore(main): release 2.11.9-SNAPSHOT (#1320)
:robot: I have created a release *beep* *boop*
---
### Updating meta-information for bleeding-edge SNAPSHOT release.
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
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 7e85f5a45..c46a8404b 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.11.8
+ 2.11.9-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 73e594f27..4abc54e52 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.8
+ 2.11.9-SNAPSHOT
diff --git a/versions.txt b/versions.txt
index e9d28b678..f29b5a46c 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.8:2.11.8
+google-cloud-spanner-jdbc:2.11.8:2.11.9-SNAPSHOT
From ae5c6078e14c31f32ea52e19f2cb9c460b5c7678 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Tue, 15 Aug 2023 13:00:23 +0200
Subject: [PATCH 064/173] chore(deps): update dependency
com.google.cloud:google-cloud-spanner-jdbc to v2.11.8 (#1322)
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:google-cloud-spanner-jdbc](https://togithub.com/googleapis/java-spanner-jdbc) | `2.11.7` -> `2.11.8` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.11.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-spanner-jdbc/2.11.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-spanner-jdbc/2.11.7/2.11.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-spanner-jdbc/2.11.7/2.11.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
---
### Release Notes
googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc)
### [`v2.11.8`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2118-2023-08-15)
[Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.11.7...v2.11.8)
##### Dependencies
- Update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.2 ([#1318](https://togithub.com/googleapis/java-spanner-jdbc/issues/1318)) ([e924178](https://togithub.com/googleapis/java-spanner-jdbc/commit/e9241787b94cb614f658f5e6c977ffc008fd3397))
---
### 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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/googleapis/java-spanner-jdbc).
---
samples/install-without-bom/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 192263619..9b535bcfd 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.11.7
+ 2.11.8
From 9e050e0a6d9693dc9da44ac00691413d1d947b5e Mon Sep 17 00:00:00 2001
From: Tomo Suzuki
Date: Fri, 18 Aug 2023 15:06:52 -0400
Subject: [PATCH 065/173] ci: javadoc as a required check (#1326)
---
.github/sync-repo-settings.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml
index 4879f02a5..a259dc084 100644
--- a/.github/sync-repo-settings.yaml
+++ b/.github/sync-repo-settings.yaml
@@ -39,6 +39,7 @@ branchProtectionRules:
- OwlBot Post Processor
- 'Kokoro - Test: Java GraalVM Native Image'
- 'Kokoro - Test: Java 17 GraalVM Native Image'
+ - javadoc
# Identifies the protection rule pattern. Name of the branch to be protected.
# Defaults to `main`
From d96d278f58942c38b30dc0a4e1f9f92aefdc760b Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Mon, 21 Aug 2023 07:50:29 +0200
Subject: [PATCH 066/173] deps: update dependency
com.google.cloud:google-cloud-spanner-bom to v6.45.3 (#1325)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index c46a8404b..42bdae59c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,7 @@
com.google.cloud
google-cloud-spanner-bom
- 6.45.2
+ 6.45.3
pom
import
From f960e7025a57925fe89c4e431a5b66347a399a05 Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Mon, 21 Aug 2023 07:14:13 +0000
Subject: [PATCH 067/173] chore(main): release 2.11.9 (#1327)
:robot: I have created a release *beep* *boop*
---
## [2.11.9](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.11.8...v2.11.9) (2023-08-21)
### Dependencies
* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.3 ([#1325](https://togithub.com/googleapis/java-spanner-jdbc/issues/1325)) ([d96d278](https://togithub.com/googleapis/java-spanner-jdbc/commit/d96d278f58942c38b30dc0a4e1f9f92aefdc760b))
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
CHANGELOG.md | 7 +++++++
pom.xml | 2 +-
samples/snapshot/pom.xml | 2 +-
versions.txt | 2 +-
4 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a1f93aa82..39927096c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog
+## [2.11.9](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.8...v2.11.9) (2023-08-21)
+
+
+### Dependencies
+
+* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.3 ([#1325](https://github.com/googleapis/java-spanner-jdbc/issues/1325)) ([d96d278](https://github.com/googleapis/java-spanner-jdbc/commit/d96d278f58942c38b30dc0a4e1f9f92aefdc760b))
+
## [2.11.8](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.7...v2.11.8) (2023-08-15)
diff --git a/pom.xml b/pom.xml
index 42bdae59c..84b23656c 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.11.9-SNAPSHOT
+ 2.11.9
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 4abc54e52..47da31b3e 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.9-SNAPSHOT
+ 2.11.9
diff --git a/versions.txt b/versions.txt
index f29b5a46c..9b5dabc43 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.8:2.11.9-SNAPSHOT
+google-cloud-spanner-jdbc:2.11.9:2.11.9
From 08cbdecc966a4d0387d440e7e6300676bf782374 Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Mon, 21 Aug 2023 08:38:13 +0000
Subject: [PATCH 068/173] chore(main): release 2.11.10-SNAPSHOT (#1328)
:robot: I have created a release *beep* *boop*
---
### Updating meta-information for bleeding-edge SNAPSHOT release.
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
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 84b23656c..4a33dea80 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.11.9
+ 2.11.10-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 47da31b3e..5cc1db045 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.9
+ 2.11.10-SNAPSHOT
diff --git a/versions.txt b/versions.txt
index 9b5dabc43..4a69a3a0a 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.9:2.11.9
+google-cloud-spanner-jdbc:2.11.9:2.11.10-SNAPSHOT
From d2d8c9cd00285185dc2debd4ffd2d77f330494c3 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Thu, 24 Aug 2023 14:42:19 +0200
Subject: [PATCH 069/173] chore(deps): update dependency
com.google.cloud:google-cloud-spanner-jdbc to v2.11.9 (#1329)
---
samples/install-without-bom/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 9b535bcfd..be6323501 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.11.8
+ 2.11.9
From ce7d74c01e1e180dfe9eb7db3b1bdfd157c03aba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?=
Date: Fri, 25 Aug 2023 14:04:57 +0200
Subject: [PATCH 070/173] chore: add copyOf method for result sets (#1316)
Adds a method for creating a JDBC ResultSet that creates a copy of a
Cloud Spanner ResultSet. This type of ResultSet can be used for small
result sets that are unlikely to be closed by the client application,
such as a ResultSet that holds the generated keys of an update
statement. If an application requests the JDBC driver to return the
generated keys, and then never gets and closes the generated keys
ResultSet, the underlying session and/or result stream could be
leaked.
---
.../cloud/spanner/jdbc/JdbcResultSet.java | 59 ++++++++++++++++++-
.../cloud/spanner/jdbc/JdbcResultSetTest.java | 56 ++++++++++++++++++
2 files changed, 113 insertions(+), 2 deletions(-)
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java
index f8ab45264..94b460420 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java
@@ -16,12 +16,13 @@
package com.google.cloud.spanner.jdbc;
-import static com.google.cloud.spanner.Type.Code.PG_NUMERIC;
-
+import com.google.cloud.spanner.ResultSets;
+import com.google.cloud.spanner.Struct;
import com.google.cloud.spanner.Type;
import com.google.cloud.spanner.Type.Code;
import com.google.cloud.spanner.Value;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Reader;
@@ -43,8 +44,11 @@
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
+import javax.annotation.Nonnull;
/** Implementation of {@link ResultSet} for Cloud Spanner */
class JdbcResultSet extends AbstractJdbcResultSet {
@@ -60,6 +64,57 @@ static JdbcResultSet of(Statement statement, com.google.cloud.spanner.ResultSet
return new JdbcResultSet(statement, resultSet);
}
+ /**
+ * Creates a JDBC result set by copying the given Spanner {@link
+ * com.google.cloud.spanner.ResultSet}. This can be used for result sets that are known not to be
+ * too large. This type of result set should be preferred for results that are unlikely to be
+ * closed by the client application, such as the returned generated keys of an update statement.
+ * The copy will not hold on to a reference to a Cloud Spanner session or result stream. All the
+ * data in the given Spanner {@link com.google.cloud.spanner.ResultSet} have been consumed after
+ * calling this method. The {@link com.google.cloud.spanner.ResultSet} is not closed by this
+ * method.
+ */
+ static JdbcResultSet copyOf(@Nonnull com.google.cloud.spanner.ResultSet resultSet) {
+ Preconditions.checkNotNull(resultSet);
+ // Make the copy first. This ensures that ResultSet#next() has been called at least once, which
+ // is necessary to get the type of the result set.
+ ImmutableList rows = ImmutableList.copyOf(new ResultSetIterator(resultSet));
+ return of(ResultSets.forRows(resultSet.getType(), rows));
+ }
+
+ /**
+ * {@link Iterator} implementation for {@link com.google.cloud.spanner.ResultSet}. This is used to
+ * create a copy of an existing result set without the need to iterate the rows more than once.
+ */
+ private static class ResultSetIterator implements Iterator {
+ private final com.google.cloud.spanner.ResultSet resultSet;
+ private boolean calculatedHasNext = false;
+ private boolean hasNext = false;
+
+ ResultSetIterator(com.google.cloud.spanner.ResultSet resultSet) {
+ this.resultSet = resultSet;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (!calculatedHasNext) {
+ calculatedHasNext = true;
+ hasNext = resultSet.next();
+ }
+ return hasNext;
+ }
+
+ @Override
+ public Struct next() {
+ if (hasNext()) {
+ // Indicate that the next call to hasNext() must re-check whether there are more results.
+ calculatedHasNext = false;
+ return resultSet.getCurrentRowAsStruct();
+ }
+ throw new NoSuchElementException();
+ }
+ }
+
private boolean closed = false;
private final Statement statement;
private boolean wasNull = false;
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java
index 024f6c243..476c40492 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java
@@ -37,6 +37,7 @@
import com.google.cloud.spanner.Type.StructField;
import com.google.cloud.spanner.Value;
import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl;
+import com.google.common.collect.ImmutableList;
import com.google.rpc.Code;
import java.io.IOException;
import java.io.InputStream;
@@ -46,9 +47,11 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
+import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
+import java.sql.Types;
import java.time.Instant;
import java.time.LocalDate;
import java.time.OffsetDateTime;
@@ -1753,4 +1756,57 @@ public void testGetOffsetDateTime() throws SQLException {
offsetDateTime);
assertFalse(subject.wasNull());
}
+
+ @Test
+ public void testCopyOf() throws SQLException {
+ ResultSet original =
+ ResultSets.forRows(
+ Type.struct(StructField.of("id", Type.int64()), StructField.of("value", Type.string())),
+ ImmutableList.of(
+ Struct.newBuilder().set("id").to(1L).set("value").to("One").build(),
+ Struct.newBuilder().set("id").to(2L).set("value").to("Two").build()));
+ java.sql.ResultSet copy = JdbcResultSet.copyOf(original);
+ // The original result set has been fully consumed.
+ assertFalse(original.next());
+ // We can safely close the original result set and still use the copy.
+ original.close();
+
+ ResultSetMetaData metadata = copy.getMetaData();
+ assertEquals(2, metadata.getColumnCount());
+ assertEquals("id", metadata.getColumnName(1));
+ assertEquals("value", metadata.getColumnName(2));
+ assertEquals(Types.BIGINT, metadata.getColumnType(1));
+ assertEquals(Types.NVARCHAR, metadata.getColumnType(2));
+
+ assertTrue(copy.next());
+ assertEquals(1L, copy.getLong(1));
+ assertEquals("One", copy.getString(2));
+ assertTrue(copy.next());
+ assertEquals(2L, copy.getLong("id"));
+ assertEquals("Two", copy.getString("value"));
+ assertFalse(copy.next());
+ }
+
+ @Test
+ public void testCopyOfEmpty() throws SQLException {
+ ResultSet original =
+ ResultSets.forRows(
+ Type.struct(StructField.of("id", Type.int64()), StructField.of("value", Type.string())),
+ ImmutableList.of());
+ java.sql.ResultSet copy = JdbcResultSet.copyOf(original);
+ // The original result set has been fully consumed.
+ assertFalse(original.next());
+ // We can safely close the original result set and still use the copy.
+ original.close();
+
+ ResultSetMetaData metadata = copy.getMetaData();
+ assertEquals(2, metadata.getColumnCount());
+ assertEquals("id", metadata.getColumnName(1));
+ assertEquals("value", metadata.getColumnName(2));
+ assertEquals(Types.BIGINT, metadata.getColumnType(1));
+ assertEquals(Types.NVARCHAR, metadata.getColumnType(2));
+
+ // The copy should not contain any rows.
+ assertFalse(copy.next());
+ }
}
From a7d0fbb529ff71b45d6ddbbad8fc3be43e7c966f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?=
Date: Fri, 25 Aug 2023 14:05:13 +0200
Subject: [PATCH 071/173] fix: session leak for invalid update (#1323)
* deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.2 (#1318)
* fix: session leak for invalid update
Close the underlying ResultSet if the result that was returned for an
executeUpdate call turned out to be of an unexpected type.
---------
Co-authored-by: Mend Renovate
---
.../cloud/spanner/jdbc/JdbcStatement.java | 16 ++-
.../spanner/jdbc/ExecuteMockServerTest.java | 114 ++++++++++++++++++
2 files changed, 128 insertions(+), 2 deletions(-)
create mode 100644 src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java
index 3e7c86f9f..3385ef012 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java
@@ -92,8 +92,9 @@ public long executeLargeUpdate(String sql) throws SQLException {
StatementResult result = execute(statement);
switch (result.getResultType()) {
case RESULT_SET:
- throw JdbcSqlExceptionFactory.of(
- "The statement is not a non-returning DML or DDL statement", Code.INVALID_ARGUMENT);
+ // Close the result set as we are not going to return it to the user. This prevents the
+ // underlying session from potentially being leaked.
+ throw closeResultSetAndCreateInvalidQueryException(result);
case UPDATE_COUNT:
return result.getUpdateCount();
case NO_RESULT:
@@ -104,6 +105,17 @@ public long executeLargeUpdate(String sql) throws SQLException {
}
}
+ private SQLException closeResultSetAndCreateInvalidQueryException(StatementResult result) {
+ //noinspection finally
+ try {
+ result.getResultSet().close();
+ } finally {
+ //noinspection ReturnInsideFinallyBlock
+ return JdbcSqlExceptionFactory.of(
+ "The statement is not a non-returning DML or DDL statement", Code.INVALID_ARGUMENT);
+ }
+ }
+
/**
* Adds a THEN RETURN/RETURNING clause to the given statement if the following conditions are all
* met:
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java b/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java
new file mode 100644
index 000000000..f74de6631
--- /dev/null
+++ b/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.spanner.jdbc;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult;
+import com.google.cloud.spanner.SessionPoolOptions;
+import com.google.cloud.spanner.connection.AbstractMockServerTest;
+import com.google.cloud.spanner.connection.ConnectionOptions;
+import com.google.protobuf.ListValue;
+import com.google.protobuf.Value;
+import com.google.rpc.Code;
+import com.google.spanner.v1.ResultSetMetadata;
+import com.google.spanner.v1.StructType;
+import com.google.spanner.v1.StructType.Field;
+import com.google.spanner.v1.Type;
+import com.google.spanner.v1.TypeCode;
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Test class for verifying that the methods execute, executeQuery, and executeUpdate work as
+ * intended.
+ */
+@RunWith(JUnit4.class)
+public class ExecuteMockServerTest extends AbstractMockServerTest {
+ private static final String QUERY = "select * from my_table";
+
+ @Before
+ public void setupResults() {
+ super.setupResults();
+ com.google.spanner.v1.ResultSet resultSet =
+ com.google.spanner.v1.ResultSet.newBuilder()
+ .setMetadata(
+ ResultSetMetadata.newBuilder()
+ .setRowType(
+ StructType.newBuilder()
+ .addFields(
+ Field.newBuilder()
+ .setType(Type.newBuilder().setCode(TypeCode.INT64).build())
+ .setName("id")
+ .build())
+ .addFields(
+ Field.newBuilder()
+ .setType(Type.newBuilder().setCode(TypeCode.STRING).build())
+ .setName("value")
+ .build())
+ .build())
+ .build())
+ .addRows(
+ ListValue.newBuilder()
+ .addValues(Value.newBuilder().setStringValue("1").build())
+ .addValues(Value.newBuilder().setStringValue("One").build())
+ .build())
+ .build();
+ mockSpanner.putStatementResult(
+ StatementResult.query(com.google.cloud.spanner.Statement.of(QUERY), resultSet));
+ }
+
+ private String createUrl() {
+ return String.format(
+ "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true",
+ getPort(), "proj", "inst", "db");
+ }
+
+ @Test
+ public void testInvalidExecuteUpdate_shouldNotLeakSession() throws SQLException {
+ int maxSessions = 1;
+ try (Connection connection =
+ new JdbcConnection(
+ createUrl(),
+ ConnectionOptions.newBuilder()
+ .setUri(createUrl().substring("jdbc:".length()))
+ .setSessionPoolOptions(
+ SessionPoolOptions.newBuilder()
+ .setMinSessions(1)
+ .setMaxSessions(maxSessions)
+ .setFailIfPoolExhausted()
+ .build())
+ .build())) {
+
+ for (int i = 0; i < (maxSessions + 1); i++) {
+ SQLException exception =
+ assertThrows(
+ SQLException.class, () -> connection.createStatement().executeUpdate(QUERY));
+ assertTrue(exception instanceof JdbcSqlException);
+ JdbcSqlException jdbcSqlException = (JdbcSqlException) exception;
+ // This would be RESOURCE_EXHAUSTED if the query leaked a session.
+ assertEquals(Code.INVALID_ARGUMENT, jdbcSqlException.getCode());
+ }
+ }
+ }
+}
From 9b5ab377587de09004474cb1cf488919fc83d6cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?=
Date: Mon, 28 Aug 2023 13:38:13 +0200
Subject: [PATCH 072/173] feat: return generated keys (#1310)
Adds support for returning generated keys.
---
.../spanner/jdbc/AbstractJdbcStatement.java | 38 ---
.../cloud/spanner/jdbc/JdbcConnection.java | 34 +-
.../spanner/jdbc/JdbcPreparedStatement.java | 23 +-
.../cloud/spanner/jdbc/JdbcStatement.java | 192 ++++++++---
.../spanner/jdbc/JdbcConnectionTest.java | 14 +-
.../jdbc/JdbcPreparedStatementTest.java | 21 +-
.../cloud/spanner/jdbc/JdbcStatementTest.java | 75 ++--
...mentReturnGeneratedKeysMockServerTest.java | 322 ++++++++++++++++++
...mentReturnGeneratedKeysMockServerTest.java | 322 ++++++++++++++++++
9 files changed, 888 insertions(+), 153 deletions(-)
create mode 100644 src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementReturnGeneratedKeysMockServerTest.java
create mode 100644 src/test/java/com/google/cloud/spanner/jdbc/StatementReturnGeneratedKeysMockServerTest.java
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java
index 2ee68afb2..e7b1a47f4 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java
@@ -24,7 +24,6 @@
import com.google.cloud.spanner.connection.Connection;
import com.google.cloud.spanner.connection.StatementResult;
import com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType;
-import com.google.rpc.Code;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
@@ -201,43 +200,6 @@ private ResultSet executeQuery(
}
}
- /**
- * Executes a SQL statement on the connection of this {@link Statement} as an update (DML)
- * statement.
- *
- * @param statement The SQL statement to execute
- * @return the number of rows that was inserted/updated/deleted
- * @throws SQLException if a database error occurs, or if the number of rows affected is larger
- * than {@link Integer#MAX_VALUE}
- */
- int executeUpdate(com.google.cloud.spanner.Statement statement) throws SQLException {
- long count = executeLargeUpdate(statement);
- if (count > Integer.MAX_VALUE) {
- throw JdbcSqlExceptionFactory.of(
- "update count too large for executeUpdate: " + count, Code.OUT_OF_RANGE);
- }
- return (int) count;
- }
-
- /**
- * Executes a SQL statement on the connection of this {@link Statement} as an update (DML)
- * statement.
- *
- * @param statement The SQL statement to execute
- * @return the number of rows that was inserted/updated/deleted
- * @throws SQLException if a database error occurs
- */
- long executeLargeUpdate(com.google.cloud.spanner.Statement statement) throws SQLException {
- StatementTimeout originalTimeout = setTemporaryStatementTimeout();
- try {
- return connection.getSpannerConnection().executeUpdate(statement);
- } catch (SpannerException e) {
- throw JdbcSqlExceptionFactory.of(e);
- } finally {
- resetStatementTimeout(originalTimeout);
- }
- }
-
/**
* Executes a SQL statement on the connection of this {@link Statement}. The SQL statement can be
* any supported SQL statement, including client side statements such as SET AUTOCOMMIT ON|OFF.
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java
index a710ac80b..6d6bd80d0 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java
@@ -16,6 +16,9 @@
package com.google.cloud.spanner.jdbc;
+import static com.google.cloud.spanner.jdbc.JdbcStatement.ALL_COLUMNS;
+import static com.google.cloud.spanner.jdbc.JdbcStatement.isNullOrEmpty;
+
import com.google.api.client.util.Preconditions;
import com.google.cloud.spanner.CommitResponse;
import com.google.cloud.spanner.Mutation;
@@ -25,6 +28,7 @@
import com.google.cloud.spanner.connection.ConnectionOptions;
import com.google.cloud.spanner.connection.SavepointSupport;
import com.google.cloud.spanner.connection.TransactionMode;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import java.sql.Array;
import java.sql.Blob;
@@ -49,9 +53,10 @@ class JdbcConnection extends AbstractJdbcConnection {
"Only result sets with concurrency CONCUR_READ_ONLY are supported";
private static final String ONLY_CLOSE_CURSORS_AT_COMMIT =
"Only result sets with holdability CLOSE_CURSORS_AT_COMMIT are supported";
- static final String ONLY_NO_GENERATED_KEYS = "Only NO_GENERATED_KEYS are supported";
static final String IS_VALID_QUERY = "SELECT 1";
+ static final ImmutableList NO_GENERATED_KEY_COLUMNS = ImmutableList.of();
+
private Map> typeMap = new HashMap<>();
JdbcConnection(String connectionUrl, ConnectionOptions options) throws SQLException {
@@ -66,8 +71,13 @@ public Statement createStatement() throws SQLException {
@Override
public JdbcPreparedStatement prepareStatement(String sql) throws SQLException {
+ return prepareStatement(sql, NO_GENERATED_KEY_COLUMNS);
+ }
+
+ private JdbcPreparedStatement prepareStatement(
+ String sql, ImmutableList generatedKeyColumns) throws SQLException {
checkClosed();
- return new JdbcPreparedStatement(this, sql);
+ return new JdbcPreparedStatement(this, sql, generatedKeyColumns);
}
@Override
@@ -299,22 +309,26 @@ public PreparedStatement prepareStatement(
@Override
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
- checkClosed();
- JdbcPreconditions.checkSqlFeatureSupported(
- autoGeneratedKeys == Statement.NO_GENERATED_KEYS, ONLY_NO_GENERATED_KEYS);
- return prepareStatement(sql);
+ return prepareStatement(
+ sql,
+ autoGeneratedKeys == Statement.RETURN_GENERATED_KEYS
+ ? ALL_COLUMNS
+ : NO_GENERATED_KEY_COLUMNS);
}
@Override
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
- checkClosed();
- return prepareStatement(sql);
+ // This should preferably have returned an error, but the initial version of the driver just
+ // accepted and ignored this. Starting to throw an error now would be a breaking change.
+ // TODO: Consider throwing an Unsupported error for the next major version bump.
+ return prepareStatement(sql, NO_GENERATED_KEY_COLUMNS);
}
@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
- checkClosed();
- return prepareStatement(sql);
+ return prepareStatement(
+ sql,
+ isNullOrEmpty(columnNames) ? NO_GENERATED_KEY_COLUMNS : ImmutableList.copyOf(columnNames));
}
@Override
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java
index a1b327b23..3ab302ce9 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java
@@ -24,7 +24,9 @@
import com.google.cloud.spanner.Type;
import com.google.cloud.spanner.connection.AbstractStatementParser.ParametersInfo;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.rpc.Code;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
@@ -36,8 +38,11 @@ class JdbcPreparedStatement extends AbstractJdbcPreparedStatement {
private final String sql;
private final String sqlWithoutComments;
private final ParametersInfo parameters;
+ private final ImmutableList generatedKeysColumns;
- JdbcPreparedStatement(JdbcConnection connection, String sql) throws SQLException {
+ JdbcPreparedStatement(
+ JdbcConnection connection, String sql, ImmutableList generatedKeysColumns)
+ throws SQLException {
super(connection);
this.sql = sql;
try {
@@ -47,6 +52,7 @@ class JdbcPreparedStatement extends AbstractJdbcPreparedStatement {
} catch (SpannerException e) {
throw JdbcSqlExceptionFactory.of(e);
}
+ this.generatedKeysColumns = Preconditions.checkNotNull(generatedKeysColumns);
}
ParametersInfo getParametersInfo() {
@@ -76,19 +82,22 @@ ResultSet executeQueryWithOptions(QueryOption... options) throws SQLException {
@Override
public int executeUpdate() throws SQLException {
- checkClosed();
- return executeUpdate(createStatement());
+ long count = executeLargeUpdate(createStatement(), generatedKeysColumns);
+ if (count > Integer.MAX_VALUE) {
+ throw JdbcSqlExceptionFactory.of(
+ "update count too large for executeUpdate: " + count, Code.OUT_OF_RANGE);
+ }
+ return (int) count;
}
+ @Override
public long executeLargeUpdate() throws SQLException {
- checkClosed();
- return executeLargeUpdate(createStatement());
+ return executeLargeUpdate(createStatement(), generatedKeysColumns);
}
@Override
public boolean execute() throws SQLException {
- checkClosed();
- return executeStatement(createStatement());
+ return executeStatement(createStatement(), generatedKeysColumns);
}
@Override
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java
index 3385ef012..6c6a45a15 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java
@@ -16,6 +16,8 @@
package com.google.cloud.spanner.jdbc;
+import static com.google.cloud.spanner.jdbc.JdbcConnection.NO_GENERATED_KEY_COLUMNS;
+
import com.google.cloud.spanner.Options;
import com.google.cloud.spanner.ResultSets;
import com.google.cloud.spanner.SpannerBatchUpdateException;
@@ -36,7 +38,6 @@
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
-import javax.annotation.Nullable;
/** Implementation of {@link java.sql.Statement} for Google Cloud Spanner. */
class JdbcStatement extends AbstractJdbcStatement {
@@ -49,6 +50,7 @@ enum BatchType {
}
private ResultSet currentResultSet;
+ private ResultSet currentGeneratedKeys;
private long currentUpdateCount;
private int fetchSize;
private BatchType currentBatchType = BatchType.NONE;
@@ -72,7 +74,12 @@ public ResultSet executeQuery(String sql) throws SQLException {
*/
@Override
public int executeUpdate(String sql) throws SQLException {
- long result = executeLargeUpdate(sql);
+ return executeUpdate(sql, NO_GENERATED_KEY_COLUMNS);
+ }
+
+ private int executeUpdate(String sql, ImmutableList generatedKeysColumns)
+ throws SQLException {
+ long result = executeLargeUpdate(sql, generatedKeysColumns);
if (result > Integer.MAX_VALUE) {
throw JdbcSqlExceptionFactory.of("update count too large: " + result, Code.OUT_OF_RANGE);
}
@@ -87,14 +94,33 @@ public int executeUpdate(String sql) throws SQLException {
*/
@Override
public long executeLargeUpdate(String sql) throws SQLException {
+ return executeLargeUpdate(sql, NO_GENERATED_KEY_COLUMNS);
+ }
+
+ private long executeLargeUpdate(String sql, ImmutableList generatedKeysColumns)
+ throws SQLException {
+ return executeLargeUpdate(Statement.of(sql), generatedKeysColumns);
+ }
+
+ protected long executeLargeUpdate(Statement statement, ImmutableList generatedKeysColumns)
+ throws SQLException {
+ Preconditions.checkNotNull(generatedKeysColumns);
checkClosed();
- Statement statement = Statement.of(sql);
- StatementResult result = execute(statement);
+ Statement statementWithReturningClause =
+ addReturningToStatement(statement, generatedKeysColumns);
+ StatementResult result = execute(statementWithReturningClause);
switch (result.getResultType()) {
case RESULT_SET:
- // Close the result set as we are not going to return it to the user. This prevents the
- // underlying session from potentially being leaked.
- throw closeResultSetAndCreateInvalidQueryException(result);
+ if (generatedKeysColumns.isEmpty()) {
+ // Close the result set as we are not going to return it to the user. This prevents the
+ // underlying session from potentially being leaked.
+ throw closeResultSetAndCreateInvalidQueryException(result);
+ }
+ // Make a copy of the result set as it does not matter if the user does not close the result
+ // set. This also consumes all rows of the result set, which again means that it is safe to
+ // extract the update count.
+ this.currentGeneratedKeys = JdbcResultSet.copyOf(result.getResultSet());
+ return extractUpdateCountAndClose(result.getResultSet());
case UPDATE_COUNT:
return result.getUpdateCount();
case NO_RESULT:
@@ -105,6 +131,35 @@ public long executeLargeUpdate(String sql) throws SQLException {
}
}
+ /**
+ * Extracts the update count from the given result set and then closes the result set. This method
+ * may only be called for a {@link com.google.cloud.spanner.ResultSet} where all rows have been
+ * fetched. That is; {@link com.google.cloud.spanner.ResultSet#next()} must have returned false.
+ */
+ private long extractUpdateCountAndClose(com.google.cloud.spanner.ResultSet resultSet)
+ throws SQLException {
+ try {
+ if (resultSet.getStats() == null) {
+ throw JdbcSqlExceptionFactory.of(
+ "Result does not contain any stats", Code.FAILED_PRECONDITION);
+ }
+ long updateCount;
+ if (resultSet.getStats().hasRowCountExact()) {
+ updateCount = resultSet.getStats().getRowCountExact();
+ } else if (resultSet.getStats().hasRowCountLowerBound()) {
+ // This is returned by Cloud Spanner if the user had set the autocommit_dml_mode to
+ // 'partitioned_non_atomic' (i.e. PDML).
+ updateCount = resultSet.getStats().getRowCountLowerBound();
+ } else {
+ throw JdbcSqlExceptionFactory.of(
+ "Result does not contain an update count", Code.FAILED_PRECONDITION);
+ }
+ return updateCount;
+ } finally {
+ resultSet.close();
+ }
+ }
+
private SQLException closeResultSetAndCreateInvalidQueryException(StatementResult result) {
//noinspection finally
try {
@@ -121,15 +176,14 @@ private SQLException closeResultSetAndCreateInvalidQueryException(StatementResul
* met:
*
*
- * - The generatedKeysColumns is not null or empty
+ *
- The generatedKeysColumns is not empty
*
- The statement is a DML statement
*
- The DML statement does not already contain a THEN RETURN/RETURNING clause
*
*/
- Statement addReturningToStatement(
- Statement statement, @Nullable ImmutableList generatedKeysColumns)
+ Statement addReturningToStatement(Statement statement, ImmutableList generatedKeysColumns)
throws SQLException {
- if (generatedKeysColumns == null || generatedKeysColumns.isEmpty()) {
+ if (Preconditions.checkNotNull(generatedKeysColumns).isEmpty()) {
return statement;
}
// Check if the statement is a DML statement or not.
@@ -193,17 +247,30 @@ String quoteColumn(String column) {
@Override
public boolean execute(String sql) throws SQLException {
- checkClosed();
- return executeStatement(Statement.of(sql));
+ return executeStatement(Statement.of(sql), NO_GENERATED_KEY_COLUMNS);
}
- boolean executeStatement(Statement statement) throws SQLException {
- StatementResult result = execute(statement);
+ boolean executeStatement(Statement statement, ImmutableList generatedKeysColumns)
+ throws SQLException {
+ checkClosed();
+ // This will return the same Statement instance if no THEN RETURN clause is added to the
+ // statement.
+ Statement statementWithReturning = addReturningToStatement(statement, generatedKeysColumns);
+ StatementResult result = execute(statementWithReturning);
switch (result.getResultType()) {
case RESULT_SET:
- currentResultSet = JdbcResultSet.of(this, result.getResultSet());
- currentUpdateCount = JdbcConstants.STATEMENT_RESULT_SET;
- return true;
+ // Check whether the statement was modified to include a RETURNING clause for generated
+ // keys. If so, then we return the result as an update count and the rows as the generated
+ // keys. We can safely use '==', as the addReturningToStatement(..) method returns the same
+ // instance if no generated keys were requested.
+ if (statementWithReturning == statement) {
+ currentResultSet = JdbcResultSet.of(this, result.getResultSet());
+ currentUpdateCount = JdbcConstants.STATEMENT_RESULT_SET;
+ return true;
+ }
+ this.currentGeneratedKeys = JdbcResultSet.copyOf(result.getResultSet());
+ this.currentUpdateCount = extractUpdateCountAndClose(result.getResultSet());
+ return false;
case UPDATE_COUNT:
currentResultSet = null;
currentUpdateCount = result.getUpdateCount();
@@ -441,77 +508,94 @@ void convertUpdateCountsToSuccessNoInfo(long[] updateCounts, long[] res) {
@Override
public ResultSet getGeneratedKeys() throws SQLException {
checkClosed();
- // Return an empty result set instead of throwing an exception, to facilitate any application
- // that might not check on beforehand whether the driver supports any generated keys.
- com.google.cloud.spanner.ResultSet rs =
- ResultSets.forRows(
- Type.struct(
- StructField.of("COLUMN_NAME", Type.string()),
- StructField.of("VALUE", Type.int64())),
- Collections.emptyList());
- return JdbcResultSet.of(rs);
+ if (this.currentGeneratedKeys == null) {
+ // Return an empty result set instead of throwing an exception, as that is what the JDBC spec
+ // says we should do. Note that we need to create a new instance every time, as users could in
+ // theory call close() on the returned result set.
+ this.currentGeneratedKeys =
+ JdbcResultSet.of(
+ ResultSets.forRows(
+ Type.struct(
+ StructField.of("COLUMN_NAME", Type.string()),
+ StructField.of("VALUE", Type.int64())),
+ Collections.emptyList()));
+ }
+ return this.currentGeneratedKeys;
}
@Override
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
- checkClosed();
- JdbcPreconditions.checkSqlFeatureSupported(
- autoGeneratedKeys == java.sql.Statement.NO_GENERATED_KEYS,
- JdbcConnection.ONLY_NO_GENERATED_KEYS);
- return executeUpdate(sql);
+ return executeUpdate(
+ sql,
+ autoGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS
+ ? ALL_COLUMNS
+ : NO_GENERATED_KEY_COLUMNS);
}
@Override
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
- checkClosed();
- return executeUpdate(sql);
+ // This should preferably have returned an error, but the initial version of the driver just
+ // accepted and ignored this. Starting to throw an error now would be a breaking change.
+ // TODO: Consider throwing an Unsupported error for the next major version bump.
+ return executeUpdate(sql, NO_GENERATED_KEY_COLUMNS);
}
@Override
public int executeUpdate(String sql, String[] columnNames) throws SQLException {
- checkClosed();
- return executeUpdate(sql);
+ return executeUpdate(
+ sql,
+ isNullOrEmpty(columnNames) ? NO_GENERATED_KEY_COLUMNS : ImmutableList.copyOf(columnNames));
}
@Override
public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
- checkClosed();
- JdbcPreconditions.checkSqlFeatureSupported(
- autoGeneratedKeys == java.sql.Statement.NO_GENERATED_KEYS,
- JdbcConnection.ONLY_NO_GENERATED_KEYS);
- return executeLargeUpdate(sql);
+ return executeLargeUpdate(
+ sql,
+ autoGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS
+ ? ALL_COLUMNS
+ : NO_GENERATED_KEY_COLUMNS);
}
@Override
public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException {
- checkClosed();
- return executeLargeUpdate(sql);
+ // This should preferably have returned an error, but the initial version of the driver just
+ // accepted and ignored this. Starting to throw an error now would be a breaking change.
+ // TODO: Consider throwing an Unsupported error for the next major version bump.
+ return executeLargeUpdate(sql, NO_GENERATED_KEY_COLUMNS);
}
@Override
public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException {
- checkClosed();
- return executeLargeUpdate(sql);
+ return executeLargeUpdate(
+ sql,
+ isNullOrEmpty(columnNames) ? NO_GENERATED_KEY_COLUMNS : ImmutableList.copyOf(columnNames));
}
@Override
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
- checkClosed();
- JdbcPreconditions.checkSqlFeatureSupported(
- autoGeneratedKeys == java.sql.Statement.NO_GENERATED_KEYS,
- JdbcConnection.ONLY_NO_GENERATED_KEYS);
- return execute(sql);
+ return executeStatement(
+ Statement.of(sql),
+ autoGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS
+ ? ALL_COLUMNS
+ : NO_GENERATED_KEY_COLUMNS);
}
@Override
public boolean execute(String sql, int[] columnIndexes) throws SQLException {
- checkClosed();
- return execute(sql);
+ // This should preferably have returned an error, but the initial version of the driver just
+ // accepted and ignored this. Starting to throw an error now would be a breaking change.
+ // TODO: Consider throwing an Unsupported error for the next major version bump.
+ return executeStatement(Statement.of(sql), NO_GENERATED_KEY_COLUMNS);
}
@Override
public boolean execute(String sql, String[] columnNames) throws SQLException {
- checkClosed();
- return execute(sql);
+ return executeStatement(
+ Statement.of(sql),
+ isNullOrEmpty(columnNames) ? NO_GENERATED_KEY_COLUMNS : ImmutableList.copyOf(columnNames));
+ }
+
+ static boolean isNullOrEmpty(String[] columnNames) {
+ return columnNames == null || columnNames.length == 0;
}
}
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java
index 8010c2151..592d40409 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java
@@ -686,14 +686,12 @@ public void testPrepareStatementWithAutoGeneratedKeys() throws SQLException {
try (JdbcConnection connection = createConnection(mockOptions())) {
PreparedStatement statement =
connection.prepareStatement(sql, java.sql.Statement.NO_GENERATED_KEYS);
- ResultSet rs = statement.getGeneratedKeys();
- assertThat(rs.next()).isFalse();
- try {
- statement = connection.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS);
- fail("missing expected SQLFeatureNotSupportedException");
- } catch (SQLFeatureNotSupportedException e) {
- // ignore, this is the expected exception.
- }
+ ResultSet generatedKeys = statement.getGeneratedKeys();
+ assertFalse(generatedKeys.next());
+
+ statement = connection.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS);
+ generatedKeys = statement.getGeneratedKeys();
+ assertFalse(generatedKeys.next());
}
}
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java
index 8f21e68d3..310d1546e 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java
@@ -16,6 +16,7 @@
package com.google.cloud.spanner.jdbc;
+import static com.google.cloud.spanner.jdbc.JdbcConnection.NO_GENERATED_KEY_COLUMNS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
@@ -142,7 +143,8 @@ public void testValueAsParameter() throws SQLException {
Collections.singleton(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(999L, 99))),
}) {
- try (JdbcPreparedStatement ps = new JdbcPreparedStatement(connection, sql)) {
+ try (JdbcPreparedStatement ps =
+ new JdbcPreparedStatement(connection, sql, NO_GENERATED_KEY_COLUMNS)) {
ps.setObject(1, value);
Statement statement = ps.createStatement();
assertEquals(statement.getParameters().get("p1"), value);
@@ -157,7 +159,8 @@ public void testParameters() throws SQLException, MalformedURLException {
String sql = generateSqlWithParameters(numberOfParams);
JdbcConnection connection = createMockConnection();
- try (JdbcPreparedStatement ps = new JdbcPreparedStatement(connection, sql)) {
+ try (JdbcPreparedStatement ps =
+ new JdbcPreparedStatement(connection, sql, NO_GENERATED_KEY_COLUMNS)) {
ps.setArray(1, connection.createArrayOf("INT64", new Long[] {1L, 2L, 3L}));
ps.setAsciiStream(2, new ByteArrayInputStream("TEST".getBytes()));
ps.setAsciiStream(3, new ByteArrayInputStream("TEST".getBytes()), 4);
@@ -276,7 +279,8 @@ public void testParameters() throws SQLException, MalformedURLException {
public void testSetNullValues() throws SQLException {
final int numberOfParameters = 31;
String sql = generateSqlWithParameters(numberOfParameters);
- try (JdbcPreparedStatement ps = new JdbcPreparedStatement(createMockConnection(), sql)) {
+ try (JdbcPreparedStatement ps =
+ new JdbcPreparedStatement(createMockConnection(), sql, NO_GENERATED_KEY_COLUMNS)) {
int index = 0;
ps.setNull(++index, Types.BLOB);
ps.setNull(++index, Types.NVARCHAR);
@@ -350,7 +354,8 @@ public void testGetResultSetMetadata() throws SQLException {
.build()));
when(connection.analyzeQuery(Statement.of(sql), QueryAnalyzeMode.PLAN)).thenReturn(rs);
try (JdbcPreparedStatement ps =
- new JdbcPreparedStatement(createMockConnection(connection), sql)) {
+ new JdbcPreparedStatement(
+ createMockConnection(connection), sql, NO_GENERATED_KEY_COLUMNS)) {
ResultSetMetaData metadata = ps.getMetaData();
assertEquals(4, metadata.getColumnCount());
assertEquals("ID", metadata.getColumnLabel(1));
@@ -369,7 +374,9 @@ public void testGetResultSetMetaDataForDml() throws SQLException {
Connection connection = mock(Connection.class);
try (JdbcPreparedStatement ps =
new JdbcPreparedStatement(
- createMockConnection(connection), "UPDATE FOO SET BAR=1 WHERE TRUE")) {
+ createMockConnection(connection),
+ "UPDATE FOO SET BAR=1 WHERE TRUE",
+ NO_GENERATED_KEY_COLUMNS)) {
ResultSetMetaData metadata = ps.getMetaData();
assertEquals(0, metadata.getColumnCount());
}
@@ -381,7 +388,9 @@ public void testInvalidSql() {
SQLException sqlException =
assertThrows(
SQLException.class,
- () -> new JdbcPreparedStatement(createMockConnection(mock(Connection.class)), sql));
+ () ->
+ new JdbcPreparedStatement(
+ createMockConnection(mock(Connection.class)), sql, NO_GENERATED_KEY_COLUMNS));
assertTrue(sqlException instanceof JdbcSqlException);
JdbcSqlException jdbcSqlException = (JdbcSqlException) sqlException;
assertEquals(
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java
index d44583587..727e63acf 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java
@@ -16,6 +16,7 @@
package com.google.cloud.spanner.jdbc;
+import static com.google.cloud.spanner.jdbc.JdbcConnection.NO_GENERATED_KEY_COLUMNS;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -44,7 +45,6 @@
import com.google.rpc.Code;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.List;
@@ -101,6 +101,10 @@ private JdbcStatement createStatement() throws SQLException {
when(updateResult.getResultType()).thenReturn(ResultType.UPDATE_COUNT);
when(updateResult.getUpdateCount()).thenReturn(1L);
when(spanner.execute(com.google.cloud.spanner.Statement.of(UPDATE))).thenReturn(updateResult);
+ when(spanner.execute(com.google.cloud.spanner.Statement.of(UPDATE + "\nTHEN RETURN *")))
+ .thenReturn(updateResult);
+ when(spanner.execute(com.google.cloud.spanner.Statement.of(UPDATE + "\nRETURNING *")))
+ .thenReturn(updateResult);
StatementResult largeUpdateResult = mock(StatementResult.class);
when(largeUpdateResult.getResultType()).thenReturn(ResultType.UPDATE_COUNT);
@@ -274,15 +278,14 @@ public void testExecuteWithDmlReturningStatement() throws SQLException {
@Test
public void testExecuteWithGeneratedKeys() throws SQLException {
- Statement statement = createStatement();
- assertThat(statement.execute(UPDATE, Statement.NO_GENERATED_KEYS)).isFalse();
- ResultSet keys = statement.getGeneratedKeys();
- assertThat(keys.next()).isFalse();
- try {
+ try (Statement statement = createStatement()) {
+ assertFalse(statement.execute(UPDATE, Statement.NO_GENERATED_KEYS));
+ ResultSet keys = statement.getGeneratedKeys();
+ assertFalse(keys.next());
+
statement.execute(UPDATE, Statement.RETURN_GENERATED_KEYS);
- fail("missing expected exception");
- } catch (SQLFeatureNotSupportedException e) {
- // Ignore, this is the expected exception.
+ keys = statement.getGeneratedKeys();
+ assertFalse(keys.next());
}
}
@@ -357,12 +360,18 @@ public void testInternalExecuteUpdate() throws SQLException {
com.google.cloud.spanner.Statement.of(UPDATE);
com.google.cloud.spanner.Statement largeUpdateStatement =
com.google.cloud.spanner.Statement.of(LARGE_UPDATE);
- when(spannerConnection.executeUpdate(updateStatement)).thenReturn(1L);
- when(spannerConnection.executeUpdate(largeUpdateStatement)).thenReturn(Integer.MAX_VALUE + 1L);
+ StatementResult updateResult = mock(StatementResult.class);
+ when(updateResult.getUpdateCount()).thenReturn(1L);
+ when(updateResult.getResultType()).thenReturn(ResultType.UPDATE_COUNT);
+ when(spannerConnection.execute(updateStatement)).thenReturn(updateResult);
+ StatementResult largeUpdateResult = mock(StatementResult.class);
+ when(largeUpdateResult.getUpdateCount()).thenReturn(Integer.MAX_VALUE + 1L);
+ when(largeUpdateResult.getResultType()).thenReturn(ResultType.UPDATE_COUNT);
+ when(spannerConnection.execute(largeUpdateStatement)).thenReturn(largeUpdateResult);
try (JdbcStatement statement = new JdbcStatement(connection)) {
- assertThat(statement.executeUpdate(updateStatement)).isEqualTo(1);
+ assertThat(statement.executeUpdate(UPDATE)).isEqualTo(1);
try {
- statement.executeUpdate(largeUpdateStatement);
+ statement.executeUpdate(LARGE_UPDATE);
fail("missing expected exception");
} catch (JdbcSqlExceptionImpl e) {
assertThat(e.getCode()).isEqualTo(Code.OUT_OF_RANGE);
@@ -380,12 +389,17 @@ public void testInternalExecuteLargeUpdate() throws SQLException {
com.google.cloud.spanner.Statement.of(UPDATE);
com.google.cloud.spanner.Statement largeUpdateStatement =
com.google.cloud.spanner.Statement.of(LARGE_UPDATE);
- when(spannerConnection.executeUpdate(updateStatement)).thenReturn(1L);
- when(spannerConnection.executeUpdate(largeUpdateStatement)).thenReturn(Integer.MAX_VALUE + 1L);
+ StatementResult updateResult = mock(StatementResult.class);
+ when(updateResult.getUpdateCount()).thenReturn(1L);
+ when(updateResult.getResultType()).thenReturn(ResultType.UPDATE_COUNT);
+ when(spannerConnection.execute(updateStatement)).thenReturn(updateResult);
+ StatementResult largeUpdateResult = mock(StatementResult.class);
+ when(largeUpdateResult.getUpdateCount()).thenReturn(Integer.MAX_VALUE + 1L);
+ when(largeUpdateResult.getResultType()).thenReturn(ResultType.UPDATE_COUNT);
+ when(spannerConnection.execute(largeUpdateStatement)).thenReturn(largeUpdateResult);
try (JdbcStatement statement = new JdbcStatement(connection)) {
- assertThat(statement.executeLargeUpdate(updateStatement)).isEqualTo(1);
- assertThat(statement.executeLargeUpdate(largeUpdateStatement))
- .isEqualTo(Integer.MAX_VALUE + 1L);
+ assertThat(statement.executeLargeUpdate(UPDATE)).isEqualTo(1);
+ assertThat(statement.executeLargeUpdate(LARGE_UPDATE)).isEqualTo(Integer.MAX_VALUE + 1L);
}
}
@@ -448,15 +462,14 @@ public void testExecuteUpdateWithDdlStatement() throws SQLException {
@Test
public void testExecuteUpdateWithGeneratedKeys() throws SQLException {
- Statement statement = createStatement();
- assertThat(statement.executeUpdate(UPDATE, Statement.NO_GENERATED_KEYS)).isEqualTo(1);
- ResultSet keys = statement.getGeneratedKeys();
- assertThat(keys.next()).isFalse();
- try {
- statement.executeUpdate(UPDATE, Statement.RETURN_GENERATED_KEYS);
- fail("missing expected exception");
- } catch (SQLFeatureNotSupportedException e) {
- // Ignore, this is the expected exception.
+ try (Statement statement = createStatement()) {
+ assertEquals(1, statement.executeUpdate(UPDATE, Statement.NO_GENERATED_KEYS));
+ ResultSet keys = statement.getGeneratedKeys();
+ assertFalse(keys.next());
+
+ assertEquals(1, statement.executeUpdate(UPDATE, Statement.RETURN_GENERATED_KEYS));
+ keys = statement.getGeneratedKeys();
+ assertFalse(keys.next());
}
}
@@ -609,7 +622,8 @@ public void testAddReturningToStatement() throws SQLException {
when(connection.getDialect()).thenReturn(dialect);
when(connection.getParser()).thenReturn(AbstractStatementParser.getInstance(dialect));
try (JdbcStatement statement = new JdbcStatement(connection)) {
- assertAddReturningSame(statement, "insert into test (id, value) values (1, 'One')", null);
+ assertAddReturningSame(
+ statement, "insert into test (id, value) values (1, 'One')", NO_GENERATED_KEY_COLUMNS);
assertAddReturningSame(
statement, "insert into test (id, value) values (1, 'One')", ImmutableList.of());
assertAddReturningEquals(
@@ -649,7 +663,8 @@ public void testAddReturningToStatement() throws SQLException {
}
// Update statements may also request generated keys.
- assertAddReturningSame(statement, "update test set value='Two' where id=1", null);
+ assertAddReturningSame(
+ statement, "update test set value='Two' where id=1", NO_GENERATED_KEY_COLUMNS);
assertAddReturningSame(
statement, "update test set value='Two' where id=1", ImmutableList.of());
assertAddReturningEquals(
@@ -681,7 +696,7 @@ public void testAddReturningToStatement() throws SQLException {
ImmutableList.of("value"));
// Delete statements may also request generated keys.
- assertAddReturningSame(statement, "delete test where id=1", null);
+ assertAddReturningSame(statement, "delete test where id=1", NO_GENERATED_KEY_COLUMNS);
assertAddReturningSame(statement, "delete test where id=1", ImmutableList.of());
assertAddReturningEquals(
statement,
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementReturnGeneratedKeysMockServerTest.java b/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementReturnGeneratedKeysMockServerTest.java
new file mode 100644
index 000000000..b88428bdf
--- /dev/null
+++ b/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementReturnGeneratedKeysMockServerTest.java
@@ -0,0 +1,322 @@
+/*
+ * 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.spanner.jdbc;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.cloud.spanner.Dialect;
+import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult;
+import com.google.cloud.spanner.Statement;
+import com.google.cloud.spanner.connection.AbstractMockServerTest;
+import com.google.cloud.spanner.connection.RandomResultSetGenerator;
+import com.google.cloud.spanner.connection.SpannerPool;
+import com.google.common.collect.ImmutableList;
+import com.google.longrunning.Operation;
+import com.google.protobuf.Any;
+import com.google.protobuf.Empty;
+import com.google.protobuf.ListValue;
+import com.google.protobuf.Value;
+import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
+import com.google.spanner.v1.ResultSetMetadata;
+import com.google.spanner.v1.ResultSetStats;
+import com.google.spanner.v1.StructType;
+import com.google.spanner.v1.StructType.Field;
+import com.google.spanner.v1.Type;
+import com.google.spanner.v1.TypeCode;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class PreparedStatementReturnGeneratedKeysMockServerTest extends AbstractMockServerTest {
+ @Parameter public Dialect dialect;
+
+ @Parameters(name = "dialect = {0}")
+ public static Object[] data() {
+ return Dialect.values();
+ }
+
+ @Before
+ public void setupDialect() {
+ mockSpanner.putStatementResult(StatementResult.detectDialectResult(this.dialect));
+ }
+
+ @After
+ public void clearRequests() {
+ mockSpanner.clearRequests();
+ // Close Spanner pool to force a refresh of the dialect of a given database.
+ SpannerPool.closeSpannerPool();
+ }
+
+ private String createUrl() {
+ return String.format(
+ "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true",
+ getPort(), "proj", "inst", "db");
+ }
+
+ private Connection createConnection() throws SQLException {
+ return DriverManager.getConnection(createUrl());
+ }
+
+ interface SqlRunnable {
+ void run() throws SQLException;
+ }
+
+ @Test
+ public void testReturnAutoGeneratedKeys() throws SQLException {
+ String sql = "insert into test (id, value) values (1, 'One')";
+ String returningClause = dialect == Dialect.POSTGRESQL ? "\nRETURNING *" : "\nTHEN RETURN *";
+ mockSpanner.putStatementResult(
+ StatementResult.query(
+ Statement.of(sql + returningClause),
+ com.google.spanner.v1.ResultSet.newBuilder()
+ .setMetadata(
+ ResultSetMetadata.newBuilder()
+ .setRowType(
+ StructType.newBuilder()
+ .addFields(
+ Field.newBuilder()
+ .setName("id")
+ .setType(Type.newBuilder().setCode(TypeCode.INT64).build())
+ .build())
+ .addFields(
+ Field.newBuilder()
+ .setName("value")
+ .setType(Type.newBuilder().setCode(TypeCode.STRING).build())
+ .build())
+ .build())
+ .build())
+ .addRows(
+ ListValue.newBuilder()
+ .addValues(Value.newBuilder().setStringValue("1").build())
+ .addValues(Value.newBuilder().setStringValue("One").build())
+ .build())
+ .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build())
+ .build()));
+
+ try (Connection connection = createConnection();
+ PreparedStatement statement =
+ connection.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS)) {
+ for (SqlRunnable runnable :
+ ImmutableList.of(
+ () -> assertEquals(1, statement.executeUpdate()),
+ () -> assertEquals(1L, statement.executeLargeUpdate()),
+ () -> {
+ assertFalse(statement.execute());
+ assertEquals(1, statement.getUpdateCount());
+ assertEquals(1L, statement.getLargeUpdateCount());
+ })) {
+ runnable.run();
+ assertNotNull(statement.getGeneratedKeys());
+ assertEquals(2, statement.getGeneratedKeys().getMetaData().getColumnCount());
+ assertEquals(Types.BIGINT, statement.getGeneratedKeys().getMetaData().getColumnType(1));
+ assertEquals(Types.NVARCHAR, statement.getGeneratedKeys().getMetaData().getColumnType(2));
+ assertEquals("id", statement.getGeneratedKeys().getMetaData().getColumnName(1));
+ assertEquals("value", statement.getGeneratedKeys().getMetaData().getColumnName(2));
+ try (ResultSet keys = statement.getGeneratedKeys()) {
+ assertTrue(keys.next());
+ assertEquals(1L, keys.getLong(1));
+ assertEquals("One", keys.getString(2));
+ assertFalse(keys.next());
+ }
+ // There should be no more results for this statement.
+ assertFalse(statement.getMoreResults());
+ assertEquals(-1, statement.getUpdateCount());
+ }
+ }
+ }
+
+ @Test
+ public void testReturnColumnNames() throws SQLException {
+ String sql = "insert into test (id, value) values (1, 'One')";
+ String returningClause =
+ dialect == Dialect.POSTGRESQL ? "\nRETURNING \"id\"" : "\nTHEN RETURN `id`";
+ mockSpanner.putStatementResult(
+ StatementResult.query(
+ Statement.of(sql + returningClause),
+ com.google.spanner.v1.ResultSet.newBuilder()
+ .setMetadata(
+ ResultSetMetadata.newBuilder()
+ .setRowType(
+ StructType.newBuilder()
+ .addFields(
+ Field.newBuilder()
+ .setName("id")
+ .setType(Type.newBuilder().setCode(TypeCode.INT64).build())
+ .build())
+ .build())
+ .build())
+ .addRows(
+ ListValue.newBuilder()
+ .addValues(Value.newBuilder().setStringValue("1").build())
+ .build())
+ .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build())
+ .build()));
+
+ try (Connection connection = createConnection();
+ PreparedStatement statement = connection.prepareStatement(sql, new String[] {"id"})) {
+ for (SqlRunnable runnable :
+ ImmutableList.of(
+ () -> assertEquals(1, statement.executeUpdate()),
+ () -> assertEquals(1L, statement.executeLargeUpdate()),
+ () -> {
+ assertFalse(statement.execute());
+ assertEquals(1, statement.getUpdateCount());
+ assertEquals(1L, statement.getLargeUpdateCount());
+ })) {
+ runnable.run();
+ assertNotNull(statement.getGeneratedKeys());
+ assertEquals(1, statement.getGeneratedKeys().getMetaData().getColumnCount());
+ assertEquals(Types.BIGINT, statement.getGeneratedKeys().getMetaData().getColumnType(1));
+ assertEquals("id", statement.getGeneratedKeys().getMetaData().getColumnName(1));
+ try (ResultSet keys = statement.getGeneratedKeys()) {
+ assertTrue(keys.next());
+ assertEquals(1L, keys.getLong(1));
+ assertFalse(keys.next());
+ }
+ // There should be no more results for this statement.
+ assertFalse(statement.getMoreResults());
+ assertEquals(-1, statement.getUpdateCount());
+ }
+ }
+ }
+
+ @Test
+ public void testReturnColumnIndices() throws SQLException {
+ String sql = "insert into test (id, value) values (1, 'One')";
+ mockSpanner.putStatementResult(StatementResult.update(Statement.of(sql), 1L));
+
+ try (Connection connection = createConnection();
+ PreparedStatement statement = connection.prepareStatement(sql, new int[] {1})) {
+ // The JDBC driver silently ignores the request for column indices.
+ for (SqlRunnable runnable :
+ ImmutableList.of(
+ () -> assertEquals(1, statement.executeUpdate()),
+ () -> assertEquals(1L, statement.executeLargeUpdate()),
+ () -> {
+ assertFalse(statement.execute());
+ assertEquals(1, statement.getUpdateCount());
+ assertEquals(1L, statement.getLargeUpdateCount());
+ })) {
+ runnable.run();
+ assertNotNull(statement.getGeneratedKeys());
+ assertFalse(statement.getGeneratedKeys().next());
+ }
+ }
+ }
+
+ @Test
+ public void testReturnGeneratedKeysForQuery() throws SQLException {
+ String sql = "select * from test";
+ RandomResultSetGenerator generator = new RandomResultSetGenerator(1);
+ mockSpanner.putStatementResult(StatementResult.query(Statement.of(sql), generator.generate()));
+
+ try (Connection connection = createConnection();
+ PreparedStatement statement =
+ connection.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS)) {
+ assertTrue(statement.execute());
+ try (ResultSet resultSet = statement.getResultSet()) {
+ assertTrue(resultSet.next());
+ assertFalse(resultSet.next());
+ }
+ // Statements without generated keys return an empty result set.
+ assertFalse(statement.getGeneratedKeys().next());
+ }
+ }
+
+ @Test
+ public void testReturnGeneratedKeysForDdl() throws SQLException {
+ String sql = "create table test";
+ addDdlResponseToSpannerAdmin();
+
+ try (Connection connection = createConnection();
+ PreparedStatement statement =
+ connection.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS)) {
+ assertFalse(statement.execute());
+ assertEquals(java.sql.Statement.SUCCESS_NO_INFO, statement.getUpdateCount());
+ // Statements without generated keys return an empty result set.
+ assertFalse(statement.getGeneratedKeys().next());
+ }
+ }
+
+ @Test
+ public void testReturnAutoGeneratedKeysForStatementWithReturning() throws SQLException {
+ String sql =
+ "insert into test (id, value) values (1, 'One') "
+ + (dialect == Dialect.POSTGRESQL ? "RETURNING value" : "THEN RETURN value");
+ mockSpanner.putStatementResult(
+ StatementResult.query(
+ Statement.of(sql),
+ com.google.spanner.v1.ResultSet.newBuilder()
+ .setMetadata(
+ ResultSetMetadata.newBuilder()
+ .setRowType(
+ StructType.newBuilder()
+ .addFields(
+ Field.newBuilder()
+ .setName("value")
+ .setType(Type.newBuilder().setCode(TypeCode.STRING).build())
+ .build())
+ .build())
+ .build())
+ .addRows(
+ ListValue.newBuilder()
+ .addValues(Value.newBuilder().setStringValue("One").build())
+ .build())
+ .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build())
+ .build()));
+
+ try (Connection connection = createConnection();
+ PreparedStatement statement =
+ connection.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS)) {
+ assertTrue(statement.execute());
+ try (ResultSet resultSet = statement.getResultSet()) {
+ assertTrue(resultSet.next());
+ assertEquals("One", resultSet.getString(1));
+ assertFalse(resultSet.next());
+ }
+
+ assertNotNull(statement.getGeneratedKeys());
+ assertFalse(statement.getGeneratedKeys().next());
+ // There should be no more results for this statement.
+ assertFalse(statement.getMoreResults());
+ assertEquals(-1, statement.getUpdateCount());
+ }
+ }
+
+ private void addDdlResponseToSpannerAdmin() {
+ mockDatabaseAdmin.addResponse(
+ Operation.newBuilder()
+ .setDone(true)
+ .setResponse(Any.pack(Empty.getDefaultInstance()))
+ .setMetadata(Any.pack(UpdateDatabaseDdlMetadata.getDefaultInstance()))
+ .build());
+ }
+}
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/StatementReturnGeneratedKeysMockServerTest.java b/src/test/java/com/google/cloud/spanner/jdbc/StatementReturnGeneratedKeysMockServerTest.java
new file mode 100644
index 000000000..9cd9068dc
--- /dev/null
+++ b/src/test/java/com/google/cloud/spanner/jdbc/StatementReturnGeneratedKeysMockServerTest.java
@@ -0,0 +1,322 @@
+/*
+ * 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.spanner.jdbc;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.cloud.spanner.Dialect;
+import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult;
+import com.google.cloud.spanner.Statement;
+import com.google.cloud.spanner.connection.AbstractMockServerTest;
+import com.google.cloud.spanner.connection.RandomResultSetGenerator;
+import com.google.cloud.spanner.connection.SpannerPool;
+import com.google.common.collect.ImmutableList;
+import com.google.longrunning.Operation;
+import com.google.protobuf.Any;
+import com.google.protobuf.Empty;
+import com.google.protobuf.ListValue;
+import com.google.protobuf.Value;
+import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
+import com.google.spanner.v1.ResultSetMetadata;
+import com.google.spanner.v1.ResultSetStats;
+import com.google.spanner.v1.StructType;
+import com.google.spanner.v1.StructType.Field;
+import com.google.spanner.v1.Type;
+import com.google.spanner.v1.TypeCode;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class StatementReturnGeneratedKeysMockServerTest extends AbstractMockServerTest {
+ @Parameter public Dialect dialect;
+
+ @Parameters(name = "dialect = {0}")
+ public static Object[] data() {
+ return Dialect.values();
+ }
+
+ @Before
+ public void setupDialect() {
+ mockSpanner.putStatementResult(StatementResult.detectDialectResult(this.dialect));
+ }
+
+ @After
+ public void clearRequests() {
+ mockSpanner.clearRequests();
+ // Close Spanner pool to force a refresh of the dialect of a given database.
+ SpannerPool.closeSpannerPool();
+ }
+
+ private String createUrl() {
+ return String.format(
+ "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true",
+ getPort(), "proj", "inst", "db");
+ }
+
+ private Connection createConnection() throws SQLException {
+ return DriverManager.getConnection(createUrl());
+ }
+
+ interface SqlRunnable {
+ void run() throws SQLException;
+ }
+
+ @Test
+ public void testReturnAutoGeneratedKeys() throws SQLException {
+ String sql = "insert into test (id, value) values (1, 'One')";
+ String returningClause = dialect == Dialect.POSTGRESQL ? "\nRETURNING *" : "\nTHEN RETURN *";
+ mockSpanner.putStatementResult(
+ StatementResult.query(
+ Statement.of(sql + returningClause),
+ com.google.spanner.v1.ResultSet.newBuilder()
+ .setMetadata(
+ ResultSetMetadata.newBuilder()
+ .setRowType(
+ StructType.newBuilder()
+ .addFields(
+ Field.newBuilder()
+ .setName("id")
+ .setType(Type.newBuilder().setCode(TypeCode.INT64).build())
+ .build())
+ .addFields(
+ Field.newBuilder()
+ .setName("value")
+ .setType(Type.newBuilder().setCode(TypeCode.STRING).build())
+ .build())
+ .build())
+ .build())
+ .addRows(
+ ListValue.newBuilder()
+ .addValues(Value.newBuilder().setStringValue("1").build())
+ .addValues(Value.newBuilder().setStringValue("One").build())
+ .build())
+ .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build())
+ .build()));
+
+ try (Connection connection = createConnection();
+ java.sql.Statement statement = connection.createStatement()) {
+ for (SqlRunnable runnable :
+ ImmutableList.of(
+ () ->
+ assertEquals(
+ 1, statement.executeUpdate(sql, java.sql.Statement.RETURN_GENERATED_KEYS)),
+ () ->
+ assertEquals(
+ 1L,
+ statement.executeLargeUpdate(sql, java.sql.Statement.RETURN_GENERATED_KEYS)),
+ () -> {
+ assertFalse(statement.execute(sql, java.sql.Statement.RETURN_GENERATED_KEYS));
+ assertEquals(1, statement.getUpdateCount());
+ assertEquals(1L, statement.getLargeUpdateCount());
+ })) {
+ runnable.run();
+ assertNotNull(statement.getGeneratedKeys());
+ assertEquals(2, statement.getGeneratedKeys().getMetaData().getColumnCount());
+ assertEquals(Types.BIGINT, statement.getGeneratedKeys().getMetaData().getColumnType(1));
+ assertEquals(Types.NVARCHAR, statement.getGeneratedKeys().getMetaData().getColumnType(2));
+ assertEquals("id", statement.getGeneratedKeys().getMetaData().getColumnName(1));
+ assertEquals("value", statement.getGeneratedKeys().getMetaData().getColumnName(2));
+ try (ResultSet keys = statement.getGeneratedKeys()) {
+ assertTrue(keys.next());
+ assertEquals(1L, keys.getLong(1));
+ assertEquals("One", keys.getString(2));
+ assertFalse(keys.next());
+ }
+ // There should be no more results for this statement.
+ assertFalse(statement.getMoreResults());
+ assertEquals(-1, statement.getUpdateCount());
+ }
+ }
+ }
+
+ @Test
+ public void testReturnColumnNames() throws SQLException {
+ String sql = "insert into test (id, value) values (1, 'One')";
+ String returningClause =
+ dialect == Dialect.POSTGRESQL ? "\nRETURNING \"id\"" : "\nTHEN RETURN `id`";
+ mockSpanner.putStatementResult(
+ StatementResult.query(
+ Statement.of(sql + returningClause),
+ com.google.spanner.v1.ResultSet.newBuilder()
+ .setMetadata(
+ ResultSetMetadata.newBuilder()
+ .setRowType(
+ StructType.newBuilder()
+ .addFields(
+ Field.newBuilder()
+ .setName("id")
+ .setType(Type.newBuilder().setCode(TypeCode.INT64).build())
+ .build())
+ .build())
+ .build())
+ .addRows(
+ ListValue.newBuilder()
+ .addValues(Value.newBuilder().setStringValue("1").build())
+ .build())
+ .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build())
+ .build()));
+
+ try (Connection connection = createConnection();
+ java.sql.Statement statement = connection.createStatement()) {
+ for (SqlRunnable runnable :
+ ImmutableList.of(
+ () -> assertEquals(1, statement.executeUpdate(sql, new String[] {"id"})),
+ () -> assertEquals(1L, statement.executeLargeUpdate(sql, new String[] {"id"})),
+ () -> {
+ assertFalse(statement.execute(sql, new String[] {"id"}));
+ assertEquals(1, statement.getUpdateCount());
+ assertEquals(1L, statement.getLargeUpdateCount());
+ })) {
+ runnable.run();
+ assertNotNull(statement.getGeneratedKeys());
+ assertEquals(1, statement.getGeneratedKeys().getMetaData().getColumnCount());
+ assertEquals(Types.BIGINT, statement.getGeneratedKeys().getMetaData().getColumnType(1));
+ assertEquals("id", statement.getGeneratedKeys().getMetaData().getColumnName(1));
+ try (ResultSet keys = statement.getGeneratedKeys()) {
+ assertTrue(keys.next());
+ assertEquals(1L, keys.getLong(1));
+ assertFalse(keys.next());
+ }
+ // There should be no more results for this statement.
+ assertFalse(statement.getMoreResults());
+ assertEquals(-1, statement.getUpdateCount());
+ }
+ }
+ }
+
+ @Test
+ public void testReturnColumnIndices() throws SQLException {
+ String sql = "insert into test (id, value) values (1, 'One')";
+ mockSpanner.putStatementResult(StatementResult.update(Statement.of(sql), 1L));
+
+ try (Connection connection = createConnection();
+ java.sql.Statement statement = connection.createStatement()) {
+ // The JDBC driver silently ignores the request for column indices.
+ for (SqlRunnable runnable :
+ ImmutableList.of(
+ () -> assertEquals(1, statement.executeUpdate(sql, new int[] {1})),
+ () -> assertEquals(1L, statement.executeLargeUpdate(sql, new int[] {1})),
+ () -> {
+ assertFalse(statement.execute(sql, new int[] {1}));
+ assertEquals(1, statement.getUpdateCount());
+ assertEquals(1L, statement.getLargeUpdateCount());
+ })) {
+ runnable.run();
+ assertNotNull(statement.getGeneratedKeys());
+ assertFalse(statement.getGeneratedKeys().next());
+ }
+ }
+ }
+
+ @Test
+ public void testReturnGeneratedKeysForQuery() throws SQLException {
+ String sql = "select * from test";
+ RandomResultSetGenerator generator = new RandomResultSetGenerator(1);
+ mockSpanner.putStatementResult(StatementResult.query(Statement.of(sql), generator.generate()));
+
+ try (Connection connection = createConnection();
+ java.sql.Statement statement = connection.createStatement()) {
+ assertTrue(statement.execute(sql, java.sql.Statement.RETURN_GENERATED_KEYS));
+ try (ResultSet resultSet = statement.getResultSet()) {
+ assertTrue(resultSet.next());
+ assertFalse(resultSet.next());
+ }
+ // Statements without generated keys return an empty result set.
+ assertFalse(statement.getGeneratedKeys().next());
+ }
+ }
+
+ @Test
+ public void testReturnGeneratedKeysForDdl() throws SQLException {
+ String sql = "create table test";
+ addDdlResponseToSpannerAdmin();
+
+ try (Connection connection = createConnection();
+ java.sql.Statement statement = connection.createStatement()) {
+ assertFalse(statement.execute(sql, java.sql.Statement.RETURN_GENERATED_KEYS));
+ assertEquals(java.sql.Statement.SUCCESS_NO_INFO, statement.getUpdateCount());
+ // Statements without generated keys return an empty result set.
+ assertFalse(statement.getGeneratedKeys().next());
+ }
+ }
+
+ @Test
+ public void testReturnAutoGeneratedKeysForStatementWithReturning() throws SQLException {
+ String sql =
+ "insert into test (id, value) values (1, 'One') "
+ + (dialect == Dialect.POSTGRESQL ? "RETURNING value" : "THEN RETURN value");
+ mockSpanner.putStatementResult(
+ StatementResult.query(
+ Statement.of(sql),
+ com.google.spanner.v1.ResultSet.newBuilder()
+ .setMetadata(
+ ResultSetMetadata.newBuilder()
+ .setRowType(
+ StructType.newBuilder()
+ .addFields(
+ Field.newBuilder()
+ .setName("value")
+ .setType(Type.newBuilder().setCode(TypeCode.STRING).build())
+ .build())
+ .build())
+ .build())
+ .addRows(
+ ListValue.newBuilder()
+ .addValues(Value.newBuilder().setStringValue("One").build())
+ .build())
+ .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build())
+ .build()));
+
+ try (Connection connection = createConnection();
+ java.sql.Statement statement = connection.createStatement()) {
+ assertTrue(statement.execute(sql, java.sql.Statement.RETURN_GENERATED_KEYS));
+ try (ResultSet resultSet = statement.getResultSet()) {
+ assertTrue(resultSet.next());
+ assertEquals("One", resultSet.getString(1));
+ assertFalse(resultSet.next());
+ }
+
+ assertNotNull(statement.getGeneratedKeys());
+ assertFalse(statement.getGeneratedKeys().next());
+ // There should be no more results for this statement.
+ assertFalse(statement.getMoreResults());
+ assertEquals(-1, statement.getUpdateCount());
+ }
+ }
+
+ private void addDdlResponseToSpannerAdmin() {
+ mockDatabaseAdmin.addResponse(
+ Operation.newBuilder()
+ .setDone(true)
+ .setResponse(Any.pack(Empty.getDefaultInstance()))
+ .setMetadata(Any.pack(UpdateDatabaseDdlMetadata.getDefaultInstance()))
+ .build());
+ }
+}
From 93a1403a8a46aa9ae9e65d5ce7a30b12db458f9b Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Wed, 6 Sep 2023 10:56:17 +0200
Subject: [PATCH 073/173] chore(main): release 2.12.0 (#1330)
Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
---
CHANGELOG.md | 12 ++++++++++++
pom.xml | 2 +-
samples/snapshot/pom.xml | 2 +-
versions.txt | 2 +-
4 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 39927096c..1d60dd9de 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,17 @@
# Changelog
+## [2.12.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.9...v2.12.0) (2023-08-28)
+
+
+### Features
+
+* Return generated keys ([#1310](https://github.com/googleapis/java-spanner-jdbc/issues/1310)) ([9b5ab37](https://github.com/googleapis/java-spanner-jdbc/commit/9b5ab377587de09004474cb1cf488919fc83d6cb))
+
+
+### Bug Fixes
+
+* Session leak for invalid update ([#1323](https://github.com/googleapis/java-spanner-jdbc/issues/1323)) ([a7d0fbb](https://github.com/googleapis/java-spanner-jdbc/commit/a7d0fbb529ff71b45d6ddbbad8fc3be43e7c966f))
+
## [2.11.9](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.8...v2.11.9) (2023-08-21)
diff --git a/pom.xml b/pom.xml
index 4a33dea80..6f1e9cfbc 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.11.10-SNAPSHOT
+ 2.12.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 5cc1db045..33389f8da 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.11.10-SNAPSHOT
+ 2.12.0
diff --git a/versions.txt b/versions.txt
index 4a69a3a0a..1b9bfe902 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.11.9:2.11.10-SNAPSHOT
+google-cloud-spanner-jdbc:2.12.0:2.12.0
From 3468b88d0ff94bc81a0f3fbd8e354541a4d047d0 Mon Sep 17 00:00:00 2001
From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com>
Date: Wed, 6 Sep 2023 10:56:58 +0200
Subject: [PATCH 074/173] chore: for Java repos RenovateBot to ignore GitHub
Actions workflow file (#1855) (#1335)
chore: for Java repos RenovateBot to ignore GitHub Actions workflow file
The actions used in the GitHub Actions workflow files do not appear in libraries' dependencies and mostly maintained by Java postprocessor templates.
IgnorePath option document: https://docs.renovatebot.com/configuration-options/
Source-Link: https://github.com/googleapis/synthtool/commit/1543029c843989702adbe789acdead153ad696d1
Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:88ba8dcc5c2c7792e1c3511381f4ab329002a1c42c512f66ca87ced572dfbf9f
Co-authored-by: Owl Bot
---
.github/.OwlBot.lock.yaml | 4 ++--
renovate.json | 5 ++++-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml
index fa335912b..52eaa54d8 100644
--- a/.github/.OwlBot.lock.yaml
+++ b/.github/.OwlBot.lock.yaml
@@ -13,5 +13,5 @@
# limitations under the License.
docker:
image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest
- digest: sha256:3a95f1b9b1102865ca551b76be51d2bdb850900c4db2f6d79269e7af81ac8f84
-# created: 2023-07-27T18:37:44.251188775Z
+ digest: sha256:88ba8dcc5c2c7792e1c3511381f4ab329002a1c42c512f66ca87ced572dfbf9f
+# created: 2023-09-05T18:54:42.225408832Z
diff --git a/renovate.json b/renovate.json
index 6525dc2a5..efe64307f 100644
--- a/renovate.json
+++ b/renovate.json
@@ -10,7 +10,10 @@
":maintainLockFilesDisabled",
":autodetectPinVersions"
],
- "ignorePaths": [".kokoro/requirements.txt"],
+ "ignorePaths": [
+ ".kokoro/requirements.txt",
+ ".github/workflows/**"
+ ],
"packageRules": [
{
"packagePatterns": [
From 2c4fea074eb062b1ca1813a88a0fedfd7993de7c Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Wed, 6 Sep 2023 10:30:14 +0000
Subject: [PATCH 075/173] chore(main): release 2.12.1-SNAPSHOT (#1336)
:robot: I have created a release *beep* *boop*
---
### Updating meta-information for bleeding-edge SNAPSHOT release.
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
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 6f1e9cfbc..1ea8a9c65 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.12.0
+ 2.12.1-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 33389f8da..875835773 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.12.0
+ 2.12.1-SNAPSHOT
diff --git a/versions.txt b/versions.txt
index 1b9bfe902..5d40b59a7 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.12.0:2.12.0
+google-cloud-spanner-jdbc:2.12.0:2.12.1-SNAPSHOT
From 4fd7f420e13beb3620abf652217d3926718ad18a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?=
Date: Wed, 6 Sep 2023 13:53:50 +0200
Subject: [PATCH 076/173] chore: fix the region tags in the snippets pom.xml
(#1332)
* chore: fix the region tags in the snippets pom.xml
* chore: remove file from list of generated files
---
samples/snippets/pom.xml | 17 ++---------------
synth.metadata | 3 +--
2 files changed, 3 insertions(+), 17 deletions(-)
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index b0a7026a7..001268427 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -9,7 +9,7 @@
com.google.cloud.samples
@@ -42,19 +42,6 @@
com.google.cloud
google-cloud-spanner-jdbc
-
-
-
- junit
- junit
- 4.13.2
- test
-
-
- com.google.truth
- truth
- 1.1.5
- test
-
+
diff --git a/synth.metadata b/synth.metadata
index f335115e6..f877cda09 100644
--- a/synth.metadata
+++ b/synth.metadata
@@ -85,7 +85,6 @@
"renovate.json",
"samples/install-without-bom/pom.xml",
"samples/pom.xml",
- "samples/snapshot/pom.xml",
- "samples/snippets/pom.xml"
+ "samples/snapshot/pom.xml"
]
}
\ No newline at end of file
From 0596b85f776f6842f0de522a3788dcae272bd8c4 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Wed, 6 Sep 2023 14:48:13 +0200
Subject: [PATCH 077/173] chore(deps): update dependency
com.google.cloud:google-cloud-spanner-jdbc to v2.12.0 (#1337)
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:google-cloud-spanner-jdbc](https://togithub.com/googleapis/java-spanner-jdbc) | `2.11.9` -> `2.12.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-spanner-jdbc/2.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-spanner-jdbc/2.11.9/2.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-spanner-jdbc/2.11.9/2.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
---
### Release Notes
googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc)
### [`v2.12.0`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2120-2023-08-28)
[Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.11.9...v2.12.0)
##### Features
- Return generated keys ([#1310](https://togithub.com/googleapis/java-spanner-jdbc/issues/1310)) ([9b5ab37](https://togithub.com/googleapis/java-spanner-jdbc/commit/9b5ab377587de09004474cb1cf488919fc83d6cb))
##### Bug Fixes
- Session leak for invalid update ([#1323](https://togithub.com/googleapis/java-spanner-jdbc/issues/1323)) ([a7d0fbb](https://togithub.com/googleapis/java-spanner-jdbc/commit/a7d0fbb529ff71b45d6ddbbad8fc3be43e7c966f))
---
### 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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/googleapis/java-spanner-jdbc).
---
samples/install-without-bom/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index be6323501..ac3ea89e2 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.11.9
+ 2.12.0
From 0bcb5dc9d0c6e4d3878ceb748c09e87c75d88675 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Sat, 9 Sep 2023 08:26:59 +0200
Subject: [PATCH 078/173] deps: update dependency
com.google.cloud:google-cloud-spanner-bom to v6.46.0 (#1338)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 1ea8a9c65..571f071ed 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,7 @@
com.google.cloud
google-cloud-spanner-bom
- 6.45.3
+ 6.46.0
pom
import
From 00106505771ed75f83ceaf181f45f19e4251cd78 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Tue, 12 Sep 2023 19:26:15 +0200
Subject: [PATCH 079/173] deps: update dependency
com.google.cloud:google-cloud-spanner-bom to v6.47.0 (#1341)
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:google-cloud-spanner-bom](https://togithub.com/googleapis/java-spanner) | `6.46.0` -> `6.47.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.47.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-spanner-bom/6.47.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-spanner-bom/6.46.0/6.47.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-spanner-bom/6.46.0/6.47.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
---
### Release Notes
googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom)
### [`v6.47.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6470-2023-09-12)
[Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.46.0...v6.47.0)
##### Features
- Add devcontainers for enabling github codespaces usage. ([#2605](https://togithub.com/googleapis/java-spanner/issues/2605)) ([a7d60f1](https://togithub.com/googleapis/java-spanner/commit/a7d60f13781f87054a1631ca511492c5c8334751))
- Disable dynamic code loading properties by default ([#2606](https://togithub.com/googleapis/java-spanner/issues/2606)) ([d855ebb](https://togithub.com/googleapis/java-spanner/commit/d855ebbd2dec11cdd6cdbe326de81115632598cd))
##### Bug Fixes
- Add reflection configurations for com.google.rpc classes ([#2617](https://togithub.com/googleapis/java-spanner/issues/2617)) ([c42460a](https://togithub.com/googleapis/java-spanner/commit/c42460ae7b6bb5874cc18c7aecff34186dcbff2a))
- Avoid unbalanced session pool creation ([#2442](https://togithub.com/googleapis/java-spanner/issues/2442)) ([db751ce](https://togithub.com/googleapis/java-spanner/commit/db751ceebc8b6981d00cd07ce4742196cc1dd50d))
##### Dependencies
- Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.15.0 ([#2615](https://togithub.com/googleapis/java-spanner/issues/2615)) ([ac762fb](https://togithub.com/googleapis/java-spanner/commit/ac762fbf079db79eab5f2ebee971b850ac89eb11))
---
### 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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/googleapis/java-spanner-jdbc).
---
pom.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pom.xml b/pom.xml
index 571f071ed..31789c490 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,14 +62,14 @@
com.google.cloud
google-cloud-spanner-bom
- 6.46.0
+ 6.47.0
pom
import
com.google.cloud
google-cloud-shared-dependencies
- 3.14.0
+ 3.15.0
pom
import
From 2b9e44b29319839eecbfa20803f38208a570ea67 Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Tue, 12 Sep 2023 18:56:15 +0000
Subject: [PATCH 080/173] chore(main): release 2.12.1 (#1340)
:robot: I have created a release *beep* *boop*
---
## [2.12.1](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.12.0...v2.12.1) (2023-09-12)
### Dependencies
* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.46.0 ([#1338](https://togithub.com/googleapis/java-spanner-jdbc/issues/1338)) ([0bcb5dc](https://togithub.com/googleapis/java-spanner-jdbc/commit/0bcb5dc9d0c6e4d3878ceb748c09e87c75d88675))
* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.47.0 ([#1341](https://togithub.com/googleapis/java-spanner-jdbc/issues/1341)) ([0010650](https://togithub.com/googleapis/java-spanner-jdbc/commit/00106505771ed75f83ceaf181f45f19e4251cd78))
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
CHANGELOG.md | 8 ++++++++
pom.xml | 2 +-
samples/snapshot/pom.xml | 2 +-
versions.txt | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1d60dd9de..beda76d7f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## [2.12.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.12.0...v2.12.1) (2023-09-12)
+
+
+### Dependencies
+
+* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.46.0 ([#1338](https://github.com/googleapis/java-spanner-jdbc/issues/1338)) ([0bcb5dc](https://github.com/googleapis/java-spanner-jdbc/commit/0bcb5dc9d0c6e4d3878ceb748c09e87c75d88675))
+* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.47.0 ([#1341](https://github.com/googleapis/java-spanner-jdbc/issues/1341)) ([0010650](https://github.com/googleapis/java-spanner-jdbc/commit/00106505771ed75f83ceaf181f45f19e4251cd78))
+
## [2.12.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.9...v2.12.0) (2023-08-28)
diff --git a/pom.xml b/pom.xml
index 31789c490..6a62e0eaf 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.12.1-SNAPSHOT
+ 2.12.1
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 875835773..e7a72cae9 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.12.1-SNAPSHOT
+ 2.12.1
diff --git a/versions.txt b/versions.txt
index 5d40b59a7..81abcbb2d 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.12.0:2.12.1-SNAPSHOT
+google-cloud-spanner-jdbc:2.12.1:2.12.1
From e33fbe17ea4255b4f8f6c873bfb3b1b2fe440c34 Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Tue, 12 Sep 2023 20:28:14 +0000
Subject: [PATCH 081/173] chore(main): release 2.12.2-SNAPSHOT (#1342)
:robot: I have created a release *beep* *boop*
---
### Updating meta-information for bleeding-edge SNAPSHOT release.
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
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 6a62e0eaf..5d2bd1a22 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.12.1
+ 2.12.2-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 e7a72cae9..f0f41910a 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.12.1
+ 2.12.2-SNAPSHOT
diff --git a/versions.txt b/versions.txt
index 81abcbb2d..2da236249 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.12.1:2.12.1
+google-cloud-spanner-jdbc:2.12.1:2.12.2-SNAPSHOT
From ff6648f52f65a02bb44f648adb0c56542954e3ec Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Wed, 13 Sep 2023 10:04:06 +0200
Subject: [PATCH 082/173] chore(deps): update dependency
com.google.cloud:google-cloud-spanner-jdbc to v2.12.1 (#1343)
---
samples/install-without-bom/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index ac3ea89e2..0e0e2d7ae 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.12.0
+ 2.12.1
From cefea55086eb191f71a1a493e046cb136f9f9f87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?=
Date: Thu, 14 Sep 2023 11:24:13 +0200
Subject: [PATCH 083/173] docs: create Spring Data JDBC sample (#1334)
Adds a sample for using Spring Data JDBC with Cloud Spanner PostgreSQL and shows how to run the same application on both Cloud Spanner and traditional PostgreSQL. This can be used to create a portable application, or to use PostgreSQL as a development/test database, while Cloud Spanner is used for production.
---
.../workflows/spring-data-jdbc-sample.yaml | 30 +
samples/spring-data-jdbc/README.md | 95 +++
samples/spring-data-jdbc/pom.xml | 102 +++
.../cloud/spanner/sample/Application.java | 126 +++
.../cloud/spanner/sample/DatabaseSeeder.java | 342 ++++++++
.../spanner/sample/JdbcConfiguration.java | 84 ++
.../sample/entities/AbstractEntity.java | 74 ++
.../cloud/spanner/sample/entities/Album.java | 86 ++
.../spanner/sample/entities/Concert.java | 80 ++
.../cloud/spanner/sample/entities/Singer.java | 73 ++
.../cloud/spanner/sample/entities/Track.java | 84 ++
.../cloud/spanner/sample/entities/Venue.java | 46 ++
.../sample/repositories/AlbumRepository.java | 40 +
.../repositories/ConcertRepository.java | 24 +
.../sample/repositories/SingerRepository.java | 34 +
.../sample/repositories/TrackRepository.java | 24 +
.../sample/repositories/VenueRepository.java | 24 +
.../spanner/sample/service/SingerService.java | 67 ++
.../main/resources/application-cs.properties | 9 +
.../main/resources/application-pg.properties | 7 +
.../src/main/resources/application.properties | 9 +
.../src/main/resources/create_schema.sql | 68 ++
.../src/main/resources/drop_schema.sql | 5 +
.../cloud/spanner/sample/ApplicationTest.java | 766 ++++++++++++++++++
.../test/resources/application-cs.properties | 9 +
.../test/resources/application-pg.properties | 7 +
.../src/test/resources/application.properties | 9 +
27 files changed, 2324 insertions(+)
create mode 100644 .github/workflows/spring-data-jdbc-sample.yaml
create mode 100644 samples/spring-data-jdbc/README.md
create mode 100644 samples/spring-data-jdbc/pom.xml
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/Application.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Album.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Track.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java
create mode 100644 samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java
create mode 100644 samples/spring-data-jdbc/src/main/resources/application-cs.properties
create mode 100644 samples/spring-data-jdbc/src/main/resources/application-pg.properties
create mode 100644 samples/spring-data-jdbc/src/main/resources/application.properties
create mode 100644 samples/spring-data-jdbc/src/main/resources/create_schema.sql
create mode 100644 samples/spring-data-jdbc/src/main/resources/drop_schema.sql
create mode 100644 samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java
create mode 100644 samples/spring-data-jdbc/src/test/resources/application-cs.properties
create mode 100644 samples/spring-data-jdbc/src/test/resources/application-pg.properties
create mode 100644 samples/spring-data-jdbc/src/test/resources/application.properties
diff --git a/.github/workflows/spring-data-jdbc-sample.yaml b/.github/workflows/spring-data-jdbc-sample.yaml
new file mode 100644
index 000000000..028a48631
--- /dev/null
+++ b/.github/workflows/spring-data-jdbc-sample.yaml
@@ -0,0 +1,30 @@
+# 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.
+# Github action job to test core java library features on
+# downstream client libraries before they are released.
+on:
+ pull_request:
+name: spring-data-jdbc-sample
+jobs:
+ spring-data-jdbc:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-java@v3
+ with:
+ distribution: temurin
+ java-version: 17
+ - name: Run tests
+ run: mvn test
+ working-directory: samples/spring-data-jdbc
diff --git a/samples/spring-data-jdbc/README.md b/samples/spring-data-jdbc/README.md
new file mode 100644
index 000000000..da1d69532
--- /dev/null
+++ b/samples/spring-data-jdbc/README.md
@@ -0,0 +1,95 @@
+# Spring Data JDBC Sample Application with Cloud Spanner PostgreSQL
+
+This sample application shows how to develop portable applications using Spring Data JDBC in
+combination with Cloud Spanner PostgreSQL. This application can be configured to run on either a
+[Cloud Spanner PostgreSQL](https://cloud.google.com/spanner/docs/postgresql-interface) database or
+an open-source PostgreSQL database. The only change that is needed to switch between the two is
+changing the active Spring profile that is used by the application.
+
+The application uses the Cloud Spanner JDBC driver to connect to Cloud Spanner PostgreSQL, and it
+uses the PostgreSQL JDBC driver to connect to open-source PostgreSQL. Spring Data JDBC works with
+both drivers and offers a single consistent API to the application developer, regardless of the
+actual database or JDBC driver being used.
+
+This sample shows:
+
+1. How to use Spring Data JDBC with Cloud Spanner PostgreSQL.
+2. How to develop a portable application that runs on both Google Cloud Spanner PostgreSQL and
+ open-source PostgreSQL with the same code base.
+3. How to use bit-reversed sequences to automatically generate primary key values for entities.
+
+__NOTE__: This application does __not require PGAdapter__. Instead, it connects to Cloud Spanner
+PostgreSQL using the Cloud Spanner JDBC driver.
+
+## Cloud Spanner PostgreSQL
+
+Cloud Spanner PostgreSQL provides language support by expressing Spanner database functionality
+through a subset of open-source PostgreSQL language constructs, with extensions added to support
+Spanner functionality like interleaved tables and hinting.
+
+The PostgreSQL interface makes the capabilities of Spanner —__fully managed, unlimited scale, strong
+consistency, high performance, and up to 99.999% global availability__— accessible using the
+PostgreSQL dialect. Unlike other services that manage actual PostgreSQL database instances, Spanner
+uses PostgreSQL-compatible syntax to expose its existing scale-out capabilities. This provides
+familiarity for developers and portability for applications, but not 100% PostgreSQL compatibility.
+The SQL syntax that Spanner supports is semantically equivalent PostgreSQL, meaning schemas
+and queries written against the PostgreSQL interface can be easily ported to another PostgreSQL
+environment.
+
+This sample showcases this portability with an application that works on both Cloud Spanner PostgreSQL
+and open-source PostgreSQL with the same code base.
+
+## Spring Data JDBC
+
+[Spring Data JDBC](https://spring.io/projects/spring-data-jdbc) is part of the larger Spring Data
+family. It makes it easy to implement JDBC based repositories. This module deals with enhanced
+support for JDBC based data access layers.
+
+Spring Data JDBC aims at being conceptually easy. In order to achieve this it does NOT offer caching,
+lazy loading, write behind or many other features of JPA. This makes Spring Data JDBC a simple,
+limited, opinionated ORM.
+
+## Sample Application
+
+This sample shows how to create a portable application using Spring Data JDBC and the Cloud Spanner
+PostgreSQL dialect. The application works on both Cloud Spanner PostgreSQL and open-source
+PostgreSQL. You can switch between the two by changing the active Spring profile:
+* Profile `cs` runs the application on Cloud Spanner PostgreSQL.
+* Profile `pg` runs the application on open-source PostgreSQL.
+
+The default profile is `cs`. You can change the default profile by modifying the
+[application.properties](src/main/resources/application.properties) file.
+
+### Running the Application
+
+1. Choose the database system that you want to use by choosing a profile. The default profile is
+ `cs`, which runs the application on Cloud Spanner PostgreSQL. Modify the default profile in the
+ [application.properties](src/main/resources/application.properties) file.
+2. Modify either [application-cs.properties](src/main/resources/application-cs.properties) or
+ [application-pg.properties](src/main/resources/application-pg.properties) to point to an existing
+ database. If you use Cloud Spanner, the database that the configuration file references must be a
+ database that uses the PostgreSQL dialect.
+3. Run the application with `mvn spring-boot:run`.
+
+### Main Application Components
+
+The main application components are:
+* [DatabaseSeeder.java](src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java): This
+ class is responsible for creating the database schema and inserting some initial test data. The
+ schema is created from the [create_schema.sql](src/main/resources/create_schema.sql) file. The
+ `DatabaseSeeder` class loads this file into memory and executes it on the active database using
+ standard JDBC APIs. The class also removes Cloud Spanner-specific extensions to the PostgreSQL
+ dialect when the application runs on open-source PostgreSQL.
+* [JdbcConfiguration.java](src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java):
+ Spring Data JDBC by default detects the database dialect based on the JDBC driver that is used.
+ This class overrides this default and instructs Spring Data JDBC to also use the PostgreSQL
+ dialect for Cloud Spanner PostgreSQL.
+* [AbstractEntity.java](src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java):
+ This is the shared base class for all entities in this sample application. It defines a number of
+ standard attributes, such as the identifier (primary key). The primary key is automatically
+ generated using a (bit-reversed) sequence. [Bit-reversed sequential values](https://cloud.google.com/spanner/docs/schema-design#bit_reverse_primary_key)
+ are considered a good choice for primary keys on Cloud Spanner.
+* [Application.java](src/main/java/com/google/cloud/spanner/sample/Application.java): The starter
+ class of the application. It contains a command-line runner that executes a selection of queries
+ and updates on the database.
+
diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml
new file mode 100644
index 000000000..a2f7c377f
--- /dev/null
+++ b/samples/spring-data-jdbc/pom.xml
@@ -0,0 +1,102 @@
+
+
+ 4.0.0
+
+ org.example
+ cloud-spanner-spring-data-jdbc-example
+ 1.0-SNAPSHOT
+
+ Sample application showing how to use Spring Data JDBC with Cloud Spanner PostgreSQL.
+
+
+
+ 17
+ 17
+ 17
+ UTF-8
+
+
+
+
+
+ org.springframework.data
+ spring-data-bom
+ 2023.0.3
+ import
+ pom
+
+
+ com.google.cloud
+ libraries-bom
+ 26.22.0
+ import
+ pom
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jdbc
+ 3.1.3
+
+
+
+
+ com.google.cloud
+ google-cloud-spanner-jdbc
+ 2.12.0
+
+
+ org.postgresql
+ postgresql
+ 42.6.0
+
+
+
+ com.google.collections
+ google-collections
+ 1.0
+
+
+
+
+ com.google.cloud
+ google-cloud-spanner
+ test-jar
+ test
+
+
+ com.google.api
+ gax-grpc
+ testlib
+ test
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+
+
+
+
+ com.spotify.fmt
+ fmt-maven-plugin
+ 2.20
+
+
+
+ format
+
+
+
+
+
+
+
diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/Application.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/Application.java
new file mode 100644
index 000000000..bc55afd55
--- /dev/null
+++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/Application.java
@@ -0,0 +1,126 @@
+/*
+ * 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.spanner.sample;
+
+import com.google.cloud.spanner.sample.entities.Album;
+import com.google.cloud.spanner.sample.entities.Singer;
+import com.google.cloud.spanner.sample.entities.Track;
+import com.google.cloud.spanner.sample.repositories.AlbumRepository;
+import com.google.cloud.spanner.sample.repositories.SingerRepository;
+import com.google.cloud.spanner.sample.repositories.TrackRepository;
+import com.google.cloud.spanner.sample.service.SingerService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application implements CommandLineRunner {
+ private static final Logger logger = LoggerFactory.getLogger(Application.class);
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args).close();
+ }
+
+ private final DatabaseSeeder databaseSeeder;
+
+ private final SingerService singerService;
+
+ private final SingerRepository singerRepository;
+
+ private final AlbumRepository albumRepository;
+
+ private final TrackRepository trackRepository;
+
+ public Application(
+ SingerService singerService,
+ DatabaseSeeder databaseSeeder,
+ SingerRepository singerRepository,
+ AlbumRepository albumRepository,
+ TrackRepository trackRepository) {
+ this.databaseSeeder = databaseSeeder;
+ this.singerService = singerService;
+ this.singerRepository = singerRepository;
+ this.albumRepository = albumRepository;
+ this.trackRepository = trackRepository;
+ }
+
+ @Override
+ public void run(String... args) {
+
+ // Set the system property 'drop_schema' to true to drop any existing database
+ // schema when the application is executed.
+ if (Boolean.parseBoolean(System.getProperty("drop_schema", "false"))) {
+ logger.info("Dropping existing schema if it exists");
+ databaseSeeder.dropDatabaseSchemaIfExists();
+ }
+
+ logger.info("Creating database schema if it does not already exist");
+ databaseSeeder.createDatabaseSchemaIfNotExists();
+ logger.info("Deleting existing test data");
+ databaseSeeder.deleteTestData();
+ logger.info("Inserting fresh test data");
+ databaseSeeder.insertTestData();
+
+ Iterable allSingers = singerRepository.findAll();
+ for (Singer singer : allSingers) {
+ logger.info(
+ "Found singer: {} with {} albums",
+ singer,
+ albumRepository.countAlbumsBySingerId(singer.getId()));
+ for (Album album : albumRepository.findAlbumsBySingerId(singer.getId())) {
+ logger.info("\tAlbum: {}, released at {}", album, album.getReleaseDate());
+ }
+ }
+
+ // Create a new singer and three albums in a transaction.
+ Singer insertedSinger =
+ singerService.createSingerAndAlbums(
+ new Singer("Amethyst", "Jiang"),
+ new Album(databaseSeeder.randomTitle()),
+ new Album(databaseSeeder.randomTitle()),
+ new Album(databaseSeeder.randomTitle()));
+ logger.info(
+ "Inserted singer {} {} {}",
+ insertedSinger.getId(),
+ insertedSinger.getFirstName(),
+ insertedSinger.getLastName());
+
+ // Create a new track record and insert it into the database.
+ Album album = albumRepository.getFirst().orElseThrow();
+ Track track = new Track(album, 1, databaseSeeder.randomTitle());
+ track.setSampleRate(3.14d);
+ // Spring Data JDBC supports the same base CRUD operations on entities as for example
+ // Spring Data JPA.
+ trackRepository.save(track);
+
+ // List all singers that have a last name starting with an 'J'.
+ logger.info("All singers with a last name starting with an 'J':");
+ for (Singer singer : singerRepository.findSingersByLastNameStartingWith("J")) {
+ logger.info("\t{}", singer.getFullName());
+ }
+
+ // The singerService.listSingersWithLastNameStartingWith(..) method uses a read-only
+ // transaction. You should prefer read-only transactions to read/write transactions whenever
+ // possible, as read-only transactions do not take locks.
+ logger.info("All singers with a last name starting with an 'A', 'B', or 'C'.");
+ for (Singer singer : singerService.listSingersWithLastNameStartingWith("A", "B", "C")) {
+ logger.info("\t{}", singer.getFullName());
+ }
+ }
+}
diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java
new file mode 100644
index 000000000..eabd04c3b
--- /dev/null
+++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java
@@ -0,0 +1,342 @@
+/*
+ * 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.spanner.sample;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.cloud.spanner.sample.entities.Singer;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UncheckedIOException;
+import java.math.BigDecimal;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.time.LocalDate;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.function.Supplier;
+import javax.annotation.Nonnull;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.Resource;
+import org.springframework.jdbc.core.BatchPreparedStatementSetter;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.FileCopyUtils;
+
+/** This component creates the database schema and seeds it with some random test data. */
+@Component
+public class DatabaseSeeder {
+
+ /** Randomly generated names. */
+ public static final ImmutableList INITIAL_SINGERS =
+ ImmutableList.of(
+ new Singer("Aaliyah", "Smith"),
+ new Singer("Benjamin", "Jones"),
+ new Singer("Chloe", "Brown"),
+ new Singer("David", "Williams"),
+ new Singer("Elijah", "Johnson"),
+ new Singer("Emily", "Miller"),
+ new Singer("Gabriel", "Garcia"),
+ new Singer("Hannah", "Rodriguez"),
+ new Singer("Isabella", "Hernandez"),
+ new Singer("Jacob", "Perez"));
+
+ private static final Random RANDOM = new Random();
+
+ private final JdbcTemplate jdbcTemplate;
+
+ @Value("classpath:create_schema.sql")
+ private Resource createSchemaFile;
+
+ @Value("classpath:drop_schema.sql")
+ private Resource dropSchemaFile;
+
+ /** This value is determined once using a system query, and then cached. */
+ private final Supplier isCloudSpannerPG;
+
+ public DatabaseSeeder(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ this.isCloudSpannerPG =
+ Suppliers.memoize(() -> JdbcConfiguration.isCloudSpannerPG(jdbcTemplate));
+ }
+
+ /** Reads a resource file into a string. */
+ private static String resourceAsString(Resource resource) {
+ try (Reader reader = new InputStreamReader(resource.getInputStream(), UTF_8)) {
+ return FileCopyUtils.copyToString(reader);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ /**
+ * Returns true if this application is currently running on a Cloud Spanner PostgreSQL database,
+ * and false if it is running on an open-source PostgreSQL database.
+ */
+ private boolean isCloudSpanner() {
+ return isCloudSpannerPG.get();
+ }
+
+ /**
+ * Removes all statements that start with a 'skip_on_open_source_pg' comment if the application is
+ * running on open-source PostgreSQL. This ensures that we can use the same DDL script both on
+ * Cloud Spanner and on open-source PostgreSQL. It also removes any empty statements in the given
+ * array.
+ */
+ private String[] updateDdlStatements(String[] statements) {
+ if (!isCloudSpanner()) {
+ for (int i = 0; i < statements.length; i++) {
+ // Replace any line that starts with '/* skip_on_open_source_pg */' with an empty string.
+ statements[i] =
+ statements[i].replaceAll("(?m)^\\s*/\\*\\s*skip_on_open_source_pg\\s*\\*/.+$", "");
+ }
+ }
+ // Remove any empty statements from the script.
+ return Arrays.stream(statements)
+ .filter(statement -> !statement.isBlank())
+ .toArray(String[]::new);
+ }
+
+ /** Creates the database schema if it does not yet exist. */
+ public void createDatabaseSchemaIfNotExists() {
+ // We can safely just split the script based on ';', as we know that there are no literals or
+ // other strings that contain semicolons in the script.
+ String[] statements = updateDdlStatements(resourceAsString(createSchemaFile).split(";"));
+ // Execute all the DDL statements as a JDBC batch. That ensures that Cloud Spanner will apply
+ // all statements in a single DDL batch, which again is a lot more efficient than executing them
+ // one-by-one.
+ jdbcTemplate.batchUpdate(statements);
+ }
+
+ /** Drops the database schema if it exists. */
+ public void dropDatabaseSchemaIfExists() {
+ // We can safely just split the script based on ';', as we know that there are no literals or
+ // other strings that contain semicolons in the script.
+ String[] statements = updateDdlStatements(resourceAsString(dropSchemaFile).split(";"));
+ // Execute all the DDL statements as a JDBC batch. That ensures that Cloud Spanner will apply
+ // all statements in a single DDL batch, which again is a lot more efficient than executing them
+ // one-by-one.
+ jdbcTemplate.batchUpdate(statements);
+ }
+
+ /** Deletes all data currently in the sample tables. */
+ public void deleteTestData() {
+ // Delete all data in one batch.
+ jdbcTemplate.batchUpdate(
+ "delete from concerts",
+ "delete from venues",
+ "delete from tracks",
+ "delete from albums",
+ "delete from singers");
+ }
+
+ /** Inserts some initial test data into the database. */
+ public void insertTestData() {
+ jdbcTemplate.batchUpdate(
+ "insert into singers (first_name, last_name) values (?, ?)",
+ new BatchPreparedStatementSetter() {
+ @Override
+ public void setValues(@Nonnull PreparedStatement preparedStatement, int i)
+ throws SQLException {
+ preparedStatement.setString(1, INITIAL_SINGERS.get(i).getFirstName());
+ preparedStatement.setString(2, INITIAL_SINGERS.get(i).getLastName());
+ }
+
+ @Override
+ public int getBatchSize() {
+ return INITIAL_SINGERS.size();
+ }
+ });
+
+ List singerIds =
+ jdbcTemplate.query(
+ "select id from singers",
+ resultSet -> {
+ ImmutableList.Builder builder = ImmutableList.builder();
+ while (resultSet.next()) {
+ builder.add(resultSet.getLong(1));
+ }
+ return builder.build();
+ });
+ jdbcTemplate.batchUpdate(
+ "insert into albums (title, marketing_budget, release_date, cover_picture, singer_id) values (?, ?, ?, ?, ?)",
+ new BatchPreparedStatementSetter() {
+ @Override
+ public void setValues(@Nonnull PreparedStatement preparedStatement, int i)
+ throws SQLException {
+ preparedStatement.setString(1, randomTitle());
+ preparedStatement.setBigDecimal(2, randomBigDecimal());
+ preparedStatement.setObject(3, randomDate());
+ preparedStatement.setBytes(4, randomBytes());
+ preparedStatement.setLong(5, randomElement(singerIds));
+ }
+
+ @Override
+ public int getBatchSize() {
+ return INITIAL_SINGERS.size() * 20;
+ }
+ });
+ }
+
+ /** Generates a random title for an album or a track. */
+ static String randomTitle() {
+ return randomElement(ADJECTIVES) + " " + randomElement(NOUNS);
+ }
+
+ /** Returns a random element from the given list. */
+ static T randomElement(List list) {
+ return list.get(RANDOM.nextInt(list.size()));
+ }
+
+ /** Generates a random {@link BigDecimal}. */
+ BigDecimal randomBigDecimal() {
+ return BigDecimal.valueOf(RANDOM.nextDouble());
+ }
+
+ /** Generates a random {@link LocalDate}. */
+ static LocalDate randomDate() {
+ return LocalDate.of(RANDOM.nextInt(200) + 1800, RANDOM.nextInt(12) + 1, RANDOM.nextInt(28) + 1);
+ }
+
+ /** Generates a random byte array with a length between 4 and 1024 bytes. */
+ static byte[] randomBytes() {
+ int size = RANDOM.nextInt(1020) + 4;
+ byte[] res = new byte[size];
+ RANDOM.nextBytes(res);
+ return res;
+ }
+
+ /** Some randomly generated nouns that are used to generate random titles. */
+ private static final ImmutableList NOUNS =
+ ImmutableList.of(
+ "apple",
+ "banana",
+ "cherry",
+ "dog",
+ "elephant",
+ "fish",
+ "grass",
+ "house",
+ "key",
+ "lion",
+ "monkey",
+ "nail",
+ "orange",
+ "pen",
+ "queen",
+ "rain",
+ "shoe",
+ "tree",
+ "umbrella",
+ "van",
+ "whale",
+ "xylophone",
+ "zebra");
+
+ /** Some randomly generated adjectives that are used to generate random titles. */
+ private static final ImmutableList ADJECTIVES =
+ ImmutableList.of(
+ "able",
+ "angelic",
+ "artistic",
+ "athletic",
+ "attractive",
+ "autumnal",
+ "calm",
+ "careful",
+ "cheerful",
+ "clever",
+ "colorful",
+ "confident",
+ "courageous",
+ "creative",
+ "curious",
+ "daring",
+ "determined",
+ "different",
+ "dreamy",
+ "efficient",
+ "elegant",
+ "energetic",
+ "enthusiastic",
+ "exciting",
+ "expressive",
+ "faithful",
+ "fantastic",
+ "funny",
+ "gentle",
+ "gifted",
+ "great",
+ "happy",
+ "helpful",
+ "honest",
+ "hopeful",
+ "imaginative",
+ "intelligent",
+ "interesting",
+ "inventive",
+ "joyful",
+ "kind",
+ "knowledgeable",
+ "loving",
+ "loyal",
+ "magnificent",
+ "mature",
+ "mysterious",
+ "natural",
+ "nice",
+ "optimistic",
+ "peaceful",
+ "perfect",
+ "pleasant",
+ "powerful",
+ "proud",
+ "quick",
+ "relaxed",
+ "reliable",
+ "responsible",
+ "romantic",
+ "safe",
+ "sensitive",
+ "sharp",
+ "simple",
+ "sincere",
+ "skillful",
+ "smart",
+ "sociable",
+ "strong",
+ "successful",
+ "sweet",
+ "talented",
+ "thankful",
+ "thoughtful",
+ "unique",
+ "upbeat",
+ "valuable",
+ "victorious",
+ "vivacious",
+ "warm",
+ "wealthy",
+ "wise",
+ "wonderful",
+ "worthy",
+ "youthful");
+}
diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java
new file mode 100644
index 000000000..2066647b5
--- /dev/null
+++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java
@@ -0,0 +1,84 @@
+/*
+ * 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.spanner.sample;
+
+import com.google.cloud.spanner.jdbc.JdbcSqlException;
+import com.google.rpc.Code;
+import java.util.Objects;
+import javax.annotation.Nonnull;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.IncorrectResultSizeDataAccessException;
+import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration;
+import org.springframework.data.relational.core.dialect.Dialect;
+import org.springframework.data.relational.core.dialect.PostgresDialect;
+import org.springframework.jdbc.core.JdbcOperations;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
+
+@Configuration
+public class JdbcConfiguration extends AbstractJdbcConfiguration {
+
+ /** Override the dialect auto-detection, so it also returns PostgreSQL for Cloud Spanner. */
+ @Override
+ public Dialect jdbcDialect(@Nonnull NamedParameterJdbcOperations operations) {
+ if (isCloudSpannerPG(operations.getJdbcOperations())) {
+ return PostgresDialect.INSTANCE;
+ }
+ return super.jdbcDialect(operations);
+ }
+
+ /** Returns true if the current database is a Cloud Spanner PostgreSQL database. */
+ public static boolean isCloudSpannerPG(JdbcOperations operations) {
+ try {
+ Long value =
+ operations.queryForObject(
+ "select 1 "
+ + "from information_schema.database_options "
+ + "where schema_name='public' "
+ + "and option_name='database_dialect' "
+ + "and option_value='POSTGRESQL'",
+ Long.class);
+ // Shouldn't really be anything else than 1 if the query succeeded, but this avoids complaints
+ // from the compiler.
+ if (Objects.equals(1L, value)) {
+ return true;
+ }
+ } catch (IncorrectResultSizeDataAccessException exception) {
+ // This indicates that it is a valid Cloud Spanner database, but not one that uses the
+ // PostgreSQL dialect.
+ throw new RuntimeException(
+ "The selected Cloud Spanner database does not use the PostgreSQL dialect");
+ } catch (DataAccessException exception) {
+ if (exception.getCause() instanceof JdbcSqlException) {
+ JdbcSqlException jdbcSqlException = (JdbcSqlException) exception;
+ if (jdbcSqlException.getCode() == Code.PERMISSION_DENIED
+ || jdbcSqlException.getCode() == Code.NOT_FOUND) {
+ throw new RuntimeException(
+ "Failed to get the dialect of the Cloud Spanner database. "
+ + "Please check that the selected database exists and that you have permission to access it. "
+ + "Cause: "
+ + exception.getCause().getMessage(),
+ exception.getCause());
+ }
+ }
+ // ignore and fall through
+ } catch (Throwable exception) {
+ // ignore and fall through
+ }
+ return false;
+ }
+}
diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java
new file mode 100644
index 000000000..4c6d3f231
--- /dev/null
+++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java
@@ -0,0 +1,74 @@
+/*
+ * 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.spanner.sample.entities;
+
+import java.time.OffsetDateTime;
+import org.springframework.data.annotation.Id;
+
+public abstract class AbstractEntity {
+
+ /** This ID is generated using a (bit-reversed) sequence. */
+ @Id private Long id;
+
+ private OffsetDateTime createdAt;
+
+ private OffsetDateTime updatedAt;
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof AbstractEntity)) {
+ return false;
+ }
+ AbstractEntity other = (AbstractEntity) o;
+ if (this == other) {
+ return true;
+ }
+ return this.getClass().equals(other.getClass())
+ && this.id != null
+ && other.id != null
+ && this.id.equals(other.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return this.id == null ? 0 : this.id.hashCode();
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ protected void setId(Long id) {
+ this.id = id;
+ }
+
+ public OffsetDateTime getCreatedAt() {
+ return createdAt;
+ }
+
+ protected void setCreatedAt(OffsetDateTime createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public OffsetDateTime getUpdatedAt() {
+ return updatedAt;
+ }
+
+ protected void setUpdatedAt(OffsetDateTime updatedAt) {
+ this.updatedAt = updatedAt;
+ }
+}
diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Album.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Album.java
new file mode 100644
index 000000000..dfde31af2
--- /dev/null
+++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Album.java
@@ -0,0 +1,86 @@
+/*
+ * 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.spanner.sample.entities;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import org.springframework.data.relational.core.mapping.Table;
+
+@Table("albums")
+public class Album extends AbstractEntity {
+
+ private String title;
+
+ private BigDecimal marketingBudget;
+
+ private LocalDate releaseDate;
+
+ private byte[] coverPicture;
+
+ private Long singerId;
+
+ public Album() {}
+
+ public Album(String title) {
+ this.title = title;
+ }
+
+ @Override
+ public String toString() {
+ return getTitle();
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public BigDecimal getMarketingBudget() {
+ return marketingBudget;
+ }
+
+ public void setMarketingBudget(BigDecimal marketingBudget) {
+ this.marketingBudget = marketingBudget;
+ }
+
+ public LocalDate getReleaseDate() {
+ return releaseDate;
+ }
+
+ public void setReleaseDate(LocalDate releaseDate) {
+ this.releaseDate = releaseDate;
+ }
+
+ public byte[] getCoverPicture() {
+ return coverPicture;
+ }
+
+ public void setCoverPicture(byte[] coverPicture) {
+ this.coverPicture = coverPicture;
+ }
+
+ public Long getSingerId() {
+ return singerId;
+ }
+
+ public void setSingerId(Long singerId) {
+ this.singerId = singerId;
+ }
+}
diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java
new file mode 100644
index 000000000..29f2b6d90
--- /dev/null
+++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java
@@ -0,0 +1,80 @@
+/*
+ * 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.spanner.sample.entities;
+
+import java.time.OffsetDateTime;
+import org.springframework.data.relational.core.mapping.Table;
+
+@Table("concerts")
+public class Concert extends AbstractEntity {
+
+ private Long venueId;
+
+ private Long singerId;
+
+ private String name;
+
+ private OffsetDateTime startTime;
+
+ private OffsetDateTime endTime;
+
+ public Concert(Venue venue, Singer singer, String name) {
+ this.venueId = venue.getId();
+ this.singerId = singer.getId();
+ this.name = name;
+ }
+
+ public Long getVenueId() {
+ return venueId;
+ }
+
+ public void setVenueId(Long venueId) {
+ this.venueId = venueId;
+ }
+
+ public Long getSingerId() {
+ return singerId;
+ }
+
+ public void setSingerId(Long singerId) {
+ this.singerId = singerId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public OffsetDateTime getStartTime() {
+ return startTime;
+ }
+
+ public void setStartTime(OffsetDateTime startTime) {
+ this.startTime = startTime;
+ }
+
+ public OffsetDateTime getEndTime() {
+ return endTime;
+ }
+
+ public void setEndTime(OffsetDateTime endTime) {
+ this.endTime = endTime;
+ }
+}
diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java
new file mode 100644
index 000000000..255459a89
--- /dev/null
+++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java
@@ -0,0 +1,73 @@
+/*
+ * 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.spanner.sample.entities;
+
+import org.springframework.data.annotation.ReadOnlyProperty;
+import org.springframework.data.relational.core.mapping.Table;
+
+@Table("singers")
+public class Singer extends AbstractEntity {
+
+ private String firstName;
+
+ private String lastName;
+
+ /** Mark fullName as a {@link ReadOnlyProperty}, as it is generated by the database. */
+ @ReadOnlyProperty private String fullName;
+
+ private Boolean active;
+
+ public Singer() {}
+
+ public Singer(String firstName, String lastName) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+
+ @Override
+ public String toString() {
+ return getFullName();
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public Boolean getActive() {
+ return active;
+ }
+
+ public void setActive(Boolean active) {
+ this.active = active;
+ }
+}
diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Track.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Track.java
new file mode 100644
index 000000000..268b6e2b5
--- /dev/null
+++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Track.java
@@ -0,0 +1,84 @@
+/*
+ * 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.spanner.sample.entities;
+
+import org.springframework.data.relational.core.mapping.Column;
+import org.springframework.data.relational.core.mapping.Table;
+
+/**
+ * The "tracks" table is interleaved in "albums". That means that the first part of the primary key
+ * (the "id" column) references the Album that this Track belongs to. That again means that we do
+ * not auto-generate the id for this entity. We can achieve this by adding an extra property,
+ * albumId, that is mapped to the "id" column. We can then manually set an albumId value before
+ * inserting the record in the database.
+ */
+@Table("tracks")
+public class Track extends AbstractEntity {
+
+ /**
+ * We need to map this to the "id" column to be able to explicitly set it, instead of letting
+ * Spring Data generate it. This is necessary, because Track is interleaved in Album. That again
+ * means that we must use the ID value of the Album for a Track.
+ */
+ @Column("id")
+ private Long albumId;
+
+ /** This is the second part of the primary key of a Track. */
+ private int trackNumber;
+
+ private String title;
+
+ private Double sampleRate;
+
+ public Track(Album album, int trackNumber, String title) {
+ setAlbumId(album.getId());
+ this.trackNumber = trackNumber;
+ this.title = title;
+ }
+
+ public Long getAlbumId() {
+ return albumId;
+ }
+
+ private void setAlbumId(Long albumId) {
+ this.albumId = albumId;
+ }
+
+ public int getTrackNumber() {
+ return trackNumber;
+ }
+
+ public void setTrackNumber(int trackNumber) {
+ this.trackNumber = trackNumber;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public Double getSampleRate() {
+ return sampleRate;
+ }
+
+ public void setSampleRate(Double sampleRate) {
+ this.sampleRate = sampleRate;
+ }
+}
diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java
new file mode 100644
index 000000000..e7855cd01
--- /dev/null
+++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java
@@ -0,0 +1,46 @@
+/*
+ * 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.spanner.sample.entities;
+
+import org.springframework.data.relational.core.mapping.Table;
+
+@Table("venues")
+public class Venue extends AbstractEntity {
+ private String name;
+
+ private String description;
+
+ public Venue(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+}
diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java
new file mode 100644
index 000000000..de90bf798
--- /dev/null
+++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java
@@ -0,0 +1,40 @@
+/*
+ * 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.spanner.sample.repositories;
+
+import com.google.cloud.spanner.sample.entities.Album;
+import java.util.List;
+import java.util.Optional;
+import org.springframework.data.jdbc.repository.query.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface AlbumRepository extends CrudRepository {
+
+ /**
+ * The implementation for this method is automatically generated and will fetch all albums of the
+ * given singer.
+ */
+ List findAlbumsBySingerId(Long singerId);
+
+ long countAlbumsBySingerId(Long singerId);
+
+ /** Returns the first album in the database. */
+ @Query("select * from albums limit 1")
+ Optional getFirst();
+}
diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java
new file mode 100644
index 000000000..fb2ce9c59
--- /dev/null
+++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java
@@ -0,0 +1,24 @@
+/*
+ * 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.spanner.sample.repositories;
+
+import com.google.cloud.spanner.sample.entities.Concert;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ConcertRepository extends CrudRepository {}
diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java
new file mode 100644
index 000000000..a55d02f05
--- /dev/null
+++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java
@@ -0,0 +1,34 @@
+/*
+ * 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.spanner.sample.repositories;
+
+import com.google.cloud.spanner.sample.entities.Singer;
+import java.util.List;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface SingerRepository extends CrudRepository {
+
+ /**
+ * The implementation for this method is automatically generated and will fetch all singers with
+ * the given last name.
+ */
+ List findSingersByLastName(String lastName);
+
+ List findSingersByLastNameStartingWith(String prefix);
+}
diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java
new file mode 100644
index 000000000..597df5f7c
--- /dev/null
+++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java
@@ -0,0 +1,24 @@
+/*
+ * 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.spanner.sample.repositories;
+
+import com.google.cloud.spanner.sample.entities.Track;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface TrackRepository extends CrudRepository