From 822bc0a3e263da32e77c89a22507e9d31c5a537e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 2 Jun 2023 16:46:12 +0200 Subject: [PATCH 001/173] chore(deps): update dependency com.google.cloud:libraries-bom to v26.16.0 (#1249) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:libraries-bom](https://cloud.google.com/java/docs/bom) ([source](https://togithub.com/googleapis/java-cloud-bom)) | `26.15.0` -> `26.16.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.16.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.16.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.16.0/compatibility-slim/26.15.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.16.0/confidence-slim/26.15.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-cloud-bom ### [`v26.16.0`](https://togithub.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#​26160-httpsgithubcomgoogleapisjava-cloud-bomcomparev26150v26160-2023-05-31) ##### Dependencies - update dependency com.google.cloud:first-party-dependencies to v3.10.0 ([#​6000](https://togithub.com/googleapis/java-cloud-bom/issues/6000)) ([9880029](https://togithub.com/googleapis/java-cloud-bom/commit/9880029ca50417bc05d15cf0af50954256226b47)) - update dependency com.google.cloud:first-party-dependencies to v3.10.1 ([#​6018](https://togithub.com/googleapis/java-cloud-bom/issues/6018)) ([291545a](https://togithub.com/googleapis/java-cloud-bom/commit/291545a9f21bc405cebc547d1b1e8bdc90a4fe46)) - update dependency com.google.cloud:gapic-libraries-bom to v1.12.0 ([#​6002](https://togithub.com/googleapis/java-cloud-bom/issues/6002)) ([27ecac9](https://togithub.com/googleapis/java-cloud-bom/commit/27ecac9088655948c83089c2e3c4f701211d8e45)) - update dependency com.google.cloud:google-cloud-bigquery to v2.27.0 ([#​5993](https://togithub.com/googleapis/java-cloud-bom/issues/5993)) ([a9867e8](https://togithub.com/googleapis/java-cloud-bom/commit/a9867e854f8aea21a488919cb7494aec1a443c7a)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v2.37.2 ([#​6001](https://togithub.com/googleapis/java-cloud-bom/issues/6001)) ([9f2e1f7](https://togithub.com/googleapis/java-cloud-bom/commit/9f2e1f7725f0cfa207810d069ceed1c3d5ae7a4e)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.23.2 ([#​6010](https://togithub.com/googleapis/java-cloud-bom/issues/6010)) ([4aa461c](https://togithub.com/googleapis/java-cloud-bom/commit/4aa461c5897a7df2f3593a7ed55153adf25c5b70)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.14.7 ([#​6003](https://togithub.com/googleapis/java-cloud-bom/issues/6003)) ([3f38cb1](https://togithub.com/googleapis/java-cloud-bom/commit/3f38cb11a24837c03bda4e005d49db978dd7e1c5)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.12.0 ([#​6014](https://togithub.com/googleapis/java-cloud-bom/issues/6014)) ([352c3ee](https://togithub.com/googleapis/java-cloud-bom/commit/352c3eeb9481e2ba1679b59d9de3970cd9913580)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.15.2 ([#​6006](https://togithub.com/googleapis/java-cloud-bom/issues/6006)) ([da161ad](https://togithub.com/googleapis/java-cloud-bom/commit/da161adf965666aa123c469120119057e52a93a7)) - update dependency com.google.cloud:google-cloud-logging-logback to v0.130.13-alpha ([#​6011](https://togithub.com/googleapis/java-cloud-bom/issues/6011)) ([c9e6e0f](https://togithub.com/googleapis/java-cloud-bom/commit/c9e6e0f701c9c3ee9ce49218f84334427df49dc4)) - update dependency com.google.cloud:google-cloud-nio to v0.126.16 ([#​6008](https://togithub.com/googleapis/java-cloud-bom/issues/6008)) ([19f3cb0](https://togithub.com/googleapis/java-cloud-bom/commit/19f3cb039c8698e2dd6c2b9d2ed334df688f6810)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.123.13 ([#​6009](https://togithub.com/googleapis/java-cloud-bom/issues/6009)) ([5b8348d](https://togithub.com/googleapis/java-cloud-bom/commit/5b8348d926032d4ea3df3e7d1ed52de372e9ad74)) - update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.12.6 ([#​6012](https://togithub.com/googleapis/java-cloud-bom/issues/6012)) ([88e259c](https://togithub.com/googleapis/java-cloud-bom/commit/88e259c36b607d94348d51382712a0f267af76eb)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.42.2 ([#​5997](https://togithub.com/googleapis/java-cloud-bom/issues/5997)) ([a233987](https://togithub.com/googleapis/java-cloud-bom/commit/a23398776b5304485c5365378b5f93f4eadf0304)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.42.3 ([#​6016](https://togithub.com/googleapis/java-cloud-bom/issues/6016)) ([e063e7c](https://togithub.com/googleapis/java-cloud-bom/commit/e063e7c2473b369af25c70c098cb7f815e0a59da)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.10.0 ([#​6017](https://togithub.com/googleapis/java-cloud-bom/issues/6017)) ([9f6ec63](https://togithub.com/googleapis/java-cloud-bom/commit/9f6ec63d16d6b3e70177d25709208baaabb93aed)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.22.3 ([#​6007](https://togithub.com/googleapis/java-cloud-bom/issues/6007)) ([0de3cda](https://togithub.com/googleapis/java-cloud-bom/commit/0de3cda024458a7d39b9e3ccf4c77c564d545f96))
--- ### 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://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- 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 cf10eb51d..06de2d0ec 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.15.0 + 26.16.0 pom import From 18d612823a55333eb3aaccfefa0934bda1abf12c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Jun 2023 22:54:14 +0000 Subject: [PATCH 002/173] build(deps): bump cryptography from 39.0.1 to 41.0.0 in /.kokoro (#1251) Bumps [cryptography](https://togithub.com/pyca/cryptography) from 39.0.1 to 41.0.0.
Changelog

Sourced from cryptography's changelog.

41.0.0 - 2023-05-30


* **BACKWARDS INCOMPATIBLE:** Support for OpenSSL less than 1.1.1d has been
  removed.  Users on older version of OpenSSL will need to upgrade.
* **BACKWARDS INCOMPATIBLE:** Support for Python 3.6 has been removed.
* **BACKWARDS INCOMPATIBLE:** Dropped support for LibreSSL < 3.6.
* Updated the minimum supported Rust version (MSRV) to 1.56.0, from 1.48.0.
* Updated Windows, macOS, and Linux wheels to be compiled with OpenSSL 3.1.1.
* Added support for the :class:`~cryptography.x509.OCSPAcceptableResponses`
  OCSP extension.
* Added support for the :class:`~cryptography.x509.MSCertificateTemplate`
  proprietary Microsoft certificate extension.
* Implemented support for equality checks on all asymmetric public key types.
* Added support for ``aes256-gcm@openssh.com`` encrypted keys in
  :func:`~cryptography.hazmat.primitives.serialization.load_ssh_private_key`.
* Added support for obtaining X.509 certificate signature algorithm parameters
  (including PSS) via
  :meth:`~cryptography.x509.Certificate.signature_algorithm_parameters`.
* Support signing :class:`~cryptography.hazmat.primitives.asymmetric.padding.PSS`
  X.509 certificates via the new keyword-only argument ``rsa_padding`` on
  :meth:`~cryptography.x509.CertificateBuilder.sign`.
* Added support for
  :class:`~cryptography.hazmat.primitives.ciphers.aead.ChaCha20Poly1305`
  on BoringSSL.

.. _v40-0-2:

40.0.2 - 2023-04-14

  • Fixed compilation when using LibreSSL 3.7.2.
  • Added some functions to support an upcoming pyOpenSSL release.

.. _v40-0-1:

40.0.1 - 2023-03-24


* Fixed a bug where certain operations would fail if an object happened to be
  in the top-half of the memory-space. This only impacted 32-bit systems.

.. _v40-0-0:

40.0.0 - 2023-03-24

  • BACKWARDS INCOMPATIBLE: As announced in the 39.0.0 changelog, the way cryptography links OpenSSL has changed. This only impacts users who

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cryptography&package-manager=pip&previous-version=39.0.1&new-version=41.0.0)](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 8f75d26c18844617e275feb952db415a067a91d2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 7 Jun 2023 04:43:32 +0200 Subject: [PATCH 003/173] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.4.5 (#1253) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 64082e85e..3085d4986 100644 --- a/pom.xml +++ b/pom.xml @@ -393,7 +393,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.4.4 + 3.4.5 From 80d2b9d3e4c3265522bbb20766bff1f164617711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 8 Jun 2023 08:16:55 +0200 Subject: [PATCH 004/173] feat: support untyped NULL value parameters (#1224) * feat: support untyped NULL value parameters * test: add tests for untyped null parameter values * fix: update metadata test with the new table * test: add expected table for PG * refactor: move logic to ParameterStore --- .../jdbc/AbstractJdbcPreparedStatement.java | 3 +- .../spanner/jdbc/JdbcParameterStore.java | 24 ++++++- .../jdbc/JdbcPreparedStatementTest.java | 38 +++-------- ...PreparedStatementWithMockedServerTest.java | 67 +++++++++++++++++++ .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 6 +- .../jdbc/it/ITJdbcPgDatabaseMetaDataTest.java | 2 + .../jdbc/it/ITJdbcPreparedStatementTest.java | 33 +++++++++ .../spanner/jdbc/it/CreateMusicTables.sql | 23 +++++++ .../jdbc/it/CreateMusicTables_Emulator.sql | 23 +++++++ .../spanner/jdbc/it/CreateMusicTables_PG.sql | 21 ++++++ 10 files changed, 204 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java b/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java index 847f54d38..cd1c50a73 100644 --- a/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java +++ b/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java @@ -81,7 +81,8 @@ public void addBatch(String sql) throws SQLException { @Override public void setNull(int parameterIndex, int sqlType) throws SQLException { checkClosed(); - parameters.setParameter(parameterIndex, null, sqlType, null); + parameters.setParameter( + parameterIndex, /* value = */ null, sqlType, /* scaleOrLength = */ null); } @Override diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index 3ce105aa7..5fb4177fc 100644 --- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -24,6 +24,7 @@ import com.google.cloud.spanner.Value; import com.google.cloud.spanner.ValueBinder; import com.google.common.io.CharStreams; +import com.google.protobuf.NullValue; import com.google.rpc.Code; import java.io.IOException; import java.io.InputStream; @@ -231,6 +232,10 @@ void setParameter( } private void checkTypeAndValueSupported(Object value, int sqlType) throws SQLException { + if (value == null) { + // null is always supported, as we will just fall back to an untyped NULL value. + return; + } if (!isTypeSupported(sqlType)) { throw JdbcSqlExceptionFactory.of( "Type " + sqlType + " is not supported", Code.INVALID_ARGUMENT); @@ -775,8 +780,13 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu case Types.LONGVARBINARY: case Types.BLOB: return binder.toBytesArray(null); + default: + return binder.to( + Value.untyped( + com.google.protobuf.Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build())); } - throw JdbcSqlExceptionFactory.unsupported("Unknown/unsupported array base type: " + type); } if (boolean[].class.isAssignableFrom(value.getClass())) { @@ -864,7 +874,9 @@ private List toDoubleList(Number[] input) { */ private Builder setNullValue(ValueBinder binder, Integer sqlType) { if (sqlType == null) { - return binder.to((String) null); + return binder.to( + Value.untyped( + com.google.protobuf.Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build())); } switch (sqlType) { case Types.BIGINT: @@ -924,8 +936,14 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) { return binder.to((ByteArray) null); case Types.VARCHAR: return binder.to((String) null); + case JsonType.VENDOR_TYPE_NUMBER: + return binder.to(Value.json(null)); + case PgJsonbType.VENDOR_TYPE_NUMBER: + return binder.to(Value.pgJsonb(null)); default: - throw new IllegalArgumentException("Unsupported sql type for setting to null: " + sqlType); + return binder.to( + Value.untyped( + com.google.protobuf.Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build())); } } } 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 b4c33a802..8f21e68d3 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -20,7 +20,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.mock; @@ -39,7 +38,6 @@ import com.google.cloud.spanner.Value; import com.google.cloud.spanner.connection.AbstractStatementParser; import com.google.cloud.spanner.connection.Connection; -import com.google.rpc.Code; import java.io.ByteArrayInputStream; import java.io.StringReader; import java.math.BigDecimal; @@ -47,7 +45,6 @@ import java.net.URL; import java.sql.Date; import java.sql.JDBCType; -import java.sql.PreparedStatement; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Time; @@ -197,7 +194,10 @@ public void testParameters() throws SQLException, MalformedURLException { ps.setObject(35, "TEST"); ps.setObject(36, "TEST", Types.NVARCHAR); ps.setObject(37, "TEST", Types.NVARCHAR, 20); + ps.setRef(38, null); + ps.setRowId(39, null); ps.setShort(40, (short) 1); + ps.setSQLXML(41, null); ps.setString(42, "TEST"); ps.setTime(43, new Time(1000L)); ps.setTime(44, new Time(1000L), Calendar.getInstance(TimeZone.getTimeZone("GMT"))); @@ -211,8 +211,6 @@ public void testParameters() throws SQLException, MalformedURLException { ps.setObject(52, "{}", JsonType.VENDOR_TYPE_NUMBER); ps.setObject(53, "{}", PgJsonbType.VENDOR_TYPE_NUMBER); - testSetUnsupportedTypes(ps); - JdbcParameterMetaData pmd = ps.getParameterMetaData(); assertEquals(numberOfParams, pmd.getParameterCount()); assertEquals(JdbcArray.class.getName(), pmd.getParameterClassName(1)); @@ -274,33 +272,9 @@ public void testParameters() throws SQLException, MalformedURLException { } } - private void testSetUnsupportedTypes(PreparedStatement ps) { - try { - ps.setRef(38, null); - fail("missing expected exception"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); - } - try { - ps.setRowId(39, null); - fail("missing expected exception"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); - } - try { - ps.setSQLXML(41, null); - fail("missing expected exception"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); - } - } - @Test public void testSetNullValues() throws SQLException { - final int numberOfParameters = 27; + final int numberOfParameters = 31; String sql = generateSqlWithParameters(numberOfParameters); try (JdbcPreparedStatement ps = new JdbcPreparedStatement(createMockConnection(), sql)) { int index = 0; @@ -331,6 +305,10 @@ public void testSetNullValues() throws SQLException { ps.setNull(++index, Types.BIT); ps.setNull(++index, Types.VARBINARY); ps.setNull(++index, Types.VARCHAR); + ps.setNull(++index, JsonType.VENDOR_TYPE_NUMBER); + ps.setNull(++index, PgJsonbType.VENDOR_TYPE_NUMBER); + ps.setNull(++index, Types.OTHER); + ps.setNull(++index, Types.NULL); assertEquals(numberOfParameters, index); JdbcParameterMetaData pmd = ps.getParameterMetaData(); diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java index 9da17d7db..d3607d842 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java @@ -25,6 +25,7 @@ import com.google.cloud.spanner.MockSpannerServiceImpl; import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Value; import com.google.cloud.spanner.connection.SpannerPool; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlBatchUpdateException; import io.grpc.Server; @@ -36,6 +37,7 @@ import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.Types; import java.util.Arrays; import java.util.Collection; import org.junit.After; @@ -193,4 +195,69 @@ public void testExecuteBatch_withException() throws SQLException { } } } + + @Test + public void testInsertUntypedNullValues() throws SQLException { + mockSpanner.putStatementResult( + StatementResult.update( + Statement.newBuilder( + "insert into all_nullable_types (ColInt64, ColFloat64, ColBool, ColString, ColBytes, ColDate, ColTimestamp, ColNumeric, ColJson, ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColBytesArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray) " + + "values (@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16, @p17, @p18)") + .bind("p1") + .to((Value) null) + .bind("p2") + .to((Value) null) + .bind("p3") + .to((Value) null) + .bind("p4") + .to((Value) null) + .bind("p5") + .to((Value) null) + .bind("p6") + .to((Value) null) + .bind("p7") + .to((Value) null) + .bind("p8") + .to((Value) null) + .bind("p9") + .to((Value) null) + .bind("p10") + .to((Value) null) + .bind("p11") + .to((Value) null) + .bind("p12") + .to((Value) null) + .bind("p13") + .to((Value) null) + .bind("p14") + .to((Value) null) + .bind("p15") + .to((Value) null) + .bind("p16") + .to((Value) null) + .bind("p17") + .to((Value) null) + .bind("p18") + .to((Value) null) + .build(), + 1L)); + try (Connection connection = createConnection()) { + for (int type : new int[] {Types.OTHER, Types.NULL}) { + try (PreparedStatement statement = + connection.prepareStatement( + "insert into all_nullable_types (" + + "ColInt64, ColFloat64, ColBool, ColString, ColBytes, ColDate, ColTimestamp, ColNumeric, ColJson, " + + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColBytesArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray) " + + "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) { + for (int param = 1; + param <= statement.getParameterMetaData().getParameterCount(); + param++) { + statement.setNull(param, type); + } + assertEquals(1, statement.executeUpdate()); + } + mockSpanner.clearRequests(); + } + } + } } diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index ea7c236a4..7e2481a23 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -512,7 +512,8 @@ private IndexInfo( new IndexInfo("TableWithRef", false, "PRIMARY_KEY", 1, "Id", "A"), new IndexInfo("TableWithRef", true, "FOREIGN_KEY", 1, "RefFloat", "A"), new IndexInfo("TableWithRef", true, "FOREIGN_KEY", 2, "RefString", "A"), - new IndexInfo("TableWithRef", true, "FOREIGN_KEY", 3, "RefDate", "A")); + new IndexInfo("TableWithRef", true, "FOREIGN_KEY", 3, "RefDate", "A"), + new IndexInfo("all_nullable_types", false, "PRIMARY_KEY", 1, "ColInt64", "A")); @Test public void testGetIndexInfo() throws SQLException { @@ -860,7 +861,8 @@ private Table(String name, String type) { new Table("SingersView", "VIEW"), new Table("Songs"), new Table("TableWithAllColumnTypes"), - new Table("TableWithRef")); + new Table("TableWithRef"), + new Table("all_nullable_types")); @Test public void testGetTables() throws SQLException { diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java index bbd37122c..ff0bff7a9 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java @@ -420,6 +420,7 @@ private IndexInfo( new IndexInfo("albums", false, "PRIMARY_KEY", 1, "singerid", "A"), new IndexInfo("albums", false, "PRIMARY_KEY", 2, "albumid", "A"), new IndexInfo("albums", true, "albumsbyalbumtitle", 1, "albumtitle", "A"), + new IndexInfo("all_nullable_types", false, "PRIMARY_KEY", 1, "colint64", "A"), new IndexInfo("concerts", false, "PRIMARY_KEY", 1, "venueid", "A"), new IndexInfo("concerts", false, "PRIMARY_KEY", 2, "singerid", "A"), new IndexInfo("concerts", false, "PRIMARY_KEY", 3, "concertdate", "A"), @@ -790,6 +791,7 @@ private Table(String name, String type) { private static final List EXPECTED_TABLES = Arrays.asList( new Table("albums"), + new Table("all_nullable_types"), new Table("concerts"), new Table("singers"), // TODO: Enable when views are supported for PostgreSQL dialect databases. diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index c1d841696..2864559c8 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -1294,6 +1294,39 @@ public void test12_InsertReturningTestData() throws SQLException { } } + @Test + public void test13_InsertUntypedNullValues() throws SQLException { + try (Connection connection = createConnection(env, database)) { + try (PreparedStatement preparedStatement = + connection.prepareStatement( + "insert into all_nullable_types (" + + "ColInt64, ColFloat64, ColBool, ColString, ColBytes, ColDate, ColTimestamp, ColNumeric, ColJson, " + + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColBytesArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray) " + + "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) { + for (int param = 1; + param <= preparedStatement.getParameterMetaData().getParameterCount(); + param++) { + preparedStatement.setNull(param, Types.OTHER); + } + if (getDialect() == Dialect.POSTGRESQL) { + // PostgreSQL-dialect databases do not allow NULLs in primary keys. + preparedStatement.setLong(1, 1L); + } + assertEquals(1, preparedStatement.executeUpdate()); + + // Verify that calling preparedStatement.setObject(index, null) works. + for (int param = 1; + param <= preparedStatement.getParameterMetaData().getParameterCount(); + param++) { + preparedStatement.setObject(param, null); + } + // We need a different primary key value to insert another row. + preparedStatement.setLong(1, 2L); + assertEquals(1, preparedStatement.executeUpdate()); + } + } + } + private List readValuesFromFile(String filename) { StringBuilder builder = new StringBuilder(); try (InputStream stream = ITJdbcPreparedStatementTest.class.getResourceAsStream(filename)) { diff --git a/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql b/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql index 24579b272..153dd773d 100644 --- a/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql +++ b/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql @@ -97,6 +97,29 @@ CREATE TABLE TableWithAllColumnTypes ( ) PRIMARY KEY (ColInt64) ; +CREATE TABLE all_nullable_types ( + ColInt64 INT64, + ColFloat64 FLOAT64, + ColBool BOOL, + ColString STRING(100), + ColBytes BYTES(100), + ColDate DATE, + ColTimestamp TIMESTAMP, + ColNumeric NUMERIC, + ColJson JSON, + + ColInt64Array ARRAY, + ColFloat64Array ARRAY, + ColBoolArray ARRAY, + ColStringArray ARRAY, + ColBytesArray ARRAY, + ColDateArray ARRAY, + ColTimestampArray ARRAY, + ColNumericArray ARRAY, + ColJsonArray ARRAY, +) PRIMARY KEY (ColInt64) +; + CREATE TABLE TableWithRef ( Id INT64 NOT NULL, RefFloat FLOAT64 NOT NULL, diff --git a/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql b/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql index aaba70c19..6aa8e843c 100644 --- a/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql +++ b/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql @@ -92,6 +92,29 @@ CREATE TABLE TableWithAllColumnTypes ( ) PRIMARY KEY (ColInt64) ; +CREATE TABLE all_nullable_types ( + ColInt64 INT64, + ColFloat64 FLOAT64, + ColBool BOOL, + ColString STRING(100), + ColBytes BYTES(100), + ColDate DATE, + ColTimestamp TIMESTAMP, + ColNumeric NUMERIC, + ColJson JSON, + + ColInt64Array ARRAY, + ColFloat64Array ARRAY, + ColBoolArray ARRAY, + ColStringArray ARRAY, + ColBytesArray ARRAY, + ColDateArray ARRAY, + ColTimestampArray ARRAY, + ColNumericArray ARRAY, + ColJsonArray ARRAY, +) PRIMARY KEY (ColInt64) +; + CREATE TABLE TableWithRef ( Id INT64 NOT NULL, RefFloat FLOAT64 NOT NULL, diff --git a/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql b/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql index 438d2d5df..c77968b45 100644 --- a/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql +++ b/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql @@ -74,6 +74,27 @@ CREATE TABLE TableWithAllColumnTypes ( ColNumeric NUMERIC NOT NULL, ColJson VARCHAR NOT NULL ); +CREATE TABLE all_nullable_types ( + ColInt64 bigint primary key, + ColFloat64 float8, + ColBool boolean, + ColString varchar(100), + ColBytes bytea, + ColDate date, + ColTimestamp timestamptz, + ColNumeric numeric, + ColJson jsonb, + + ColInt64Array bigint[], + ColFloat64Array float8[], + ColBoolArray boolean[], + ColStringArray varchar(100)[], + ColBytesArray bytea[], + ColDateArray date[], + ColTimestampArray timestamptz[], + ColNumericArray numeric[], + ColJsonArray jsonb[] +); CREATE TABLE TableWithRef ( Id BIGINT NOT NULL PRIMARY KEY, From 41f40fce634cea205d5e5a9c1eb567ecb97ff655 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 12 Jun 2023 10:36:45 +0200 Subject: [PATCH 005/173] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.11.0 (#1254) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3085d4986..422b4c938 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.10.1 + 3.11.0 pom import From 0a564d9f967fa25244ea6750ad74b22403a05244 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 12 Jun 2023 16:18:22 +0200 Subject: [PATCH 006/173] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.5.6 (#1250) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 422b4c938..923ec36de 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.5.5 + 1.5.6 From ffe36b6b2087157c8d895fa348cff614435a4735 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 12 Jun 2023 17:44:14 +0200 Subject: [PATCH 007/173] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.43.0 (#1255) 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.42.3` -> `6.43.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.43.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.43.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.43.0/compatibility-slim/6.42.3)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.43.0/confidence-slim/6.42.3)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-spanner ### [`v6.43.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6430-httpsgithubcomgoogleapisjava-spannercomparev6423v6430-2023-06-07) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.42.3...v6.43.0) ##### Features - Delay transaction start option ([#​2462](https://togithub.com/googleapis/java-spanner/issues/2462)) ([f1cbd16](https://togithub.com/googleapis/java-spanner/commit/f1cbd168a7e5f48206cdfc2d782835cf7ccb8b0d)) - Make administrative request retries optional ([#​2476](https://togithub.com/googleapis/java-spanner/issues/2476)) ([ee6548c](https://togithub.com/googleapis/java-spanner/commit/ee6548cfa511d6efc99f508290ed0b1ce025a4cc)) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.11.0 ([#​2486](https://togithub.com/googleapis/java-spanner/issues/2486)) ([82400d5](https://togithub.com/googleapis/java-spanner/commit/82400d5576c3ffe08ff6bb94d8b1a307e2f41662))
--- ### 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://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 923ec36de..55e62450c 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.42.3 + 6.43.0 pom import From cf417c1777957cd14bb32af1c81d49015a26c6aa Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 18:40:13 +0000 Subject: [PATCH 008/173] chore(main): release 2.11.0 (#1256) :robot: I have created a release *beep* *boop* --- ## [2.11.0](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.10.0...v2.11.0) (2023-06-12) ### Features * Support untyped NULL value parameters ([#1224](https://togithub.com/googleapis/java-spanner-jdbc/issues/1224)) ([80d2b9d](https://togithub.com/googleapis/java-spanner-jdbc/commit/80d2b9d3e4c3265522bbb20766bff1f164617711)) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.11.0 ([#1254](https://togithub.com/googleapis/java-spanner-jdbc/issues/1254)) ([41f40fc](https://togithub.com/googleapis/java-spanner-jdbc/commit/41f40fce634cea205d5e5a9c1eb567ecb97ff655)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.42.3 ([#1248](https://togithub.com/googleapis/java-spanner-jdbc/issues/1248)) ([397d573](https://togithub.com/googleapis/java-spanner-jdbc/commit/397d5738a8126aaf090d533d0f20efb74a77a788)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.43.0 ([#1255](https://togithub.com/googleapis/java-spanner-jdbc/issues/1255)) ([ffe36b6](https://togithub.com/googleapis/java-spanner-jdbc/commit/ffe36b6b2087157c8d895fa348cff614435a4735)) --- 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 | 14 ++++++++++++++ pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- versions.txt | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57a583fc9..d51198acb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [2.11.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.10.0...v2.11.0) (2023-06-12) + + +### Features + +* Support untyped NULL value parameters ([#1224](https://github.com/googleapis/java-spanner-jdbc/issues/1224)) ([80d2b9d](https://github.com/googleapis/java-spanner-jdbc/commit/80d2b9d3e4c3265522bbb20766bff1f164617711)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.11.0 ([#1254](https://github.com/googleapis/java-spanner-jdbc/issues/1254)) ([41f40fc](https://github.com/googleapis/java-spanner-jdbc/commit/41f40fce634cea205d5e5a9c1eb567ecb97ff655)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.42.3 ([#1248](https://github.com/googleapis/java-spanner-jdbc/issues/1248)) ([397d573](https://github.com/googleapis/java-spanner-jdbc/commit/397d5738a8126aaf090d533d0f20efb74a77a788)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.43.0 ([#1255](https://github.com/googleapis/java-spanner-jdbc/issues/1255)) ([ffe36b6](https://github.com/googleapis/java-spanner-jdbc/commit/ffe36b6b2087157c8d895fa348cff614435a4735)) + ## [2.10.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.16...v2.10.0) (2023-05-30) diff --git a/pom.xml b/pom.xml index 55e62450c..9b0d4aec6 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.10.1-SNAPSHOT + 2.11.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 675c8fe27..9b0ce3fe4 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.10.1-SNAPSHOT + 2.11.0 diff --git a/versions.txt b/versions.txt index 151946b0b..bee319b9a 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.10.0:2.10.1-SNAPSHOT +google-cloud-spanner-jdbc:2.11.0:2.11.0 From 34ee41821ec3b94eec9cfa92fc7931f46e5224f4 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 20:06:13 +0000 Subject: [PATCH 009/173] chore(main): release 2.11.1-SNAPSHOT (#1257) :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 9b0d4aec6..290d63312 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.0 + 2.11.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 9b0ce3fe4..5e328938b 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.0 + 2.11.1-SNAPSHOT diff --git a/versions.txt b/versions.txt index bee319b9a..71cbbdd6b 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.11.0:2.11.0 +google-cloud-spanner-jdbc:2.11.0:2.11.1-SNAPSHOT From 79ab6729548f106136b87c2a2c985b95a748f2d2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 14 Jun 2023 22:16:42 +0200 Subject: [PATCH 010/173] chore(deps): update dependency com.google.cloud:libraries-bom to v26.17.0 (#1259) --- 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 06de2d0ec..d4b7215b9 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.16.0 + 26.17.0 pom import From 2f36e1d0455d5e42d0be898d15075b8cfb5a27dc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 14 Jun 2023 22:17:02 +0200 Subject: [PATCH 011/173] build(deps): update dependency org.codehaus.mojo:build-helper-maven-plugin to v3.4.0 (#1260) --- samples/install-without-bom/pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 42875833f..1e2ac9dfd 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -53,7 +53,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.4.0 add-snippets-source diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 5e328938b..8559ccd43 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -52,7 +52,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.4.0 add-snippets-source From 24eabfa0d12647372486896b082655e5e5fbf868 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 14 Jun 2023 22:17:24 +0200 Subject: [PATCH 012/173] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.11.0 (#1258) --- 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 1e2ac9dfd..8425d143f 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.10.0 + 2.11.0 From 286052a586efda8aa31e2785c29166060ad8ef32 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Jun 2023 19:36:50 +0200 Subject: [PATCH 013/173] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.0 (#1262) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 290d63312..04a595306 100644 --- a/pom.xml +++ b/pom.xml @@ -256,7 +256,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.4.1 + 3.5.0 From defe065880ffa0b07fcd487f80e9a5add69c7fd1 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 16 Jun 2023 23:07:26 +0530 Subject: [PATCH 014/173] chore: Update `dependabot.yml` template (#1813) (#1261) * chore: Update `dependabot.yml` template not to touch pip dependencies Source-Link: https://github.com/googleapis/synthtool/commit/f961eb0fe51109238128055897ccba1b70dbd804 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:af2eda87a54601ae7b7b2be5055c17b43ac98a7805b586772db314de8a7d4a1d Co-authored-by: Owl Bot --- .github/.OwlBot.lock.yaml | 3 ++- .github/dependabot.yml | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index aadf54f64..73568a1e9 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,4 +13,5 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:ad9cabee4c022f1aab04a71332369e0c23841062124818a4490f73337f790337 + digest: sha256:af2eda87a54601ae7b7b2be5055c17b43ac98a7805b586772db314de8a7d4a1d +# created: 2023-06-16T02:10:09.149325782Z diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c8f413b0d..fde1ced49 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,10 +5,13 @@ updates: schedule: interval: "daily" # Disable version updates for Maven dependencies - open-pull-requests-limit: 0 + # we use renovate-bot as well as shared-dependencies BOM to update maven dependencies. + ignore: "*" - package-ecosystem: "pip" directory: "/" schedule: interval: "daily" # Disable version updates for pip dependencies - open-pull-requests-limit: 0 \ No newline at end of file + # If a security vulnerability comes in, we will be notified about + # it via template in the synthtool repository. + ignore: "*" From 9ac6ecc66884d067dc1a71f89d63481db842c192 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Thu, 22 Jun 2023 18:44:13 +0000 Subject: [PATCH 015/173] chore: Java 8 unit test to build code in Java 17 and run tests on Java 8 (#1800) (#1266) * Our Java projects are configured to produce Java 8-compatible bytecode via https://togithub.com/googleapis/java-shared-config/blob/main/pom.xml#L848. This unit test change ensures this config is applied correctly. * This change also switches the JDK distribution of GitHub Actions to temurin from zulu. * For the repositories that mark "dependencies (8)" and "dependencies (11)" as required, they should point to only "dependencies (17)" via `.github/sync-repo-settings.yaml` and repo's Settings tab. Source-Link: https://togithub.com/googleapis/synthtool/commit/cbe010084fc59dc15730c86e9b8e03ddac1de050 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:32851debfefed2b66038e0141f1b5c2103bb59ba80b7475adbc10ef7abab3de7 Closes https://togithub.com/googleapis/java-spanner-jdbc/pull/1265 --- .github/.OwlBot.lock.yaml | 4 ++-- .github/dependabot.yml | 6 ++++-- .github/sync-repo-settings.yaml | 3 +-- .github/workflows/ci.yaml | 26 ++++++++++++++++++++++++-- .kokoro/build.sh | 3 ++- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 73568a1e9..47a70ea40 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:af2eda87a54601ae7b7b2be5055c17b43ac98a7805b586772db314de8a7d4a1d -# created: 2023-06-16T02:10:09.149325782Z + digest: sha256:32851debfefed2b66038e0141f1b5c2103bb59ba80b7475adbc10ef7abab3de7 +# created: 2023-06-22T15:06:52.039318836Z diff --git a/.github/dependabot.yml b/.github/dependabot.yml index fde1ced49..203f9eacc 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,7 +6,8 @@ updates: interval: "daily" # Disable version updates for Maven dependencies # we use renovate-bot as well as shared-dependencies BOM to update maven dependencies. - ignore: "*" + ignore: + - dependency-name: "*" - package-ecosystem: "pip" directory: "/" schedule: @@ -14,4 +15,5 @@ updates: # Disable version updates for pip dependencies # If a security vulnerability comes in, we will be notified about # it via template in the synthtool repository. - ignore: "*" + ignore: + - dependency-name: "*" diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml index 19bc1242a..4879f02a5 100644 --- a/.github/sync-repo-settings.yaml +++ b/.github/sync-repo-settings.yaml @@ -29,8 +29,7 @@ branchProtectionRules: requiresStrictStatusChecks: false # List of required status check contexts that must pass for commits to be accepted to matching branches. requiredStatusCheckContexts: - - "dependencies (8)" - - "dependencies (11)" + - "dependencies (17)" - "lint" - "clirr" - "units (8)" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e3bb26e37..65436cde4 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -25,7 +25,7 @@ jobs: strategy: fail-fast: false matrix: - java: [8, 11, 17] + java: [11, 17] steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 @@ -36,6 +36,28 @@ jobs: - run: .kokoro/build.sh env: JOB_TYPE: test + units-java8: + # Building using Java 17 and run the tests with Java 8 runtime + name: "units (8)" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + java-version: 8 + distribution: zulu + - 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 + run: echo "SUREFIRE_JVM_OPT=-Djvm=${JAVA_HOME}/bin/java" >> $GITHUB_ENV + shell: bash + - uses: actions/setup-java@v3 + with: + java-version: 17 + distribution: zulu + - run: .kokoro/build.sh + env: + JOB_TYPE: test windows: runs-on: windows-latest steps: @@ -54,7 +76,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [8, 11, 17] + java: [17] steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 diff --git a/.kokoro/build.sh b/.kokoro/build.sh index f315d0cc9..1f2ae77da 100755 --- a/.kokoro/build.sh +++ b/.kokoro/build.sh @@ -47,7 +47,8 @@ set +e case ${JOB_TYPE} in test) - mvn test -B -ntp -Dclirr.skip=true -Denforcer.skip=true + echo "SUREFIRE_JVM_OPT: ${SUREFIRE_JVM_OPT}" + mvn test -B -ntp -Dclirr.skip=true -Denforcer.skip=true ${SUREFIRE_JVM_OPT} RETURN_CODE=$? ;; lint) From bb23df01bf401310c91c3fc2069a2ea16c70f5a4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Jun 2023 20:13:14 +0200 Subject: [PATCH 016/173] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.12.0 (#1267) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 04a595306..da881176b 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.11.0 + 3.12.0 pom import From 83f55717e875552f1f2ff7ac56bd606cabf2ac57 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Jun 2023 20:14:44 +0200 Subject: [PATCH 017/173] test(deps): update dependency com.google.truth:truth to v1.1.5 (#1264) --- samples/install-without-bom/pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- samples/snippets/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 8425d143f..3902fadfa 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.1.4 + 1.1.5 test diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 8559ccd43..fb3b84c00 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -41,7 +41,7 @@ com.google.truth truth - 1.1.4 + 1.1.5 test diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index d4b7215b9..fe2761c64 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -53,7 +53,7 @@ com.google.truth truth - 1.1.4 + 1.1.5 test From 6de47728bdd665a3c955d33fc74c33a546e188b6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Jun 2023 20:15:19 +0200 Subject: [PATCH 018/173] test(deps): update dependency com.google.truth:truth to v1.1.5 (#1263) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index da881176b..7a3359980 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ google-cloud-spanner-jdbc 4.13.2 3.0.2 - 1.1.4 + 1.1.5 4.11.0 2.2 0.31.1 From d82b304044d2c70bb363327474f9375b1834c3a2 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 26 Jun 2023 19:36:13 +0000 Subject: [PATCH 019/173] chore(main): release 2.11.1 (#1270) :robot: I have created a release *beep* *boop* --- ## [2.11.1](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.11.0...v2.11.1) (2023-06-26) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.12.0 ([#1267](https://togithub.com/googleapis/java-spanner-jdbc/issues/1267)) ([bb23df0](https://togithub.com/googleapis/java-spanner-jdbc/commit/bb23df01bf401310c91c3fc2069a2ea16c70f5a4)) --- 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 d51198acb..615325320 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.11.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.0...v2.11.1) (2023-06-26) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.12.0 ([#1267](https://github.com/googleapis/java-spanner-jdbc/issues/1267)) ([bb23df0](https://github.com/googleapis/java-spanner-jdbc/commit/bb23df01bf401310c91c3fc2069a2ea16c70f5a4)) + ## [2.11.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.10.0...v2.11.0) (2023-06-12) diff --git a/pom.xml b/pom.xml index 7a3359980..e52047829 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.1-SNAPSHOT + 2.11.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 fb3b84c00..95a4b010c 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.1-SNAPSHOT + 2.11.1 diff --git a/versions.txt b/versions.txt index 71cbbdd6b..37a47637a 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.11.0:2.11.1-SNAPSHOT +google-cloud-spanner-jdbc:2.11.1:2.11.1 From c5499012dff10c5999cf046f3e1076e17c973662 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Jun 2023 22:56:15 +0200 Subject: [PATCH 020/173] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.43.1 (#1271) 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.43.0` -> `6.43.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.43.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.43.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.43.1/compatibility-slim/6.43.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.43.1/confidence-slim/6.43.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.43.1`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6431-httpsgithubcomgoogleapisjava-spannercomparev6430v6431-2023-06-26) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.43.0...v6.43.1) ##### Dependencies - Update dependency com.google.cloud:google-cloud-monitoring to v3.20.0 ([#​2492](https://togithub.com/googleapis/java-spanner/issues/2492)) ([faa6807](https://togithub.com/googleapis/java-spanner/commit/faa68073673e789e35b600dab72152591a647dc6)) - Update dependency com.google.cloud:google-cloud-monitoring to v3.21.0 ([#​2510](https://togithub.com/googleapis/java-spanner/issues/2510)) ([f10400b](https://togithub.com/googleapis/java-spanner/commit/f10400baf2d320991e75794250b9e1b2fb218718)) - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.12.0.with temp exclusions. ([#​2512](https://togithub.com/googleapis/java-spanner/issues/2512)) ([ce04645](https://togithub.com/googleapis/java-spanner/commit/ce0464527ef489d351b9086f6bb8922f295f1897)) - Update dependency com.google.cloud:google-cloud-trace to v2.19.0 ([#​2493](https://togithub.com/googleapis/java-spanner/issues/2493)) ([1dc7cea](https://togithub.com/googleapis/java-spanner/commit/1dc7cea723658c43b8c8d2e085c964371fb72223)) - Update dependency com.google.cloud:google-cloud-trace to v2.20.0 ([#​2511](https://togithub.com/googleapis/java-spanner/issues/2511)) ([2ea52ec](https://togithub.com/googleapis/java-spanner/commit/2ea52ec1cef2468e6c36b76797a3878f270badaa)) - Update dependency commons-io:commons-io to v2.13.0 ([#​2490](https://togithub.com/googleapis/java-spanner/issues/2490)) ([b087b0e](https://togithub.com/googleapis/java-spanner/commit/b087b0e813cacb4f08d12815d9371fe9c004ca9e)) - Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.23 ([#​2500](https://togithub.com/googleapis/java-spanner/issues/2500)) ([0b794a6](https://togithub.com/googleapis/java-spanner/commit/0b794a68d57eb990e013fdd05c72eaed868497b0)) - Update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.23 ([#​2501](https://togithub.com/googleapis/java-spanner/issues/2501)) ([9db5c78](https://togithub.com/googleapis/java-spanner/commit/9db5c7850b53fa10d1856d88908d5e8e95467206)) - Update dependency org.json:json to v20230618 ([#​2504](https://togithub.com/googleapis/java-spanner/issues/2504)) ([8a87fee](https://togithub.com/googleapis/java-spanner/commit/8a87fee19bb2dd41495a15740893375c8778f71a))
--- ### 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 e52047829..c93cfe9c8 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.43.0 + 6.43.1 pom import From dbd606b6d0ca0603d022ed1815c972a6f39a7143 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 26 Jun 2023 22:20:12 +0000 Subject: [PATCH 021/173] chore(main): release 2.11.2-SNAPSHOT (#1272) :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 c93cfe9c8..7225e3e6a 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.1 + 2.11.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 95a4b010c..104b8d2c9 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.1 + 2.11.2-SNAPSHOT diff --git a/versions.txt b/versions.txt index 37a47637a..636b8ccd8 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.11.1:2.11.1 +google-cloud-spanner-jdbc:2.11.1:2.11.2-SNAPSHOT From 4aeb61c78485c8bee608d73d8c42e852ec969d1a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 26 Jun 2023 23:44:16 +0000 Subject: [PATCH 022/173] chore(main): release 2.11.2 (#1274) :robot: I have created a release *beep* *boop* --- ## [2.11.2](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.11.1...v2.11.2) (2023-06-26) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.43.1 ([#1271](https://togithub.com/googleapis/java-spanner-jdbc/issues/1271)) ([c549901](https://togithub.com/googleapis/java-spanner-jdbc/commit/c5499012dff10c5999cf046f3e1076e17c973662)) --- 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 615325320..ff5ec7274 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.11.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.1...v2.11.2) (2023-06-26) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.43.1 ([#1271](https://github.com/googleapis/java-spanner-jdbc/issues/1271)) ([c549901](https://github.com/googleapis/java-spanner-jdbc/commit/c5499012dff10c5999cf046f3e1076e17c973662)) + ## [2.11.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.11.0...v2.11.1) (2023-06-26) diff --git a/pom.xml b/pom.xml index 7225e3e6a..5d9e4405f 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.2-SNAPSHOT + 2.11.2 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 104b8d2c9..07c7704a2 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.2-SNAPSHOT + 2.11.2 diff --git a/versions.txt b/versions.txt index 636b8ccd8..ab9730ca6 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.11.1:2.11.2-SNAPSHOT +google-cloud-spanner-jdbc:2.11.2:2.11.2 From 6bfdb9b85474be609d0a91402f4b7c81f2fac146 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 27 Jun 2023 01:18:17 +0000 Subject: [PATCH 023/173] chore(main): release 2.11.3-SNAPSHOT (#1275) :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 5d9e4405f..9827c001d 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.2 + 2.11.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 07c7704a2..8c6952781 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.2 + 2.11.3-SNAPSHOT diff --git a/versions.txt b/versions.txt index ab9730ca6..0ba2d4e46 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.2 +google-cloud-spanner-jdbc:2.11.2:2.11.3-SNAPSHOT From 7481d12a8b6dab917927f3b55553f0bd8ebb03fa Mon Sep 17 00:00:00 2001 From: Mend Renovate 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: + * + *
    + *
  1. The generatedKeysColumns is not null or empty + *
  2. The statement is a DML statement + *
  3. 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: * *
    - *
  1. The generatedKeysColumns is not null or empty + *
  2. The generatedKeysColumns is not empty *
  3. The statement is a DML statement *
  4. 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 {} diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java new file mode 100644 index 000000000..f029979ad --- /dev/null +++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.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.Venue; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface VenueRepository extends CrudRepository {} diff --git a/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java new file mode 100644 index 000000000..afb496e35 --- /dev/null +++ b/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java @@ -0,0 +1,67 @@ +/* + * 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.service; + +import com.google.cloud.spanner.sample.entities.Album; +import com.google.cloud.spanner.sample.entities.Singer; +import com.google.cloud.spanner.sample.repositories.AlbumRepository; +import com.google.cloud.spanner.sample.repositories.SingerRepository; +import com.google.common.collect.ImmutableList; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SingerService { + private final SingerRepository singerRepository; + + private final AlbumRepository albumRepository; + + public SingerService(SingerRepository singerRepository, AlbumRepository albumRepository) { + this.singerRepository = singerRepository; + this.albumRepository = albumRepository; + } + + /** Creates a singer and a list of albums in a transaction. */ + @Transactional + public Singer createSingerAndAlbums(Singer singer, Album... albums) { + // Saving a singer will return an updated singer entity that has the primary key value set. + singer = singerRepository.save(singer); + for (Album album : albums) { + // Set the singerId that was generated on the Album before saving it. + album.setSingerId(singer.getId()); + albumRepository.save(album); + } + return singer; + } + + /** + * Searches for all singers that have a last name starting with any of the given prefixes. This + * method uses a read-only transaction. Read-only transactions should be preferred to read/write + * transactions whenever possible, as read-only transactions do not take locks. + */ + @Transactional(readOnly = true) + public List listSingersWithLastNameStartingWith(String... prefixes) { + ImmutableList.Builder result = ImmutableList.builder(); + // This is not the most efficient way to search for this, but the main purpose of this method is + // to show how to use read-only transactions. + for (String prefix : prefixes) { + result.addAll(singerRepository.findSingersByLastNameStartingWith(prefix)); + } + return result.build(); + } +} diff --git a/samples/spring-data-jdbc/src/main/resources/application-cs.properties b/samples/spring-data-jdbc/src/main/resources/application-cs.properties new file mode 100644 index 000000000..96aaae7ff --- /dev/null +++ b/samples/spring-data-jdbc/src/main/resources/application-cs.properties @@ -0,0 +1,9 @@ + +# This profile uses a Cloud Spanner PostgreSQL database. + +spanner.project=my-project +spanner.instance=my-instance +spanner.database=spring-data-jdbc + +spring.datasource.url=jdbc:cloudspanner:/projects/${spanner.project}/instances/${spanner.instance}/databases/${spanner.database} +spring.datasource.driver-class-name=com.google.cloud.spanner.jdbc.JdbcDriver diff --git a/samples/spring-data-jdbc/src/main/resources/application-pg.properties b/samples/spring-data-jdbc/src/main/resources/application-pg.properties new file mode 100644 index 000000000..894f63eba --- /dev/null +++ b/samples/spring-data-jdbc/src/main/resources/application-pg.properties @@ -0,0 +1,7 @@ + +# This profile uses an open-source PostgreSQL database. + +spring.datasource.url=jdbc:postgresql://localhost:5432/spring-data-jdbc +spring.datasource.driver-class-name=org.postgresql.Driver +spring.datasource.username=postgres +spring.datasource.password=mysecretpassword diff --git a/samples/spring-data-jdbc/src/main/resources/application.properties b/samples/spring-data-jdbc/src/main/resources/application.properties new file mode 100644 index 000000000..3347f3137 --- /dev/null +++ b/samples/spring-data-jdbc/src/main/resources/application.properties @@ -0,0 +1,9 @@ + +# This application can use both a Cloud Spanner PostgreSQL database or an open-source PostgreSQL +# database. Which database is used is determined by the active profile: +# 1. 'cs' means use Cloud Spanner. +# 2. 'pg' means use open-source PostgreSQL. + +# Activate the Cloud Spanner profile by default. +# Change to 'pg' to activate the PostgreSQL profile. +spring.profiles.default=cs diff --git a/samples/spring-data-jdbc/src/main/resources/create_schema.sql b/samples/spring-data-jdbc/src/main/resources/create_schema.sql new file mode 100644 index 000000000..60552d3ad --- /dev/null +++ b/samples/spring-data-jdbc/src/main/resources/create_schema.sql @@ -0,0 +1,68 @@ +/* + This script creates the database schema for this sample application. + All lines that start with /* skip_on_open_source_pg */ are skipped when the application is running on a + normal PostgreSQL database. The same lines are executed when the application is running on a Cloud + Spanner database. The script is executed by the DatabaseSeeder class. +*/ + +create sequence if not exists id_generator +/* skip_on_open_source_pg */ bit_reversed_positive +; + +create table if not exists singers ( + id bigint not null primary key default nextval('id_generator'), + first_name varchar, + last_name varchar, + full_name varchar generated always as (CASE WHEN first_name IS NULL THEN last_name + WHEN last_name IS NULL THEN first_name + ELSE first_name || ' ' || last_name END) stored, + active boolean default true, + created_at timestamptz default current_timestamp, + updated_at timestamptz default current_timestamp +); + +create table if not exists albums ( + id bigint not null primary key default nextval('id_generator'), + title varchar not null, + marketing_budget numeric, + release_date date, + cover_picture bytea, + singer_id bigint not null, + created_at timestamptz default current_timestamp, + updated_at timestamptz default current_timestamp, + constraint fk_albums_singers foreign key (singer_id) references singers (id) +); + +create table if not exists tracks ( + id bigint not null, + track_number bigint not null, + title varchar not null, + sample_rate float8 not null, + created_at timestamptz default current_timestamp, + updated_at timestamptz default current_timestamp, + primary key (id, track_number) +) +/* skip_on_open_source_pg */ interleave in parent albums on delete cascade +; + +create table if not exists venues ( + id bigint not null primary key default nextval('id_generator'), + name varchar not null, + description jsonb not null, + created_at timestamptz default current_timestamp, + updated_at timestamptz default current_timestamp +); + +create table if not exists concerts ( + id bigint not null primary key default nextval('id_generator'), + venue_id bigint not null, + singer_id bigint not null, + name varchar not null, + start_time timestamptz not null, + end_time timestamptz not null, + created_at timestamptz default current_timestamp, + updated_at timestamptz default current_timestamp, + constraint fk_concerts_venues foreign key (venue_id) references venues (id), + constraint fk_concerts_singers foreign key (singer_id) references singers (id), + constraint chk_end_time_after_start_time check (end_time > start_time) +); diff --git a/samples/spring-data-jdbc/src/main/resources/drop_schema.sql b/samples/spring-data-jdbc/src/main/resources/drop_schema.sql new file mode 100644 index 000000000..23e7b65d3 --- /dev/null +++ b/samples/spring-data-jdbc/src/main/resources/drop_schema.sql @@ -0,0 +1,5 @@ +drop table if exists concerts; +drop table if exists venues; +drop table if exists tracks; +drop table if exists albums; +drop table if exists singers; diff --git a/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java b/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java new file mode 100644 index 000000000..726b32cb3 --- /dev/null +++ b/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java @@ -0,0 +1,766 @@ +/* + * 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 com.google.cloud.spanner.sample.DatabaseSeeder.INITIAL_SINGERS; +import static com.google.cloud.spanner.sample.DatabaseSeeder.randomDate; +import static com.google.cloud.spanner.sample.DatabaseSeeder.randomTitle; +import static junit.framework.TestCase.assertEquals; + +import com.google.cloud.Timestamp; +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.sample.entities.Singer; +import com.google.common.collect.Streams; +import com.google.longrunning.Operation; +import com.google.protobuf.Any; +import com.google.protobuf.Empty; +import com.google.protobuf.ListValue; +import com.google.protobuf.NullValue; +import com.google.protobuf.Value; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import com.google.spanner.v1.CommitRequest; +import com.google.spanner.v1.ExecuteBatchDmlRequest; +import com.google.spanner.v1.ExecuteSqlRequest; +import com.google.spanner.v1.ResultSet; +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.TypeAnnotationCode; +import com.google.spanner.v1.TypeCode; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.springframework.boot.SpringApplication; + +@RunWith(JUnit4.class) +public class ApplicationTest extends AbstractMockServerTest { + + @BeforeClass + public static void setupQueryResults() { + // Set the database dialect. + mockSpanner.putStatementResult(StatementResult.detectDialectResult(Dialect.POSTGRESQL)); + // Set up a result for the dialect check that is executed by the JdbcConfiguration class. + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of( + "select 1 " + + "from information_schema.database_options " + + "where schema_name='public' " + + "and option_name='database_dialect' " + + "and option_value='POSTGRESQL'"), + ResultSet.newBuilder() + .setMetadata( + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("c") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("1").build()) + .build()) + .build())); + // Add a DDL response to the server. + addDdlResponseToSpannerAdmin(); + + // Set up results for the 'delete all test data' operations. + mockSpanner.putStatementResult( + StatementResult.update(Statement.of("delete from concerts"), 0L)); + mockSpanner.putStatementResult(StatementResult.update(Statement.of("delete from venues"), 0L)); + mockSpanner.putStatementResult(StatementResult.update(Statement.of("delete from tracks"), 0L)); + mockSpanner.putStatementResult(StatementResult.update(Statement.of("delete from albums"), 0L)); + mockSpanner.putStatementResult(StatementResult.update(Statement.of("delete from singers"), 0L)); + + // Set up results for inserting test data. + for (Singer singer : INITIAL_SINGERS) { + mockSpanner.putStatementResult( + StatementResult.update( + Statement.newBuilder("insert into singers (first_name, last_name) values ($1, $2)") + .bind("p1") + .to(singer.getFirstName()) + .bind("p2") + .to(singer.getLastName()) + .build(), + 1L)); + } + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of("select id from singers"), + ResultSet.newBuilder() + .setMetadata( + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("id") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .build()) + .build()) + .addAllRows( + LongStream.rangeClosed(1L, INITIAL_SINGERS.size()) + .mapToObj( + id -> + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue(String.valueOf(Long.reverse(id))) + .build()) + .build()) + .collect(Collectors.toList())) + .build())); + mockSpanner.putPartialStatementResult( + StatementResult.update( + Statement.of( + "insert into albums (title, marketing_budget, release_date, cover_picture, singer_id) values ($1, $2, $3, $4, $5)"), + 1L)); + + // Set up results for the queries that the application runs. + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of( + "SELECT \"singers\".\"id\" AS \"id\", \"singers\".\"active\" AS \"active\", " + + "\"singers\".\"last_name\" AS \"last_name\", \"singers\".\"full_name\" AS \"full_name\", " + + "\"singers\".\"updated_at\" AS \"updated_at\", \"singers\".\"created_at\" AS \"created_at\", " + + "\"singers\".\"first_name\" AS \"first_name\" FROM \"singers\""), + 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("active") + .setType(Type.newBuilder().setCode(TypeCode.BOOL).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("last_name") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("full_name") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("first_name") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .build()) + .build()) + .addAllRows( + Streams.mapWithIndex( + INITIAL_SINGERS.stream(), + (singer, index) -> + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue(String.valueOf(Long.reverse(index + 1))) + .build()) + .addValues(Value.newBuilder().setBoolValue(true).build()) + .addValues( + Value.newBuilder() + .setStringValue(singer.getLastName()) + .build()) + .addValues( + Value.newBuilder() + .setStringValue( + singer.getFirstName() + " " + singer.getLastName()) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setStringValue(singer.getFirstName()) + .build()) + .build()) + .collect(Collectors.toList())) + .build())); + mockSpanner.putPartialStatementResult( + StatementResult.query( + Statement.of("SELECT COUNT(*) FROM \"albums\" WHERE \"albums\".\"singer_id\" = $1"), + ResultSet.newBuilder() + .setMetadata( + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("c") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("10").build()) + .build()) + .build())); + for (long singerId : LongStream.rangeClosed(1L, INITIAL_SINGERS.size()).toArray()) { + mockSpanner.putStatementResult( + StatementResult.query( + Statement.newBuilder( + "SELECT \"albums\".\"id\" AS \"id\", \"albums\".\"title\" AS \"title\", " + + "\"albums\".\"singer_id\" AS \"singer_id\", \"albums\".\"updated_at\" AS \"updated_at\", " + + "\"albums\".\"created_at\" AS \"created_at\", \"albums\".\"release_date\" AS \"release_date\", " + + "\"albums\".\"cover_picture\" AS \"cover_picture\", \"albums\".\"marketing_budget\" AS \"marketing_budget\" " + + "FROM \"albums\" WHERE \"albums\".\"singer_id\" = $1") + .bind("p1") + .to(Long.reverse(singerId)) + .build(), + 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("title") + .setType( + Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("singer_id") + .setType( + Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("release_date") + .setType(Type.newBuilder().setCode(TypeCode.DATE).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("cover_picture") + .setType( + Type.newBuilder().setCode(TypeCode.BYTES).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("marketing_budget") + .setType( + Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation(TypeAnnotationCode.PG_NUMERIC) + .build()) + .build()) + .build()) + .build()) + .addAllRows( + IntStream.rangeClosed(1, 10) + .mapToObj( + albumId -> + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue( + String.valueOf(Long.reverse(albumId * singerId))) + .build()) + .addValues(Value.newBuilder().setStringValue(randomTitle())) + .addValues( + Value.newBuilder() + .setStringValue( + String.valueOf(Long.reverse(singerId)))) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setStringValue(randomDate().toString()) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .build()) + .collect(Collectors.toList())) + .build())); + } + mockSpanner.putStatementResult( + StatementResult.query( + Statement.newBuilder( + "INSERT INTO \"singers\" (\"active\", \"created_at\", \"first_name\", \"last_name\", \"updated_at\") VALUES ($1, $2, $3, $4, $5)\n" + + "RETURNING *") + .bind("p1") + .to((Boolean) null) + .bind("p2") + .to((Timestamp) null) + .bind("p3") + .to("Amethyst") + .bind("p4") + .to("Jiang") + .bind("p5") + .to((Timestamp) null) + .build(), + 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("active") + .setType(Type.newBuilder().setCode(TypeCode.BOOL).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("last_name") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("full_name") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("first_name") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue( + String.valueOf(Long.reverse(INITIAL_SINGERS.size() + 2))) + .build()) + .addValues(Value.newBuilder().setBoolValue(true).build()) + .addValues(Value.newBuilder().setStringValue("Amethyst").build()) + .addValues(Value.newBuilder().setStringValue("Amethyst Jiang").build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setStringValue("Jiang").build()) + .build()) + .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) + .build())); + mockSpanner.putPartialStatementResult( + StatementResult.query( + Statement.of( + "INSERT INTO \"albums\" (\"cover_picture\", \"created_at\", \"marketing_budget\", \"release_date\", \"singer_id\", \"title\", \"updated_at\") VALUES ($1, $2, $3, $4, $5, $6, $7)\n" + + "RETURNING *"), + 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("title") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("singer_id") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("release_date") + .setType(Type.newBuilder().setCode(TypeCode.DATE).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("cover_picture") + .setType(Type.newBuilder().setCode(TypeCode.BYTES).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("marketing_budget") + .setType( + Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation(TypeAnnotationCode.PG_NUMERIC) + .build()) + .build()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue(String.valueOf(Long.reverse(1L))) + .build()) + .addValues(Value.newBuilder().setStringValue(randomTitle())) + .addValues(Value.newBuilder().setStringValue(String.valueOf(1L))) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues( + Value.newBuilder().setStringValue(randomDate().toString()).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .build()) + .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) + .build())); + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of("select * from albums limit 1"), + 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("title") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("singer_id") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("release_date") + .setType(Type.newBuilder().setCode(TypeCode.DATE).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("cover_picture") + .setType(Type.newBuilder().setCode(TypeCode.BYTES).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("marketing_budget") + .setType( + Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation(TypeAnnotationCode.PG_NUMERIC) + .build()) + .build()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue(String.valueOf(Long.reverse(1L))) + .build()) + .addValues(Value.newBuilder().setStringValue(randomTitle())) + .addValues(Value.newBuilder().setStringValue(String.valueOf(1L))) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues( + Value.newBuilder().setStringValue(randomDate().toString()).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .build()) + .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) + .build())); + mockSpanner.putPartialStatementResult( + StatementResult.query( + Statement.of( + "INSERT INTO \"tracks\" (\"created_at\", \"id\", \"sample_rate\", \"title\", \"track_number\", \"updated_at\") VALUES ($1, $2, $3, $4, $5, $6)\n" + + "RETURNING *"), + ResultSet.newBuilder() + .setMetadata( + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("id") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("sample_rate") + .setType( + Type.newBuilder().setCode(TypeCode.FLOAT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("title") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("track_number") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setStringValue("1").build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setStringValue(randomTitle()).build()) + .addValues(Value.newBuilder().setStringValue("1").build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .build()) + .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) + .build())); + for (String prefix : new String[] {"J%", "A%", "B%", "C%"}) { + mockSpanner.putStatementResult( + StatementResult.query( + Statement.newBuilder( + "SELECT \"singers\".\"id\" AS \"id\", \"singers\".\"active\" AS \"active\", " + + "\"singers\".\"last_name\" AS \"last_name\", \"singers\".\"full_name\" AS \"full_name\", " + + "\"singers\".\"updated_at\" AS \"updated_at\", \"singers\".\"created_at\" AS \"created_at\", " + + "\"singers\".\"first_name\" AS \"first_name\" " + + "FROM \"singers\" WHERE \"singers\".\"last_name\" LIKE $1") + .bind("p1") + .to(prefix) + .build(), + 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("active") + .setType(Type.newBuilder().setCode(TypeCode.BOOL).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("last_name") + .setType( + Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("full_name") + .setType( + Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("first_name") + .setType( + Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .build()) + .build()) + .addAllRows( + Streams.mapWithIndex( + INITIAL_SINGERS.stream() + .filter( + singer -> + singer.getLastName().startsWith(prefix.substring(0, 1))), + (singer, index) -> + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue( + String.valueOf(Long.reverse(index + 1))) + .build()) + .addValues(Value.newBuilder().setBoolValue(true).build()) + .addValues( + Value.newBuilder() + .setStringValue(singer.getLastName()) + .build()) + .addValues( + Value.newBuilder() + .setStringValue( + singer.getFirstName() + + " " + + singer.getLastName()) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setStringValue(singer.getFirstName()) + .build()) + .build()) + .collect(Collectors.toList())) + .build())); + } + } + + @Test + public void testRunApplication() { + System.setProperty("port", String.valueOf(getPort())); + SpringApplication.run(Application.class).close(); + + assertEquals( + 34, + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(request -> !request.getSql().equals("SELECT 1")) + .count()); + assertEquals(3, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(5, mockSpanner.countRequestsOfType(CommitRequest.class)); + } + + private static void addDdlResponseToSpannerAdmin() { + mockDatabaseAdmin.addResponse( + Operation.newBuilder() + .setDone(true) + .setResponse(Any.pack(Empty.getDefaultInstance())) + .setMetadata(Any.pack(UpdateDatabaseDdlMetadata.getDefaultInstance())) + .build()); + } +} diff --git a/samples/spring-data-jdbc/src/test/resources/application-cs.properties b/samples/spring-data-jdbc/src/test/resources/application-cs.properties new file mode 100644 index 000000000..05f7cfa92 --- /dev/null +++ b/samples/spring-data-jdbc/src/test/resources/application-cs.properties @@ -0,0 +1,9 @@ + +# This profile uses a Cloud Spanner PostgreSQL database. + +spanner.project=my-project +spanner.instance=my-instance +spanner.database=spring-data-jdbc + +spring.datasource.url=jdbc:cloudspanner://localhost:${port}/projects/${spanner.project}/instances/${spanner.instance}/databases/${spanner.database}?usePlainText=true +spring.datasource.driver-class-name=com.google.cloud.spanner.jdbc.JdbcDriver diff --git a/samples/spring-data-jdbc/src/test/resources/application-pg.properties b/samples/spring-data-jdbc/src/test/resources/application-pg.properties new file mode 100644 index 000000000..894f63eba --- /dev/null +++ b/samples/spring-data-jdbc/src/test/resources/application-pg.properties @@ -0,0 +1,7 @@ + +# This profile uses an open-source PostgreSQL database. + +spring.datasource.url=jdbc:postgresql://localhost:5432/spring-data-jdbc +spring.datasource.driver-class-name=org.postgresql.Driver +spring.datasource.username=postgres +spring.datasource.password=mysecretpassword diff --git a/samples/spring-data-jdbc/src/test/resources/application.properties b/samples/spring-data-jdbc/src/test/resources/application.properties new file mode 100644 index 000000000..3347f3137 --- /dev/null +++ b/samples/spring-data-jdbc/src/test/resources/application.properties @@ -0,0 +1,9 @@ + +# This application can use both a Cloud Spanner PostgreSQL database or an open-source PostgreSQL +# database. Which database is used is determined by the active profile: +# 1. 'cs' means use Cloud Spanner. +# 2. 'pg' means use open-source PostgreSQL. + +# Activate the Cloud Spanner profile by default. +# Change to 'pg' to activate the PostgreSQL profile. +spring.profiles.default=cs From 1ffd53b1f23d9f62fc63e0b6d4f10ca9206c272c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 14 Sep 2023 15:36:08 +0200 Subject: [PATCH 084/173] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.12.1 (#1344) --- samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index a2f7c377f..d0862d2e4 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -48,7 +48,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.12.0 + 2.12.1 org.postgresql From 90d4cc11a998942d452b92f47e30c5a1c62599d6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 15 Sep 2023 11:00:44 +0200 Subject: [PATCH 085/173] chore(deps): update dependency com.google.cloud:libraries-bom to v26.23.0 (#1346) --- samples/snippets/pom.xml | 2 +- samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 001268427..a00b7a567 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.22.0 + 26.23.0 pom import diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index d0862d2e4..ee5a44390 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.22.0 + 26.23.0 import pom From c3be4d481b20fa5113c9f8ab0cabbb95353d0f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 15 Sep 2023 13:35:56 +0200 Subject: [PATCH 086/173] chore: cleanup statement execution and test all execute methods of Statement and PreparedStatement (#1321) * test: add tests for all execute methods of Statement and PreparedStatement Adds tests for all the different variations of the execute method on Statement and PreparedStatement. This will allow us to make internal changes to the way these methods are handled, while keeping control over any behavior changes that it might introduce. * chore: share do-with-timeout code (#1324) Refactor the execute methods a bit so they all share the same do-with-timeout logic. --- .../spanner/jdbc/AbstractJdbcStatement.java | 120 ++-- .../cloud/spanner/jdbc/JdbcStatement.java | 19 +- .../spanner/jdbc/ExecuteMockServerTest.java | 568 ++++++++++++++++++ 3 files changed, 657 insertions(+), 50 deletions(-) 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 e7b1a47f4..99bee40fb 100644 --- a/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -24,12 +24,15 @@ 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; import java.sql.Statement; import java.util.Arrays; import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.function.Supplier; /** Base class for Cloud Spanner JDBC {@link Statement}s */ abstract class AbstractJdbcStatement extends AbstractJdbcWrapper implements Statement { @@ -183,21 +186,74 @@ private ResultSet executeQuery( QueryAnalyzeMode analyzeMode, QueryOption... options) throws SQLException { + Options.QueryOption[] queryOptions = getQueryOptions(options); + return doWithStatementTimeout( + () -> { + com.google.cloud.spanner.ResultSet resultSet; + if (analyzeMode == null) { + resultSet = connection.getSpannerConnection().executeQuery(statement, queryOptions); + } else { + resultSet = connection.getSpannerConnection().analyzeQuery(statement, analyzeMode); + } + return JdbcResultSet.of(this, resultSet); + }); + } + + private T doWithStatementTimeout(Supplier runnable) throws SQLException { + return doWithStatementTimeout(runnable, ignore -> Boolean.TRUE); + } + + private T doWithStatementTimeout( + Supplier runnable, Function shouldResetTimeout) throws SQLException { StatementTimeout originalTimeout = setTemporaryStatementTimeout(); + T result = null; try { - com.google.cloud.spanner.ResultSet resultSet; - if (analyzeMode == null) { - resultSet = - connection.getSpannerConnection().executeQuery(statement, getQueryOptions(options)); - } else { - resultSet = connection.getSpannerConnection().analyzeQuery(statement, analyzeMode); - } - return JdbcResultSet.of(this, resultSet); - } catch (SpannerException e) { - throw JdbcSqlExceptionFactory.of(e); + result = runnable.get(); + return result; + } catch (SpannerException spannerException) { + throw JdbcSqlExceptionFactory.of(spannerException); } finally { - resetStatementTimeout(originalTimeout); + if (shouldResetTimeout.apply(result)) { + resetStatementTimeout(originalTimeout); + } + } + } + + /** + * 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 { + return checkedCast(executeLargeUpdate(statement)); + } + + /** + * Do a checked cast from long to int. Throws a {@link SQLException} with code {@link + * Code#OUT_OF_RANGE} if the update count is too big to fit in an int. + */ + int checkedCast(long updateCount) throws SQLException { + if (updateCount > Integer.MAX_VALUE) { + throw JdbcSqlExceptionFactory.of( + "update count too large for executeUpdate: " + updateCount, Code.OUT_OF_RANGE); } + return (int) updateCount; + } + + /** + * 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 { + return doWithStatementTimeout(() -> connection.getSpannerConnection().executeUpdate(statement)); } /** @@ -210,24 +266,16 @@ private ResultSet executeQuery( * @throws SQLException if a database error occurs. */ StatementResult execute(com.google.cloud.spanner.Statement statement) throws SQLException { - StatementTimeout originalTimeout = setTemporaryStatementTimeout(); - boolean mustResetTimeout = false; - try { - StatementResult result = connection.getSpannerConnection().execute(statement); - mustResetTimeout = !resultIsSetStatementTimeout(result); - if (mustResetTimeout && resultIsShowStatementTimeout(result)) { - // it was a 'SHOW STATEMENT_TIMEOUT statement, we need to re-run to get the correct value - mustResetTimeout = false; - result = rerunShowStatementTimeout(statement, originalTimeout); - } - return result; - } catch (SpannerException e) { - throw JdbcSqlExceptionFactory.of(e); - } finally { - if (mustResetTimeout) { - resetStatementTimeout(originalTimeout); - } + StatementResult statementResult = + doWithStatementTimeout( + () -> connection.getSpannerConnection().execute(statement), + result -> !resultIsSetStatementTimeout(result)); + if (resultIsShowStatementTimeout(statementResult)) { + // We can safely re-run it without first resetting the timeout to the original value, as that + // has already been done by the 'doWithStatementTimeout' function. + return rerunShowStatementTimeout(statement); } + return statementResult; } /** @@ -250,18 +298,22 @@ StatementResult execute(com.google.cloud.spanner.Statement statement) throws SQL * executed was a SET STATEMENT_TIMEOUT statement. */ private boolean resultIsSetStatementTimeout(StatementResult result) { - return result.getClientSideStatementType() == ClientSideStatementType.SET_STATEMENT_TIMEOUT; + return result != null + && result.getClientSideStatementType() == ClientSideStatementType.SET_STATEMENT_TIMEOUT; } private boolean resultIsShowStatementTimeout(StatementResult result) { - return result.getClientSideStatementType() == ClientSideStatementType.SHOW_STATEMENT_TIMEOUT; + return result != null + && result.getClientSideStatementType() == ClientSideStatementType.SHOW_STATEMENT_TIMEOUT; } - private StatementResult rerunShowStatementTimeout( - com.google.cloud.spanner.Statement statement, StatementTimeout originalTimeout) + private StatementResult rerunShowStatementTimeout(com.google.cloud.spanner.Statement statement) throws SQLException { - resetStatementTimeout(originalTimeout); - return connection.getSpannerConnection().execute(statement); + try { + return connection.getSpannerConnection().execute(statement); + } catch (SpannerException spannerException) { + throw JdbcSqlExceptionFactory.of(spannerException); + } } @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 6c6a45a15..fcc09596c 100644 --- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -79,11 +79,7 @@ public int executeUpdate(String sql) throws SQLException { 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); - } - return (int) result; + return checkedCast(executeLargeUpdate(sql, generatedKeysColumns)); } /** @@ -300,11 +296,7 @@ public ResultSet getResultSet() throws SQLException { @Override public int getUpdateCount() throws SQLException { checkClosed(); - if (currentUpdateCount > Integer.MAX_VALUE) { - throw JdbcSqlExceptionFactory.of( - "update count too large: " + currentUpdateCount, Code.OUT_OF_RANGE); - } - return (int) currentUpdateCount; + return checkedCast(currentUpdateCount); } /** @@ -481,12 +473,7 @@ private long[] executeBatch(boolean large) throws SQLException { int[] convertUpdateCounts(long[] updateCounts) throws SQLException { int[] res = new int[updateCounts.length]; for (int index = 0; index < updateCounts.length; index++) { - if (updateCounts[index] > Integer.MAX_VALUE) { - throw JdbcSqlExceptionFactory.of( - String.format("Update count too large for int: %d", updateCounts[index]), - Code.OUT_OF_RANGE); - } - res[index] = (int) updateCounts[index]; + res[index] = checkedCast(updateCounts[index]); } return res; } diff --git a/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java b/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java index f74de6631..b62449eb5 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java @@ -17,6 +17,9 @@ 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.assertNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; @@ -24,18 +27,28 @@ import com.google.cloud.spanner.SessionPoolOptions; import com.google.cloud.spanner.connection.AbstractMockServerTest; import com.google.cloud.spanner.connection.ConnectionOptions; +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.rpc.Code; +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.Statement; import org.junit.Before; import org.junit.Test; +import org.junit.function.ThrowingRunnable; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -46,6 +59,14 @@ @RunWith(JUnit4.class) public class ExecuteMockServerTest extends AbstractMockServerTest { private static final String QUERY = "select * from my_table"; + private static final String DML = "insert into my_table (id, value) values (1, 'One')"; + private static final String DML_THEN_RETURN_ID = DML + "\nTHEN RETURN `id`"; + private static final String LARGE_DML = "update my_table set value='new value' where true"; + private static final String LARGE_DML_THEN_RETURN_ID = LARGE_DML + "\nTHEN RETURN `id`"; + private static final String DML_RETURNING = + "insert into my_table (id, value) values (1, 'One') THEN RETURN *"; + private static final String DDL = "create table my_table"; + private static final long LARGE_UPDATE_COUNT = 2L * Integer.MAX_VALUE; @Before public void setupResults() { @@ -74,8 +95,58 @@ public void setupResults() { .addValues(Value.newBuilder().setStringValue("One").build()) .build()) .build(); + com.google.spanner.v1.ResultSet returnIdResultSet = + 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()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("1").build()) + .build()) + .build(); mockSpanner.putStatementResult( StatementResult.query(com.google.cloud.spanner.Statement.of(QUERY), resultSet)); + mockSpanner.putStatementResult( + StatementResult.update(com.google.cloud.spanner.Statement.of(DML), 1L)); + mockSpanner.putStatementResult( + StatementResult.update( + com.google.cloud.spanner.Statement.of(LARGE_DML), LARGE_UPDATE_COUNT)); + mockSpanner.putStatementResult( + StatementResult.query( + com.google.cloud.spanner.Statement.of(DML_RETURNING), + resultSet + .toBuilder() + .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) + .build())); + mockSpanner.putStatementResult( + StatementResult.query( + com.google.cloud.spanner.Statement.of(DML_THEN_RETURN_ID), + returnIdResultSet + .toBuilder() + .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) + .build())); + mockSpanner.putStatementResult( + StatementResult.query( + com.google.cloud.spanner.Statement.of(LARGE_DML_THEN_RETURN_ID), + returnIdResultSet + .toBuilder() + .setStats(ResultSetStats.newBuilder().setRowCountExact(LARGE_UPDATE_COUNT).build()) + .build())); + mockDatabaseAdmin.addResponse( + Operation.newBuilder() + .setDone(true) + .setResponse(Any.pack(Empty.getDefaultInstance())) + .setMetadata(Any.pack(UpdateDatabaseDdlMetadata.getDefaultInstance())) + .build()); } private String createUrl() { @@ -84,6 +155,503 @@ private String createUrl() { getPort(), "proj", "inst", "db"); } + private Connection createConnection() throws SQLException { + return DriverManager.getConnection(createUrl()); + } + + @Test + public void testStatementExecuteQuery() throws SQLException { + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + try (ResultSet resultSet = statement.executeQuery(QUERY)) { + verifyResultSet(resultSet); + } + try (ResultSet resultSet = statement.executeQuery(DML_RETURNING)) { + verifyResultSet(resultSet); + } + verifyException(() -> statement.executeQuery(DML)); + verifyException(() -> statement.executeQuery(LARGE_DML)); + verifyException(() -> statement.executeQuery(DDL)); + } + } + + @Test + public void testStatementExecuteUpdate() throws SQLException { + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + assertEquals(1, statement.executeUpdate(DML)); + assertEquals(0, statement.executeUpdate(DDL)); + verifyOverflow(() -> statement.executeUpdate(LARGE_DML)); + verifyException(() -> statement.executeUpdate(QUERY)); + verifyException(() -> statement.executeUpdate(DML_RETURNING)); + } + } + + @Test + public void testStatementExecuteUpdateReturnGeneratedKeys() throws SQLException { + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. + assertEquals(1, statement.executeUpdate(DML, Statement.NO_GENERATED_KEYS)); + assertEquals(0, statement.executeUpdate(DDL, Statement.NO_GENERATED_KEYS)); + verifyOverflow(() -> statement.executeUpdate(LARGE_DML, Statement.NO_GENERATED_KEYS)); + verifyException(() -> statement.executeUpdate(QUERY, Statement.NO_GENERATED_KEYS)); + verifyException(() -> statement.executeUpdate(DML_RETURNING, Statement.NO_GENERATED_KEYS)); + } + } + + @Test + public void testStatementExecuteUpdateReturnColumnNames() throws SQLException { + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + assertEquals(1, statement.executeUpdate(DML, new String[] {"id"})); + assertEquals(0, statement.executeUpdate(DDL, new String[] {"id"})); + verifyOverflow(() -> statement.executeUpdate(LARGE_DML, new String[] {"id"})); + verifyException( + () -> statement.executeUpdate(QUERY, new String[] {"id"}), Code.FAILED_PRECONDITION); + assertEquals(1, statement.executeUpdate(DML_RETURNING, new String[] {"id"})); + } + } + + @Test + public void testStatementExecuteUpdateReturnColumnIndexes() throws SQLException { + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + assertEquals(1, statement.executeUpdate(DML, new int[] {1})); + assertEquals(0, statement.executeUpdate(DDL, new int[] {1})); + verifyOverflow(() -> statement.executeUpdate(LARGE_DML, new int[] {1})); + verifyException(() -> statement.executeUpdate(QUERY, new int[] {1})); + verifyException(() -> statement.executeUpdate(DML_RETURNING, new int[] {1})); + } + } + + @Test + public void testStatementLargeExecuteUpdate() throws SQLException { + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + assertEquals(1L, statement.executeLargeUpdate(DML)); + assertEquals(0L, statement.executeLargeUpdate(DDL)); + assertEquals(LARGE_UPDATE_COUNT, statement.executeLargeUpdate(LARGE_DML)); + verifyException(() -> statement.executeLargeUpdate(QUERY)); + verifyException(() -> statement.executeLargeUpdate(DML_RETURNING)); + } + } + + @Test + public void testStatementExecuteLargeUpdateReturnGeneratedKeys() throws SQLException { + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. + assertEquals(1, statement.executeLargeUpdate(DML, Statement.NO_GENERATED_KEYS)); + assertEquals(0, statement.executeLargeUpdate(DDL, Statement.NO_GENERATED_KEYS)); + assertEquals( + LARGE_UPDATE_COUNT, statement.executeLargeUpdate(LARGE_DML, Statement.NO_GENERATED_KEYS)); + verifyException(() -> statement.executeLargeUpdate(QUERY, Statement.NO_GENERATED_KEYS)); + verifyException( + () -> statement.executeLargeUpdate(DML_RETURNING, Statement.NO_GENERATED_KEYS)); + } + } + + @Test + public void testStatementExecuteLargeUpdateReturnColumnNames() throws SQLException { + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + assertEquals(1, statement.executeLargeUpdate(DML, new String[] {"id"})); + assertEquals(0, statement.executeLargeUpdate(DDL, new String[] {"id"})); + assertEquals( + LARGE_UPDATE_COUNT, statement.executeLargeUpdate(LARGE_DML, new String[] {"id"})); + verifyException( + () -> statement.executeLargeUpdate(QUERY, new String[] {"id"}), Code.FAILED_PRECONDITION); + assertEquals(1L, statement.executeLargeUpdate(DML_RETURNING, new String[] {"id"})); + } + } + + @Test + public void testStatementExecuteLargeUpdateReturnColumnIndexes() throws SQLException { + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + assertEquals(1, statement.executeLargeUpdate(DML, new int[] {1})); + assertEquals(0, statement.executeLargeUpdate(DDL, new int[] {1})); + assertEquals(LARGE_UPDATE_COUNT, statement.executeLargeUpdate(LARGE_DML, new int[] {1})); + verifyException(() -> statement.executeLargeUpdate(QUERY, new int[] {1})); + verifyException(() -> statement.executeLargeUpdate(DML_RETURNING, new int[] {1})); + } + } + + @Test + public void testStatementExecute() throws SQLException { + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + verifyUpdateCount(statement, () -> statement.execute(DML), 1L); + verifyUpdateCount(statement, () -> statement.execute(LARGE_DML), LARGE_UPDATE_COUNT); + verifyUpdateCount(statement, () -> statement.execute(DDL), Statement.SUCCESS_NO_INFO); + verifyResultSet(statement, () -> statement.execute(QUERY)); + verifyResultSet(statement, () -> statement.execute(DML_RETURNING)); + } + } + + @Test + public void testStatementExecuteReturnGeneratedKeys() throws SQLException { + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. + verifyUpdateCount(statement, () -> statement.execute(DML, Statement.NO_GENERATED_KEYS), 1L); + verifyUpdateCount( + statement, + () -> statement.execute(LARGE_DML, Statement.NO_GENERATED_KEYS), + LARGE_UPDATE_COUNT); + verifyUpdateCount( + statement, + () -> statement.execute(DDL, Statement.NO_GENERATED_KEYS), + Statement.SUCCESS_NO_INFO); + verifyResultSet(statement, () -> statement.execute(QUERY, Statement.NO_GENERATED_KEYS)); + verifyResultSet( + statement, () -> statement.execute(DML_RETURNING, Statement.NO_GENERATED_KEYS)); + } + } + + @Test + public void testStatementExecuteReturnColumnNames() throws SQLException { + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + verifyUpdateCount(statement, () -> statement.execute(DML, new String[] {"id"}), 1L); + verifyUpdateCount( + statement, () -> statement.execute(LARGE_DML, new String[] {"id"}), LARGE_UPDATE_COUNT); + verifyUpdateCount( + statement, () -> statement.execute(DDL, new String[] {"id"}), Statement.SUCCESS_NO_INFO); + verifyResultSet(statement, () -> statement.execute(QUERY, new String[] {"id"})); + verifyResultSet(statement, () -> statement.execute(DML_RETURNING, new String[] {"id"})); + } + } + + @Test + public void testStatementExecuteReturnColumnIndexes() throws SQLException { + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + verifyUpdateCount(statement, () -> statement.execute(DML, new int[] {1}), 1L); + verifyUpdateCount( + statement, () -> statement.execute(LARGE_DML, new int[] {1}), LARGE_UPDATE_COUNT); + verifyUpdateCount( + statement, () -> statement.execute(DDL, new int[] {1}), Statement.SUCCESS_NO_INFO); + verifyResultSet(statement, () -> statement.execute(QUERY, new int[] {1})); + verifyResultSet(statement, () -> statement.execute(DML_RETURNING, new int[] {1})); + } + } + + @Test + public void testPreparedStatementExecuteQuery() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet resultSet = connection.prepareStatement(QUERY).executeQuery()) { + verifyResultSet(resultSet); + } + try (ResultSet resultSet = connection.prepareStatement(DML_RETURNING).executeQuery()) { + verifyResultSet(resultSet); + } + verifyException(() -> connection.prepareStatement(DML).executeQuery()); + verifyException(() -> connection.prepareStatement(LARGE_DML).executeQuery()); + verifyException(() -> connection.prepareStatement(DDL).executeQuery()); + } + } + + @Test + public void testPreparedStatementExecuteUpdate() throws SQLException { + try (Connection connection = createConnection()) { + assertEquals(1, connection.prepareStatement(DML).executeUpdate()); + // TODO: Enable the next statement once PreparedStatement supports executing DDL through the + // executeUpdate() method. + // assertEquals(0, connection.prepareStatement(DDL).executeUpdate()); + verifyOverflow(() -> connection.prepareStatement(LARGE_DML).executeUpdate()); + verifyException(() -> connection.prepareStatement(QUERY).executeUpdate()); + verifyException( + () -> connection.prepareStatement(DML_RETURNING).executeUpdate(), Code.INVALID_ARGUMENT); + } + } + + @Test + public void testPreparedStatementExecuteUpdateReturnGeneratedKeys() throws SQLException { + try (Connection connection = createConnection()) { + // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. + assertEquals( + 1, connection.prepareStatement(DML, Statement.NO_GENERATED_KEYS).executeUpdate()); + // TODO: Enable the next statement once PreparedStatement supports executing DDL through the + // executeUpdate() method. + // assertEquals(0, connection.prepareStatement(DDL, + // Statement.NO_GENERATED_KEYS).executeUpdate()); + verifyOverflow( + () -> + connection.prepareStatement(LARGE_DML, Statement.NO_GENERATED_KEYS).executeUpdate()); + verifyException( + () -> connection.prepareStatement(QUERY, Statement.NO_GENERATED_KEYS).executeUpdate()); + verifyException( + () -> + connection + .prepareStatement(DML_RETURNING, Statement.NO_GENERATED_KEYS) + .executeUpdate(), + Code.INVALID_ARGUMENT); + } + } + + @Test + public void testPreparedStatementExecuteUpdateReturnColumnNames() throws SQLException { + try (Connection connection = createConnection()) { + assertEquals(1, connection.prepareStatement(DML, new String[] {"id"}).executeUpdate()); + // TODO: Enable the next statement once PreparedStatement supports executing DDL through the + // executeUpdate() method. + // assertEquals(0, connection.prepareStatement(DDL, new String[] {"id"}).executeUpdate()); + verifyOverflow( + () -> connection.prepareStatement(LARGE_DML, new String[] {"id"}).executeUpdate()); + verifyException( + () -> connection.prepareStatement(QUERY, new String[] {"id"}).executeUpdate(), + Code.FAILED_PRECONDITION); + assertEquals( + 1, connection.prepareStatement(DML_RETURNING, new String[] {"id"}).executeUpdate()); + } + } + + @Test + public void testPreparedStatementExecuteUpdateReturnColumnIndexes() throws SQLException { + try (Connection connection = createConnection()) { + assertEquals(1, connection.prepareStatement(DML, new int[] {1}).executeUpdate()); + // TODO: Enable the next statement once PreparedStatement supports executing DDL through the + // executeUpdate() method. + // assertEquals(0, connection.prepareStatement(DDL, new int[] {1}).executeUpdate()); + verifyOverflow(() -> connection.prepareStatement(LARGE_DML, new int[] {1}).executeUpdate()); + verifyException(() -> connection.prepareStatement(QUERY, new int[] {1}).executeUpdate()); + verifyException( + () -> connection.prepareStatement(DML_RETURNING, new int[] {1}).executeUpdate(), + Code.INVALID_ARGUMENT); + } + } + + @Test + public void testPreparedStatementLargeExecuteUpdate() throws SQLException { + try (Connection connection = createConnection()) { + assertEquals(1L, connection.prepareStatement(DML).executeLargeUpdate()); + // TODO: Enable the next statement once PreparedStatement supports executing DDL through the + // executeUpdate() method. + // assertEquals(0L, connection.prepareStatement(DDL).executeLargeUpdate()); + assertEquals(LARGE_UPDATE_COUNT, connection.prepareStatement(LARGE_DML).executeLargeUpdate()); + verifyException(() -> connection.prepareStatement(QUERY).executeLargeUpdate()); + verifyException( + () -> connection.prepareStatement(DML_RETURNING).executeLargeUpdate(), + Code.INVALID_ARGUMENT); + } + } + + @Test + public void testPreparedStatementExecuteLargeUpdateReturnGeneratedKeys() throws SQLException { + try (Connection connection = createConnection()) { + // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. + assertEquals( + 1, connection.prepareStatement(DML, Statement.NO_GENERATED_KEYS).executeLargeUpdate()); + // TODO: Enable the next statement once PreparedStatement supports executing DDL through the + // executeUpdate() method. + // assertEquals(0, connection.prepareStatement(DDL, + // Statement.NO_GENERATED_KEYS).executeLargeUpdate()); + assertEquals( + LARGE_UPDATE_COUNT, + connection.prepareStatement(LARGE_DML, Statement.NO_GENERATED_KEYS).executeLargeUpdate()); + verifyException( + () -> + connection.prepareStatement(QUERY, Statement.NO_GENERATED_KEYS).executeLargeUpdate()); + verifyException( + () -> + connection + .prepareStatement(DML_RETURNING, Statement.NO_GENERATED_KEYS) + .executeLargeUpdate(), + Code.INVALID_ARGUMENT); + } + } + + @Test + public void testPreparedStatementExecuteLargeUpdateReturnColumnNames() throws SQLException { + try (Connection connection = createConnection()) { + assertEquals(1, connection.prepareStatement(DML, new String[] {"id"}).executeLargeUpdate()); + // TODO: Enable the next statement once PreparedStatement supports executing DDL through the + // executeUpdate() method. + // assertEquals(0, connection.prepareStatement(DDL, new String[] + // {"id"}).executeLargeUpdate()); + assertEquals( + LARGE_UPDATE_COUNT, + connection.prepareStatement(LARGE_DML, new String[] {"id"}).executeLargeUpdate()); + verifyException( + () -> connection.prepareStatement(QUERY, new String[] {"id"}).executeLargeUpdate(), + Code.FAILED_PRECONDITION); + assertEquals( + 1L, connection.prepareStatement(DML_RETURNING, new String[] {"id"}).executeLargeUpdate()); + } + } + + @Test + public void testPreparedStatementExecuteLargeUpdateReturnColumnIndexes() throws SQLException { + try (Connection connection = createConnection()) { + assertEquals(1, connection.prepareStatement(DML, new int[] {1}).executeLargeUpdate()); + // TODO: Enable the next statement once PreparedStatement supports executing DDL through the + // executeUpdate() method. + // assertEquals(0, connection.prepareStatement(DDL, new int[] {1}).executeLargeUpdate()); + assertEquals( + LARGE_UPDATE_COUNT, + connection.prepareStatement(LARGE_DML, new int[] {1}).executeLargeUpdate()); + verifyException(() -> connection.prepareStatement(QUERY, new int[] {1}).executeLargeUpdate()); + verifyException( + () -> connection.prepareStatement(DML_RETURNING, new int[] {1}).executeLargeUpdate(), + Code.INVALID_ARGUMENT); + } + } + + @Test + public void testPreparedStatementExecute() throws SQLException { + try (Connection connection = createConnection()) { + verifyPreparedUpdateCount(connection.prepareStatement(DML), PreparedStatement::execute, 1L); + verifyPreparedUpdateCount( + connection.prepareStatement(LARGE_DML), PreparedStatement::execute, LARGE_UPDATE_COUNT); + verifyPreparedUpdateCount( + connection.prepareStatement(DDL), PreparedStatement::execute, Statement.SUCCESS_NO_INFO); + verifyPreparedResultSet(connection.prepareStatement(QUERY), PreparedStatement::execute); + verifyPreparedResultSet( + connection.prepareStatement(DML_RETURNING), PreparedStatement::execute); + } + } + + @Test + public void testPreparedStatementExecuteReturnGeneratedKeys() throws SQLException { + try (Connection connection = createConnection()) { + // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. + verifyPreparedUpdateCount( + connection.prepareStatement(DML, Statement.NO_GENERATED_KEYS), + PreparedStatement::execute, + 1L); + verifyPreparedUpdateCount( + connection.prepareStatement(LARGE_DML, Statement.NO_GENERATED_KEYS), + PreparedStatement::execute, + LARGE_UPDATE_COUNT); + verifyPreparedUpdateCount( + connection.prepareStatement(DDL, Statement.NO_GENERATED_KEYS), + PreparedStatement::execute, + Statement.SUCCESS_NO_INFO); + verifyPreparedResultSet( + connection.prepareStatement(QUERY, Statement.NO_GENERATED_KEYS), + PreparedStatement::execute); + verifyPreparedResultSet( + connection.prepareStatement(DML_RETURNING, Statement.NO_GENERATED_KEYS), + PreparedStatement::execute); + } + } + + @Test + public void testPreparedStatementExecuteReturnColumnNames() throws SQLException { + try (Connection connection = createConnection()) { + verifyPreparedUpdateCount( + connection.prepareStatement(DML, new String[] {"id"}), PreparedStatement::execute, 1L); + verifyPreparedUpdateCount( + connection.prepareStatement(LARGE_DML, new String[] {"id"}), + PreparedStatement::execute, + LARGE_UPDATE_COUNT); + verifyPreparedUpdateCount( + connection.prepareStatement(DDL, new String[] {"id"}), + PreparedStatement::execute, + Statement.SUCCESS_NO_INFO); + verifyPreparedResultSet( + connection.prepareStatement(QUERY, new String[] {"id"}), PreparedStatement::execute); + verifyPreparedResultSet( + connection.prepareStatement(DML_RETURNING, new String[] {"id"}), + PreparedStatement::execute); + } + } + + @Test + public void testPreparedStatementExecuteReturnColumnIndexes() throws SQLException { + try (Connection connection = createConnection()) { + verifyPreparedUpdateCount( + connection.prepareStatement(DML, new int[] {1}), PreparedStatement::execute, 1L); + verifyPreparedUpdateCount( + connection.prepareStatement(LARGE_DML, new int[] {1}), + PreparedStatement::execute, + LARGE_UPDATE_COUNT); + verifyPreparedUpdateCount( + connection.prepareStatement(DDL, new int[] {1}), + PreparedStatement::execute, + Statement.SUCCESS_NO_INFO); + verifyPreparedResultSet( + connection.prepareStatement(QUERY, new int[] {1}), PreparedStatement::execute); + verifyPreparedResultSet( + connection.prepareStatement(DML_RETURNING, new int[] {1}), PreparedStatement::execute); + } + } + + private void verifyResultSet(ResultSet resultSet) throws SQLException { + assertNotNull(resultSet.getMetaData()); + assertEquals(2, resultSet.getMetaData().getColumnCount()); + assertTrue(resultSet.next()); + assertFalse(resultSet.next()); + } + + private void verifyException(ThrowingRunnable runnable) { + verifyException(runnable, Code.INVALID_ARGUMENT); + } + + private void verifyOverflow(ThrowingRunnable runnable) { + verifyException(runnable, Code.OUT_OF_RANGE); + } + + private void verifyException(ThrowingRunnable runnable, Code code) { + SQLException exception = assertThrows(SQLException.class, runnable); + assertTrue(exception instanceof JdbcSqlException); + JdbcSqlException sqlException = (JdbcSqlException) exception; + assertEquals(code, sqlException.getCode()); + } + + interface ThrowingFunction { + T apply() throws SQLException; + } + + interface ThrowingPreparedFunction { + T apply(PreparedStatement statement) throws SQLException; + } + + private void verifyPreparedUpdateCount( + PreparedStatement statement, ThrowingPreparedFunction function, long updateCount) + throws SQLException { + verifyUpdateCount(statement, () -> function.apply(statement), updateCount); + } + + private void verifyUpdateCount( + Statement statement, ThrowingFunction function, long updateCount) + throws SQLException { + assertFalse(function.apply()); + if (updateCount > Integer.MAX_VALUE) { + verifyOverflow(statement::getUpdateCount); + } else { + assertEquals((int) updateCount, statement.getUpdateCount()); + } + assertEquals(updateCount, statement.getLargeUpdateCount()); + assertNull(statement.getResultSet()); + assertFalse(statement.getMoreResults()); + assertEquals(-1, statement.getUpdateCount()); + assertEquals(-1L, statement.getLargeUpdateCount()); + } + + private void verifyPreparedResultSet( + PreparedStatement statement, ThrowingPreparedFunction function) throws SQLException { + verifyResultSet(statement, () -> function.apply(statement)); + } + + private void verifyResultSet(Statement statement, ThrowingFunction function) + throws SQLException { + assertTrue(function.apply()); + assertEquals(-1, statement.getUpdateCount()); + assertEquals(-1L, statement.getLargeUpdateCount()); + assertNotNull(statement.getResultSet()); + try (ResultSet resultSet = statement.getResultSet()) { + assertTrue(resultSet.next()); + assertFalse(resultSet.next()); + } + + assertFalse(statement.getMoreResults()); + assertEquals(-1, statement.getUpdateCount()); + assertEquals(-1L, statement.getLargeUpdateCount()); + } + @Test public void testInvalidExecuteUpdate_shouldNotLeakSession() throws SQLException { int maxSessions = 1; From c50da41e688ff48f8967c0f114f5bac8eaac49f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 15 Sep 2023 14:58:14 +0200 Subject: [PATCH 087/173] feat: support partitioned queries (#1300) Adds support for partitioned queries to the JDBC driver. Partitioned queries can be executed either using SQL statements or specific Cloud Spanner methods that are exposed by the specific Cloud Spanner JDBC interfaces. --- clirr-ignored-differences.xml | 42 ++ .../spanner/jdbc/AbstractJdbcStatement.java | 19 + .../jdbc/CloudSpannerJdbcConnection.java | 71 ++- ...dSpannerJdbcPartitionedQueryResultSet.java | 33 ++ .../CloudSpannerJdbcPreparedStatement.java | 61 +++ .../jdbc/CloudSpannerJdbcStatement.java | 60 +++ .../cloud/spanner/jdbc/JdbcConnection.java | 69 +++ .../jdbc/JdbcPartitionedQueryResultSet.java | 51 ++ .../spanner/jdbc/JdbcPreparedStatement.java | 37 +- .../cloud/spanner/jdbc/JdbcResultSet.java | 13 +- .../cloud/spanner/jdbc/JdbcStatement.java | 29 +- .../jdbc/PartitionedQueryMockServerTest.java | 486 ++++++++++++++++++ 12 files changed, 964 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPartitionedQueryResultSet.java create mode 100644 src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPreparedStatement.java create mode 100644 src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcStatement.java create mode 100644 src/main/java/com/google/cloud/spanner/jdbc/JdbcPartitionedQueryResultSet.java create mode 100644 src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java diff --git a/clirr-ignored-differences.xml b/clirr-ignored-differences.xml index a92ad5305..acf11c587 100644 --- a/clirr-ignored-differences.xml +++ b/clirr-ignored-differences.xml @@ -16,4 +16,46 @@ com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection void setSavepointSupport(com.google.cloud.spanner.connection.SavepointSupport) + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + int getMaxPartitionedParallelism() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + int getMaxPartitions() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + boolean isAutoPartitionMode() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + boolean isDataBoostEnabled() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setAutoPartitionMode(boolean) + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setDataBoostEnabled(boolean) + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setMaxPartitionedParallelism(int) + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setMaxPartitions(int) + + 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 99bee40fb..97131724d 100644 --- a/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -120,6 +120,25 @@ private StatementTimeout(long timeout, TimeUnit unit) { } } + /** Functional interface that throws {@link SQLException}. */ + interface JdbcFunction { + R apply(T t) throws SQLException; + } + + /** Runs the given function with the timeout that has been set on this statement. */ + protected T runWithStatementTimeout(JdbcFunction function) + throws SQLException { + checkClosed(); + StatementTimeout originalTimeout = setTemporaryStatementTimeout(); + try { + return function.apply(getConnection().getSpannerConnection()); + } catch (SpannerException spannerException) { + throw JdbcSqlExceptionFactory.of(spannerException); + } finally { + resetStatementTimeout(originalTimeout); + } + } + /** * Sets the statement timeout of the Spanner {@link Connection} to the query timeout of this JDBC * {@link Statement} and returns the original timeout of the Spanner {@link Connection} so it can 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 cf368f618..c161ee50a 100644 --- a/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java @@ -22,12 +22,14 @@ import com.google.cloud.spanner.CommitStats; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.PartitionOptions; import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.connection.AutocommitDmlMode; import com.google.cloud.spanner.connection.SavepointSupport; import com.google.cloud.spanner.connection.TransactionMode; import java.sql.Connection; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.Iterator; @@ -334,6 +336,73 @@ default Dialect getDialect() { return Dialect.GOOGLE_STANDARD_SQL; } + /** + * Enable data boost for partitioned queries. See also {@link + * CloudSpannerJdbcStatement#partitionQuery(String, PartitionOptions, QueryOption...)} and {@link + * CloudSpannerJdbcPreparedStatement#partitionQuery(PartitionOptions, QueryOption...)}. + */ + default void setDataBoostEnabled(boolean dataBoostEnabled) throws SQLException { + throw new UnsupportedOperationException(); + } + + /** + * Returns whether data boost is enabled for partitioned queries. See also {@link + * CloudSpannerJdbcStatement#partitionQuery(String, PartitionOptions, QueryOption...)} and {@link + * CloudSpannerJdbcPreparedStatement#partitionQuery(PartitionOptions, QueryOption...)}. + */ + default boolean isDataBoostEnabled() throws SQLException { + throw new UnsupportedOperationException(); + } + + /** + * Sets whether this connection should always use partitioned queries when a query is executed on + * this connection. Setting this flag to true and then executing a query that cannot + * be partitioned, or executing a query in a read/write transaction, will cause an error. Use this + * flag in combination with {@link #setDataBoostEnabled(boolean)} to force all queries on this + * connection to use data boost. + */ + default void setAutoPartitionMode(boolean alwaysUsePartitionedQueries) throws SQLException { + throw new UnsupportedOperationException(); + } + + /** Returns whether this connection will execute all queries as partitioned queries. */ + default boolean isAutoPartitionMode() throws SQLException { + throw new UnsupportedOperationException(); + } + + /** + * Sets the maximum number of partitions that should be included as a hint to Cloud Spanner when + * partitioning a query on this connection. Note that this is only a hint and Cloud Spanner might + * choose to ignore the hint. + */ + default void setMaxPartitions(int maxPartitions) throws SQLException { + throw new UnsupportedOperationException(); + } + + /** + * Gets the maximum number of partitions that should be included as a hint to Cloud Spanner when + * partitioning a query on this connection. Note that this is only a hint and Cloud Spanner might + * choose to ignore the hint. + */ + default int getMaxPartitions() throws SQLException { + throw new UnsupportedOperationException(); + } + + /** + * Sets the maximum degree of parallelism that is used when executing a partitioned query. A + * partitioned query will use up to maxThreads to execute and retrieve the results + * from Cloud Spanner. Set this value to 0> to use the number of available processors + * as returned by {@link Runtime#availableProcessors()}. + */ + default void setMaxPartitionedParallelism(int maxThreads) throws SQLException { + throw new UnsupportedOperationException(); + } + + /** Returns the maximum degree of parallelism that is used for partitioned queries. */ + default int getMaxPartitionedParallelism() throws SQLException { + throw new UnsupportedOperationException(); + } + /** * @see * com.google.cloud.spanner.connection.Connection#addTransactionRetryListener(com.google.cloud.spanner.connection.TransactionRetryListener) diff --git a/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPartitionedQueryResultSet.java b/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPartitionedQueryResultSet.java new file mode 100644 index 000000000..3b6118fba --- /dev/null +++ b/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPartitionedQueryResultSet.java @@ -0,0 +1,33 @@ +/* + * 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 com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.PartitionOptions; +import java.sql.ResultSet; + +/** + * Result set that is returned for partitioned queries, e.g. for 'run partitioned query select ...' + * or for {@link CloudSpannerJdbcPreparedStatement#runPartitionedQuery(PartitionOptions, + * QueryOption...)}. + */ +public interface CloudSpannerJdbcPartitionedQueryResultSet extends ResultSet { + /** Returns the number of partitions that this result set contains. */ + int getNumPartitions(); + + /** Returns the degree of parallelism that this result set uses. */ + int getParallelism(); +} diff --git a/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPreparedStatement.java b/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPreparedStatement.java new file mode 100644 index 000000000..8e72d9556 --- /dev/null +++ b/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPreparedStatement.java @@ -0,0 +1,61 @@ +/* + * 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 com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.PartitionOptions; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * This interface is implemented by {@link PreparedStatement}s that are created on Cloud Spanner + * JDBC connections. + */ +public interface CloudSpannerJdbcPreparedStatement extends PreparedStatement { + + /** + * Partitions this query, so it can be executed in parallel. This method returns a {@link + * ResultSet} with a string-representation of the partitions that were created. These strings can + * be used to execute a partition either on this connection or an any other connection (on this + * host or an any other host) by calling the method {@link #runPartition()}. This method will + * automatically enable data boost for the query if {@link + * CloudSpannerJdbcConnection#isDataBoostEnabled()} returns true. + */ + ResultSet partitionQuery(PartitionOptions partitionOptions, QueryOption... options) + throws SQLException; + + /** + * Executes the given partition of a query. The partition that should be executed must be set as a + * string parameter on this {@link PreparedStatement} using {@link #setString(int, String)}. The + * value should be a string that was returned by {@link #partitionQuery(PartitionOptions, + * QueryOption...)}. + */ + ResultSet runPartition() throws SQLException; + + /** + * Executes the given query as a partitioned query. The query will first be partitioned using the + * {@link #partitionQuery(PartitionOptions, QueryOption...)} method. Each of the partitions will + * then be executed in the background, and the results will be merged into a single result set. + * + *

This method will use {@link CloudSpannerJdbcConnection#getMaxPartitionedParallelism()} + * threads to execute the partitioned query. Set this variable to a higher/lower value to + * increase/decrease the degree of parallelism used for execution. + */ + CloudSpannerJdbcPartitionedQueryResultSet runPartitionedQuery( + PartitionOptions partitionOptions, QueryOption... options) throws SQLException; +} diff --git a/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcStatement.java b/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcStatement.java new file mode 100644 index 000000000..6115c0b23 --- /dev/null +++ b/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcStatement.java @@ -0,0 +1,60 @@ +/* + * 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 com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.PartitionOptions; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * This interface is implemented by {@link Statement}s that are created on Cloud Spanner JDBC + * connections. + */ +public interface CloudSpannerJdbcStatement extends Statement { + + /** + * Partitions the given query, so it can be executed in parallel. This method returns a {@link + * ResultSet} with a string-representation of the partitions that were created. These strings can + * be used to execute a partition either on this connection or an any other connection (on this + * host or an any other host) by calling the method {@link #runPartition(String)}. This method + * will automatically enable data boost for the query if {@link + * CloudSpannerJdbcConnection#isDataBoostEnabled()} returns true. + */ + ResultSet partitionQuery(String query, PartitionOptions partitionOptions, QueryOption... options) + throws SQLException; + + /** + * Executes the given partition of a query. The encodedPartitionId should be a string that was + * returned by {@link #partitionQuery(String, PartitionOptions, QueryOption...)}. + */ + ResultSet runPartition(String encodedPartitionId) throws SQLException; + + /** + * Executes the given query as a partitioned query. The query will first be partitioned using the + * {@link #partitionQuery(String, PartitionOptions, QueryOption...)} method. Each of the + * partitions will then be executed in the background, and the results will be merged into a + * single result set. + * + *

This method will use {@link CloudSpannerJdbcConnection#getMaxPartitionedParallelism()} + * threads to execute the partitioned query. Set this variable to a higher/lower value to + * increase/decrease the degree of parallelism used for execution. + */ + CloudSpannerJdbcPartitionedQueryResultSet runPartitionedQuery( + String query, PartitionOptions partitionOptions, QueryOption... options) throws SQLException; +} 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 6d6bd80d0..6031afe93 100644 --- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -25,6 +25,7 @@ import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.connection.AutocommitDmlMode; +import com.google.cloud.spanner.connection.Connection; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.connection.SavepointSupport; import com.google.cloud.spanner.connection.TransactionMode; @@ -44,6 +45,8 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Function; /** Jdbc Connection class for Google Cloud Spanner */ class JdbcConnection extends AbstractJdbcConnection { @@ -592,6 +595,72 @@ public void bufferedWrite(Iterable mutations) throws SQLException { } } + /** + * Convenience method for calling a setter and translating any {@link SpannerException} to a + * {@link SQLException}. + */ + private void set(BiConsumer setter, T value) throws SQLException { + checkClosed(); + try { + setter.accept(getSpannerConnection(), value); + } catch (SpannerException spannerException) { + throw JdbcSqlExceptionFactory.of(spannerException); + } + } + + /** + * Convenience method for calling a getter and translating any {@link SpannerException} to a + * {@link SQLException}. + */ + private R get(Function getter) throws SQLException { + checkClosed(); + try { + return getter.apply(getSpannerConnection()); + } catch (SpannerException spannerException) { + throw JdbcSqlExceptionFactory.of(spannerException); + } + } + + @Override + public void setDataBoostEnabled(boolean dataBoostEnabled) throws SQLException { + set(Connection::setDataBoostEnabled, dataBoostEnabled); + } + + @Override + public boolean isDataBoostEnabled() throws SQLException { + return get(Connection::isDataBoostEnabled); + } + + @Override + public void setAutoPartitionMode(boolean autoPartitionMode) throws SQLException { + set(Connection::setAutoPartitionMode, autoPartitionMode); + } + + @Override + public boolean isAutoPartitionMode() throws SQLException { + return get(Connection::isAutoPartitionMode); + } + + @Override + public void setMaxPartitions(int maxPartitions) throws SQLException { + set(Connection::setMaxPartitions, maxPartitions); + } + + @Override + public int getMaxPartitions() throws SQLException { + return get(Connection::getMaxPartitions); + } + + @Override + public void setMaxPartitionedParallelism(int maxThreads) throws SQLException { + set(Connection::setMaxPartitionedParallelism, maxThreads); + } + + @Override + public int getMaxPartitionedParallelism() throws SQLException { + return get(Connection::getMaxPartitionedParallelism); + } + @SuppressWarnings("deprecation") private static final class JdbcToSpannerTransactionRetryListener implements com.google.cloud.spanner.connection.TransactionRetryListener { diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcPartitionedQueryResultSet.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcPartitionedQueryResultSet.java new file mode 100644 index 000000000..1d5ef66fd --- /dev/null +++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcPartitionedQueryResultSet.java @@ -0,0 +1,51 @@ +/* + * 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 com.google.cloud.spanner.connection.PartitionedQueryResultSet; +import com.google.common.base.Preconditions; +import java.sql.Statement; + +/** + * {@link java.sql.ResultSet} implementation that is returned for queries that are executed with + * `RUN PARTITIONED QUERY ...`. + */ +class JdbcPartitionedQueryResultSet extends JdbcResultSet + implements CloudSpannerJdbcPartitionedQueryResultSet { + static JdbcPartitionedQueryResultSet of( + Statement statement, PartitionedQueryResultSet resultSet) { + return new JdbcPartitionedQueryResultSet( + Preconditions.checkNotNull(statement), Preconditions.checkNotNull(resultSet)); + } + + private final PartitionedQueryResultSet partitionedQueryResultSet; + + private JdbcPartitionedQueryResultSet(Statement statement, PartitionedQueryResultSet resultSet) { + super(statement, resultSet); + this.partitionedQueryResultSet = resultSet; + } + + @Override + public int getNumPartitions() { + return partitionedQueryResultSet.getNumPartitions(); + } + + @Override + public int getParallelism() { + return partitionedQueryResultSet.getParallelism(); + } +} 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 3ab302ce9..c2e0c1db0 100644 --- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.jdbc; import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.PartitionOptions; import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; import com.google.cloud.spanner.ResultSets; import com.google.cloud.spanner.SpannerException; @@ -33,7 +34,8 @@ import java.sql.SQLException; /** Implementation of {@link PreparedStatement} for Cloud Spanner. */ -class JdbcPreparedStatement extends AbstractJdbcPreparedStatement { +class JdbcPreparedStatement extends AbstractJdbcPreparedStatement + implements CloudSpannerJdbcPreparedStatement { private static final char POS_PARAM_CHAR = '?'; private final String sql; private final String sqlWithoutComments; @@ -128,4 +130,37 @@ public ResultSetMetaData getMetaData() throws SQLException { return rs.getMetaData(); } } + + @Override + public ResultSet partitionQuery(PartitionOptions partitionOptions, QueryOption... options) + throws SQLException { + return runWithStatementTimeout( + connection -> + JdbcResultSet.of( + this, connection.partitionQuery(createStatement(), partitionOptions, options))); + } + + @Override + public ResultSet runPartition() throws SQLException { + return runWithStatementTimeout( + connection -> { + if (getParameters().getHighestIndex() < 1 || getParameters().getParameter(1) == null) { + throw JdbcSqlExceptionFactory.of( + "No query parameter has been set. runPartition() requires the partition ID to be set as a query parameter with index 1. Call PreparedStatement#setString(1, \"some-partition-id\") before calling runPartition().", + Code.FAILED_PRECONDITION); + } + String partitionId = getParameters().getParameter(1).toString(); + return JdbcResultSet.of(this, connection.runPartition(partitionId)); + }); + } + + @Override + public CloudSpannerJdbcPartitionedQueryResultSet runPartitionedQuery( + PartitionOptions partitionOptions, QueryOption... options) throws SQLException { + return runWithStatementTimeout( + connection -> + JdbcPartitionedQueryResultSet.of( + this, + connection.runPartitionedQuery(createStatement(), partitionOptions, options))); + } } 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 94b460420..4152fa58b 100644 --- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -21,6 +21,7 @@ import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.Code; import com.google.cloud.spanner.Value; +import com.google.cloud.spanner.connection.PartitionedQueryResultSet; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import java.io.ByteArrayInputStream; @@ -59,9 +60,13 @@ static JdbcResultSet of(com.google.cloud.spanner.ResultSet resultSet) { } static JdbcResultSet of(Statement statement, com.google.cloud.spanner.ResultSet resultSet) { - Preconditions.checkNotNull(statement); - Preconditions.checkNotNull(resultSet); - return new JdbcResultSet(statement, resultSet); + // Return a JDBC version of a PartitionedQueryResultSet if the Cloud Spanner Java client + // returned a PartitionedQueryResultSet. + if (resultSet instanceof PartitionedQueryResultSet) { + return JdbcPartitionedQueryResultSet.of(statement, (PartitionedQueryResultSet) resultSet); + } + return new JdbcResultSet( + Preconditions.checkNotNull(statement), Preconditions.checkNotNull(resultSet)); } /** @@ -123,7 +128,7 @@ public Struct next() { private boolean nextCalledForMetaDataResult = false; private long currentRow = 0L; - private JdbcResultSet(Statement statement, com.google.cloud.spanner.ResultSet spanner) { + JdbcResultSet(Statement statement, com.google.cloud.spanner.ResultSet spanner) { super(spanner); this.statement = statement; } 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 fcc09596c..60cc3e5cf 100644 --- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -19,6 +19,8 @@ import static com.google.cloud.spanner.jdbc.JdbcConnection.NO_GENERATED_KEY_COLUMNS; import com.google.cloud.spanner.Options; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.PartitionOptions; import com.google.cloud.spanner.ResultSets; import com.google.cloud.spanner.SpannerBatchUpdateException; import com.google.cloud.spanner.SpannerException; @@ -40,7 +42,7 @@ import java.util.stream.Collectors; /** Implementation of {@link java.sql.Statement} for Google Cloud Spanner. */ -class JdbcStatement extends AbstractJdbcStatement { +class JdbcStatement extends AbstractJdbcStatement implements CloudSpannerJdbcStatement { static final ImmutableList ALL_COLUMNS = ImmutableList.of("*"); enum BatchType { @@ -585,4 +587,29 @@ public boolean execute(String sql, String[] columnNames) throws SQLException { static boolean isNullOrEmpty(String[] columnNames) { return columnNames == null || columnNames.length == 0; } + + @Override + public ResultSet partitionQuery( + String query, PartitionOptions partitionOptions, QueryOption... options) throws SQLException { + return runWithStatementTimeout( + connection -> + JdbcResultSet.of( + this, connection.partitionQuery(Statement.of(query), partitionOptions, options))); + } + + @Override + public ResultSet runPartition(String encodedPartitionId) throws SQLException { + return runWithStatementTimeout( + connection -> JdbcResultSet.of(this, connection.runPartition(encodedPartitionId))); + } + + @Override + public CloudSpannerJdbcPartitionedQueryResultSet runPartitionedQuery( + String query, PartitionOptions partitionOptions, QueryOption... options) throws SQLException { + return runWithStatementTimeout( + connection -> + JdbcPartitionedQueryResultSet.of( + this, + connection.runPartitionedQuery(Statement.of(query), partitionOptions, options))); + } } diff --git a/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java b/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java new file mode 100644 index 000000000..d6edf9993 --- /dev/null +++ b/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java @@ -0,0 +1,486 @@ +/* + * 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.PartitionOptions; +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.protobuf.ByteString; +import com.google.spanner.v1.ExecuteSqlRequest; +import com.google.spanner.v1.PartitionQueryRequest; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +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 PartitionedQueryMockServerTest 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(); + 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()); + } + + @Test + public void testPartitionedQueryUsingSql() throws SQLException { + int numRows = 5; + int maxPartitions = 4; + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + Statement statement = + Statement.newBuilder( + String.format( + "select * from my_table where active=%s", + dialect == Dialect.POSTGRESQL ? "$1" : "@p1")) + .bind("p1") + .to(true) + .build(); + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + String prefix = dialect == Dialect.POSTGRESQL ? "spanner." : ""; + + try (Connection connection = createConnection()) { + // This will automatically enable Data Boost for any partitioned query that is executed on + // this connection. The property is ignored for any query that is not a partitioned query. + connection.createStatement().execute(String.format("set %sdata_boost_enabled=true", prefix)); + // Sets the maximum number of partitions that should be used by Cloud Spanner. + // This is just a hint that can be ignored by Cloud Spanner, but the mock server that is used + // for testing respects this hint. + connection + .createStatement() + .execute(String.format("set %smax_partitions=%d", prefix, maxPartitions)); + + List partitionIds = new ArrayList<>(); + try (PreparedStatement partitionStatement = + connection.prepareStatement("partition select * from my_table where active=?")) { + partitionStatement.setBoolean(1, true); + try (ResultSet partitions = partitionStatement.executeQuery()) { + assertNotNull(partitions.getMetaData()); + while (partitions.next()) { + partitionIds.add(partitions.getString(1)); + } + } + } + + for (String partitionId : partitionIds) { + // Execute `run partition ''` to get the results of a single partition. + // This can be done from any JDBC connection, including from other hosts. + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery(String.format("run partition '%s'", partitionId))) { + assertNotNull(resultSet.getMetaData()); + int rowCount = 0; + while (resultSet.next()) { + rowCount++; + } + assertEquals(numRows, rowCount); + } + } + + for (String partitionId : partitionIds) { + // The partition ID may also be set as a query parameter. + try (PreparedStatement runStatement = connection.prepareStatement("run partition")) { + runStatement.setString(1, partitionId); + int rowCount = 0; + try (ResultSet resultSet = runStatement.executeQuery()) { + assertNotNull(resultSet.getMetaData()); + while (resultSet.next()) { + rowCount++; + } + assertEquals(numRows, rowCount); + } + } + } + + // You can also run a query directly as a partitioned query on a single JDBC connection. This + // will not give you the full benefits of a partitioned query, as the entire query is handled + // by a single host and is returned as a single result set. The result set uses multiple + // threads internally to execute the separate partitions. + // This gives users a simple way to access the Data Boost feature that should be accessible + // from most generic frameworks and tools that work with JDBC. + try (PreparedStatement partitionStatement = + connection.prepareStatement( + "run partitioned query select * from my_table where active=?")) { + partitionStatement.setBoolean(1, true); + try (ResultSet results = partitionStatement.executeQuery()) { + assertNotNull(results.getMetaData()); + assertEquals(18, results.getMetaData().getColumnCount()); + int rowCount = 0; + while (results.next()) { + rowCount++; + } + // The mock server is not smart enough to actually partition the query and only return + // a fraction of the rows per partition. The total row count will therefore be equal to + // the number of partitions multiplied by the number of rows. + assertEquals(numRows * maxPartitions, rowCount); + + // Partitioned queries return a result set with some additional metadata that can be + // inspected to determine the number of partitions and the degree of parallelism that the + // query used. + CloudSpannerJdbcPartitionedQueryResultSet partitionedQueryResultSet = + results.unwrap(CloudSpannerJdbcPartitionedQueryResultSet.class); + assertEquals(maxPartitions, partitionedQueryResultSet.getNumPartitions()); + assertEquals(1, partitionedQueryResultSet.getParallelism()); + } + } + } + } + + @Test + public void testPartitionedQueryStatement() throws SQLException { + int numRows = 5; + int maxPartitions = 4; + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + Statement statement = Statement.of("select * from my_table where active=true"); + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + + try (Connection connection = createConnection()) { + CloudSpannerJdbcConnection cloudSpannerJdbcConnection = + connection.unwrap(CloudSpannerJdbcConnection.class); + // This will automatically enable Data Boost for any partitioned query that is executed on + // this connection. The property is ignored for any query that is not a partitioned query. + cloudSpannerJdbcConnection.setDataBoostEnabled(true); + // Sets the maximum number of partitions that should be used by Cloud Spanner. + // This is just a hint that can be ignored by Cloud Spanner, but the mock server that is used + // for testing respects this hint. + cloudSpannerJdbcConnection.setMaxPartitions(maxPartitions); + + List partitionIds = new ArrayList<>(); + try (ResultSet partitions = + connection + .createStatement() + .unwrap(CloudSpannerJdbcStatement.class) + .partitionQuery( + "select * from my_table where active=true", + PartitionOptions.getDefaultInstance())) { + assertNotNull(partitions.getMetaData()); + while (partitions.next()) { + partitionIds.add(partitions.getString(1)); + } + } + + for (String partitionId : partitionIds) { + // Execute `run partition ''` to get the results of a single partition. + // This can be done from any JDBC connection, including from other hosts. + try (ResultSet resultSet = + connection + .createStatement() + .unwrap(CloudSpannerJdbcStatement.class) + .runPartition(partitionId)) { + assertNotNull(resultSet.getMetaData()); + int rowCount = 0; + while (resultSet.next()) { + rowCount++; + } + assertEquals(numRows, rowCount); + } + } + + // You can also run a query directly as a partitioned query on a single JDBC connection. This + // will not give you the full benefits of a partitioned query, as the entire query is handled + // by a single host and is returned as a single result set. The result set uses multiple + // threads internally to execute the separate partitions. + // This gives users a simple way to access the Data Boost feature that should be accessible + // from most generic frameworks and tools that work with JDBC. + try (CloudSpannerJdbcPartitionedQueryResultSet results = + connection + .createStatement() + .unwrap(CloudSpannerJdbcStatement.class) + .runPartitionedQuery( + "select * from my_table where active=true", + PartitionOptions.getDefaultInstance())) { + assertNotNull(results.getMetaData()); + int rowCount = 0; + while (results.next()) { + rowCount++; + } + // The mock server is not smart enough to actually partition the query and only return + // a fraction of the rows per partition. The total row count will therefore be equal to + // the number of partitions multiplied by the number of rows. + assertEquals(numRows * maxPartitions, rowCount); + + // Partitioned queries return a result set with some additional metadata that can be + // inspected to determine the number of partitions and the degree of parallelism that the + // query used. + assertEquals(maxPartitions, results.getNumPartitions()); + assertEquals(1, results.getParallelism()); + } + } + } + + @Test + public void testPartitionedQueryPreparedStatement() throws SQLException { + int numRows = 5; + int maxPartitions = 4; + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + Statement statement = + Statement.newBuilder( + String.format( + "select * from my_table where active=%s", + dialect == Dialect.POSTGRESQL ? "$1" : "@p1")) + .bind("p1") + .to(true) + .build(); + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + + try (Connection connection = createConnection()) { + CloudSpannerJdbcConnection cloudSpannerJdbcConnection = + connection.unwrap(CloudSpannerJdbcConnection.class); + // This will automatically enable Data Boost for any partitioned query that is executed on + // this connection. The property is ignored for any query that is not a partitioned query. + cloudSpannerJdbcConnection.setDataBoostEnabled(true); + // Sets the maximum number of partitions that should be used by Cloud Spanner. + // This is just a hint that can be ignored by Cloud Spanner, but the mock server that is used + // for testing respects this hint. + cloudSpannerJdbcConnection.setMaxPartitions(maxPartitions); + + List partitionIds = new ArrayList<>(); + try (PreparedStatement partitionStatement = + connection.prepareStatement("select * from my_table where active=?")) { + partitionStatement.setBoolean(1, true); + try (ResultSet partitions = + partitionStatement + .unwrap(CloudSpannerJdbcPreparedStatement.class) + .partitionQuery(PartitionOptions.getDefaultInstance())) { + assertNotNull(partitions.getMetaData()); + while (partitions.next()) { + partitionIds.add(partitions.getString(1)); + } + } + } + + for (String partitionId : partitionIds) { + // The partition ID can also be set as a query parameter. + // The statement text in this case is ignored and can be an empty string. + try (PreparedStatement runStatement = connection.prepareStatement("")) { + runStatement.setString(1, partitionId); + int rowCount = 0; + try (ResultSet resultSet = + runStatement.unwrap(CloudSpannerJdbcPreparedStatement.class).runPartition()) { + assertNotNull(resultSet.getMetaData()); + while (resultSet.next()) { + rowCount++; + } + assertEquals(numRows, rowCount); + } + } + } + + // You can also run a query directly as a partitioned query on a single JDBC connection. This + // will not give you the full benefits of a partitioned query, as the entire query is handled + // by a single host and is returned as a single result set. The result set uses multiple + // threads internally to execute the separate partitions. + // This gives users a simple way to access the Data Boost feature that should be accessible + // from most generic frameworks and tools that work with JDBC. + try (PreparedStatement preparedStatement = + connection.prepareStatement("select * from my_table where active=?")) { + preparedStatement.setBoolean(1, true); + try (CloudSpannerJdbcPartitionedQueryResultSet results = + preparedStatement + .unwrap(CloudSpannerJdbcPreparedStatement.class) + .runPartitionedQuery(PartitionOptions.getDefaultInstance())) { + assertNotNull(results.getMetaData()); + int rowCount = 0; + while (results.next()) { + rowCount++; + } + // The mock server is not smart enough to actually partition the query and only return + // a fraction of the rows per partition. The total row count will therefore be equal to + // the number of partitions multiplied by the number of rows. + assertEquals(numRows * maxPartitions, rowCount); + + // Partitioned queries return a result set with some additional metadata that can be + // inspected to determine the number of partitions and the degree of parallelism that the + // query used. + assertEquals(maxPartitions, results.getNumPartitions()); + assertEquals(1, results.getParallelism()); + } + } + } + } + + @Test + public void testAutoPartitionMode() throws SQLException { + int numRows = 5; + int maxPartitions = 4; + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + Statement statement = Statement.of("select * from my_table where active=true"); + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + + try (Connection connection = createConnection()) { + CloudSpannerJdbcConnection cloudSpannerJdbcConnection = + connection.unwrap(CloudSpannerJdbcConnection.class); + // This will automatically enable Data Boost for any partitioned query that is executed on + // this connection. The property is ignored for any query that is not a partitioned query. + cloudSpannerJdbcConnection.setDataBoostEnabled(true); + // Sets the maximum number of partitions that should be used by Cloud Spanner. + // This is just a hint that can be ignored by Cloud Spanner, but the mock server that is used + // for testing respects this hint. + cloudSpannerJdbcConnection.setMaxPartitions(maxPartitions); + cloudSpannerJdbcConnection.setAutoPartitionMode(true); + + try (ResultSet results = + connection.createStatement().executeQuery("select * from my_table where active=true")) { + assertNotNull(results.getMetaData()); + assertEquals(18, results.getMetaData().getColumnCount()); + int rowCount = 0; + while (results.next()) { + rowCount++; + } + // The mock server is not smart enough to actually partition the query and only return + // a fraction of the rows per partition. The total row count will therefore be equal to + // the number of partitions multiplied by the number of rows. + assertEquals(numRows * maxPartitions, rowCount); + assertEquals(1, mockSpanner.countRequestsOfType(PartitionQueryRequest.class)); + + // Partitioned queries return a result set with some additional metadata that can be + // inspected to determine the number of partitions and the degree of parallelism that the + // query used. + assertEquals( + maxPartitions, results.unwrap(JdbcPartitionedQueryResultSet.class).getNumPartitions()); + assertEquals(1, results.unwrap(JdbcPartitionedQueryResultSet.class).getParallelism()); + + // Verify that we can run metadata queries in auto_partition_mode. + // Just add a random result for the table metadata query. We don't care about the result, + // only about the fact that it should be allowed, and that it is executed in normal mode. + if (dialect == Dialect.GOOGLE_STANDARD_SQL) { + mockSpanner.putPartialStatementResult( + StatementResult.query( + Statement.of( + "SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME,\n" + + " CASE WHEN TABLE_TYPE = 'BASE TABLE' THEN 'TABLE' ELSE TABLE_TYPE END AS TABLE_TYPE,\n" + + " NULL AS REMARKS, NULL AS TYPE_CAT, NULL AS TYPE_SCHEM, NULL AS TYPE_NAME,\n" + + " NULL AS SELF_REFERENCING_COL_NAME, NULL AS REF_GENERATION\n" + + "FROM INFORMATION_SCHEMA.TABLES AS T"), + SELECT_COUNT_RESULTSET_BEFORE_INSERT)); + } else { + mockSpanner.putPartialStatementResult( + StatementResult.query( + Statement.of( + "SELECT TABLE_CATALOG AS \"TABLE_CAT\", TABLE_SCHEMA AS \"TABLE_SCHEM\", TABLE_NAME AS \"TABLE_NAME\",\n" + + " CASE WHEN TABLE_TYPE = 'BASE TABLE' THEN 'TABLE' ELSE TABLE_TYPE END AS \"TABLE_TYPE\",\n" + + " NULL AS \"REMARKS\", NULL AS \"TYPE_CAT\", NULL AS \"TYPE_SCHEM\", NULL AS \"TYPE_NAME\",\n" + + " NULL AS \"SELF_REFERENCING_COL_NAME\", NULL AS \"REF_GENERATION\"\n" + + "FROM INFORMATION_SCHEMA.TABLES AS T"), + SELECT_COUNT_RESULTSET_BEFORE_INSERT)); + } + try (ResultSet tables = connection.getMetaData().getTables(null, null, null, null)) { + assertTrue(tables.next()); + assertEquals(0, tables.getInt(1)); + assertFalse(tables.next()); + } + assertEquals( + 1, + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(req -> req.getSql().contains("FROM INFORMATION_SCHEMA.TABLES AS T")) + .count()); + ExecuteSqlRequest request = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(req -> req.getSql().contains("FROM INFORMATION_SCHEMA.TABLES AS T")) + .findFirst() + .orElse(ExecuteSqlRequest.getDefaultInstance()); + assertTrue(request.hasTransaction()); + assertTrue(request.getTransaction().hasSingleUse()); + assertTrue(request.getTransaction().getSingleUse().hasReadOnly()); + assertTrue(request.getTransaction().getSingleUse().getReadOnly().hasStrong()); + assertEquals(ByteString.EMPTY, request.getPartitionToken()); + assertEquals(1, mockSpanner.countRequestsOfType(PartitionQueryRequest.class)); + } + } + } + + @Test + public void testAutoPartitionModeEmptyResult() throws SQLException { + int numRows = 0; + int maxPartitions = 1; + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + Statement statement = Statement.of("select * from my_table where active=true"); + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + + try (Connection connection = createConnection()) { + CloudSpannerJdbcConnection cloudSpannerJdbcConnection = + connection.unwrap(CloudSpannerJdbcConnection.class); + // This will automatically enable Data Boost for any partitioned query that is executed on + // this connection. The property is ignored for any query that is not a partitioned query. + cloudSpannerJdbcConnection.setDataBoostEnabled(true); + // Sets the maximum number of partitions that should be used by Cloud Spanner. + // This is just a hint that can be ignored by Cloud Spanner, but the mock server that is used + // for testing respects this hint. + cloudSpannerJdbcConnection.setMaxPartitions(maxPartitions); + cloudSpannerJdbcConnection.setAutoPartitionMode(true); + + try (ResultSet results = + connection.createStatement().executeQuery("select * from my_table where active=true")) { + assertNotNull(results.getMetaData()); + assertEquals(18, results.getMetaData().getColumnCount()); + int rowCount = 0; + while (results.next()) { + rowCount++; + } + assertEquals(0, rowCount); + assertEquals(1, mockSpanner.countRequestsOfType(PartitionQueryRequest.class)); + + // Partitioned queries return a result set with some additional metadata that can be + // inspected to determine the number of partitions and the degree of parallelism that the + // query used. + assertEquals( + maxPartitions, results.unwrap(JdbcPartitionedQueryResultSet.class).getNumPartitions()); + assertEquals(1, results.unwrap(JdbcPartitionedQueryResultSet.class).getParallelism()); + } + } + } +} From 7c9e781bf45b112266e278e1df1586e56043698e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 15 Sep 2023 15:06:14 +0200 Subject: [PATCH 088/173] fix: comments should be sent to Spanner for PostgreSQL databases (#1331) Comments for PostgreSQL-dialect databases should be included in the request that is sent to Cloud Spanner. This is needed, because for PostgreSQL comments can contain query hints. --- .../spanner/jdbc/JdbcPreparedStatement.java | 12 +- .../spanner/jdbc/ExecuteMockServerTest.java | 277 ++++++++++-------- 2 files changed, 165 insertions(+), 124 deletions(-) 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 c2e0c1db0..518807dd1 100644 --- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Options.QueryOption; import com.google.cloud.spanner.PartitionOptions; import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; @@ -38,7 +39,6 @@ class JdbcPreparedStatement extends AbstractJdbcPreparedStatement implements CloudSpannerJdbcPreparedStatement { private static final char POS_PARAM_CHAR = '?'; private final String sql; - private final String sqlWithoutComments; private final ParametersInfo parameters; private final ImmutableList generatedKeysColumns; @@ -48,9 +48,15 @@ class JdbcPreparedStatement extends AbstractJdbcPreparedStatement super(connection); this.sql = sql; try { - this.sqlWithoutComments = parser.removeCommentsAndTrim(this.sql); + // The PostgreSQL parser allows comments to be present in the SQL string that is used to parse + // the query parameters. + String sqlForParameterExtraction = + getConnection().getDialect() == Dialect.POSTGRESQL + ? this.sql + : parser.removeCommentsAndTrim(this.sql); this.parameters = - parser.convertPositionalParametersToNamedParameters(POS_PARAM_CHAR, sqlWithoutComments); + parser.convertPositionalParametersToNamedParameters( + POS_PARAM_CHAR, sqlForParameterExtraction); } catch (SpannerException e) { throw JdbcSqlExceptionFactory.of(e); } diff --git a/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java b/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java index b62449eb5..65a54a89a 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java @@ -23,10 +23,12 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; +import com.google.cloud.spanner.Dialect; 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.cloud.spanner.connection.SpannerPool; import com.google.longrunning.Operation; import com.google.protobuf.Any; import com.google.protobuf.Empty; @@ -50,27 +52,62 @@ import org.junit.Test; import org.junit.function.ThrowingRunnable; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; /** * Test class for verifying that the methods execute, executeQuery, and executeUpdate work as - * intended. + * intended. It also verifies that they always also include any comments in the statement for the + * PostgreSQL dialect, as these may contain hints. */ -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class ExecuteMockServerTest extends AbstractMockServerTest { - private static final String QUERY = "select * from my_table"; - private static final String DML = "insert into my_table (id, value) values (1, 'One')"; - private static final String DML_THEN_RETURN_ID = DML + "\nTHEN RETURN `id`"; - private static final String LARGE_DML = "update my_table set value='new value' where true"; - private static final String LARGE_DML_THEN_RETURN_ID = LARGE_DML + "\nTHEN RETURN `id`"; - private static final String DML_RETURNING = - "insert into my_table (id, value) values (1, 'One') THEN RETURN *"; + + @Parameters(name = "dialect = {0}") + public static Object[] parameters() { + return Dialect.values(); + } + + @Parameter public Dialect dialect; + private static final String DDL = "create table my_table"; private static final long LARGE_UPDATE_COUNT = 2L * Integer.MAX_VALUE; + private String query; + private String dml; + private String largeDml; + private String dmlReturning; + @Before public void setupResults() { + query = + dialect == Dialect.POSTGRESQL + ? "/*@ lock_scanned_ranges = exclusive */ select * from my_table" + : "select * from my_table"; + dml = + dialect == Dialect.POSTGRESQL + ? "/*@ lock_scanned_ranges = exclusive */ insert into my_table (id, value) values (1, 'One')" + : "insert into my_table (id, value) values (1, 'One')"; + String DML_THEN_RETURN_ID = + dml + (dialect == Dialect.POSTGRESQL ? "\nRETURNING \"id\"" : "\nTHEN RETURN `id`"); + largeDml = + dialect == Dialect.POSTGRESQL + ? "/*@ lock_scanned_ranges = exclusive */ update my_table set value='new value' where true" + : "update my_table set value='new value' where true"; + String LARGE_DML_THEN_RETURN_ID = + largeDml + (dialect == Dialect.POSTGRESQL ? "\nRETURNING \"id\"" : "\nTHEN RETURN `id`"); + dmlReturning = + dialect == Dialect.POSTGRESQL + ? "/*@ lock_scanned_ranges = exclusive */ insert into my_table (id, value) values (1, 'One') RETURNING *" + : "insert into my_table (id, value) values (1, 'One') THEN RETURN *"; + + // This forces a refresh of the Spanner instance that is used for a connection, which again is + // needed in order to refresh the dialect of the database. + SpannerPool.closeSpannerPool(); + mockSpanner.putStatementResult(StatementResult.detectDialectResult(dialect)); super.setupResults(); + com.google.spanner.v1.ResultSet resultSet = com.google.spanner.v1.ResultSet.newBuilder() .setMetadata( @@ -114,15 +151,15 @@ public void setupResults() { .build()) .build(); mockSpanner.putStatementResult( - StatementResult.query(com.google.cloud.spanner.Statement.of(QUERY), resultSet)); + StatementResult.query(com.google.cloud.spanner.Statement.of(query), resultSet)); mockSpanner.putStatementResult( - StatementResult.update(com.google.cloud.spanner.Statement.of(DML), 1L)); + StatementResult.update(com.google.cloud.spanner.Statement.of(dml), 1L)); mockSpanner.putStatementResult( StatementResult.update( - com.google.cloud.spanner.Statement.of(LARGE_DML), LARGE_UPDATE_COUNT)); + com.google.cloud.spanner.Statement.of(largeDml), LARGE_UPDATE_COUNT)); mockSpanner.putStatementResult( StatementResult.query( - com.google.cloud.spanner.Statement.of(DML_RETURNING), + com.google.cloud.spanner.Statement.of(dmlReturning), resultSet .toBuilder() .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) @@ -163,14 +200,14 @@ private Connection createConnection() throws SQLException { public void testStatementExecuteQuery() throws SQLException { try (Connection connection = createConnection(); Statement statement = connection.createStatement()) { - try (ResultSet resultSet = statement.executeQuery(QUERY)) { + try (ResultSet resultSet = statement.executeQuery(query)) { verifyResultSet(resultSet); } - try (ResultSet resultSet = statement.executeQuery(DML_RETURNING)) { + try (ResultSet resultSet = statement.executeQuery(dmlReturning)) { verifyResultSet(resultSet); } - verifyException(() -> statement.executeQuery(DML)); - verifyException(() -> statement.executeQuery(LARGE_DML)); + verifyException(() -> statement.executeQuery(dml)); + verifyException(() -> statement.executeQuery(largeDml)); verifyException(() -> statement.executeQuery(DDL)); } } @@ -179,11 +216,11 @@ public void testStatementExecuteQuery() throws SQLException { public void testStatementExecuteUpdate() throws SQLException { try (Connection connection = createConnection(); Statement statement = connection.createStatement()) { - assertEquals(1, statement.executeUpdate(DML)); + assertEquals(1, statement.executeUpdate(dml)); assertEquals(0, statement.executeUpdate(DDL)); - verifyOverflow(() -> statement.executeUpdate(LARGE_DML)); - verifyException(() -> statement.executeUpdate(QUERY)); - verifyException(() -> statement.executeUpdate(DML_RETURNING)); + verifyOverflow(() -> statement.executeUpdate(largeDml)); + verifyException(() -> statement.executeUpdate(query)); + verifyException(() -> statement.executeUpdate(dmlReturning)); } } @@ -192,11 +229,11 @@ public void testStatementExecuteUpdateReturnGeneratedKeys() throws SQLException try (Connection connection = createConnection(); Statement statement = connection.createStatement()) { // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. - assertEquals(1, statement.executeUpdate(DML, Statement.NO_GENERATED_KEYS)); + assertEquals(1, statement.executeUpdate(dml, Statement.NO_GENERATED_KEYS)); assertEquals(0, statement.executeUpdate(DDL, Statement.NO_GENERATED_KEYS)); - verifyOverflow(() -> statement.executeUpdate(LARGE_DML, Statement.NO_GENERATED_KEYS)); - verifyException(() -> statement.executeUpdate(QUERY, Statement.NO_GENERATED_KEYS)); - verifyException(() -> statement.executeUpdate(DML_RETURNING, Statement.NO_GENERATED_KEYS)); + verifyOverflow(() -> statement.executeUpdate(largeDml, Statement.NO_GENERATED_KEYS)); + verifyException(() -> statement.executeUpdate(query, Statement.NO_GENERATED_KEYS)); + verifyException(() -> statement.executeUpdate(dmlReturning, Statement.NO_GENERATED_KEYS)); } } @@ -204,12 +241,12 @@ public void testStatementExecuteUpdateReturnGeneratedKeys() throws SQLException public void testStatementExecuteUpdateReturnColumnNames() throws SQLException { try (Connection connection = createConnection(); Statement statement = connection.createStatement()) { - assertEquals(1, statement.executeUpdate(DML, new String[] {"id"})); + assertEquals(1, statement.executeUpdate(dml, new String[] {"id"})); assertEquals(0, statement.executeUpdate(DDL, new String[] {"id"})); - verifyOverflow(() -> statement.executeUpdate(LARGE_DML, new String[] {"id"})); + verifyOverflow(() -> statement.executeUpdate(largeDml, new String[] {"id"})); verifyException( - () -> statement.executeUpdate(QUERY, new String[] {"id"}), Code.FAILED_PRECONDITION); - assertEquals(1, statement.executeUpdate(DML_RETURNING, new String[] {"id"})); + () -> statement.executeUpdate(query, new String[] {"id"}), Code.FAILED_PRECONDITION); + assertEquals(1, statement.executeUpdate(dmlReturning, new String[] {"id"})); } } @@ -217,11 +254,11 @@ public void testStatementExecuteUpdateReturnColumnNames() throws SQLException { public void testStatementExecuteUpdateReturnColumnIndexes() throws SQLException { try (Connection connection = createConnection(); Statement statement = connection.createStatement()) { - assertEquals(1, statement.executeUpdate(DML, new int[] {1})); + assertEquals(1, statement.executeUpdate(dml, new int[] {1})); assertEquals(0, statement.executeUpdate(DDL, new int[] {1})); - verifyOverflow(() -> statement.executeUpdate(LARGE_DML, new int[] {1})); - verifyException(() -> statement.executeUpdate(QUERY, new int[] {1})); - verifyException(() -> statement.executeUpdate(DML_RETURNING, new int[] {1})); + verifyOverflow(() -> statement.executeUpdate(largeDml, new int[] {1})); + verifyException(() -> statement.executeUpdate(query, new int[] {1})); + verifyException(() -> statement.executeUpdate(dmlReturning, new int[] {1})); } } @@ -229,11 +266,11 @@ public void testStatementExecuteUpdateReturnColumnIndexes() throws SQLException public void testStatementLargeExecuteUpdate() throws SQLException { try (Connection connection = createConnection(); Statement statement = connection.createStatement()) { - assertEquals(1L, statement.executeLargeUpdate(DML)); + assertEquals(1L, statement.executeLargeUpdate(dml)); assertEquals(0L, statement.executeLargeUpdate(DDL)); - assertEquals(LARGE_UPDATE_COUNT, statement.executeLargeUpdate(LARGE_DML)); - verifyException(() -> statement.executeLargeUpdate(QUERY)); - verifyException(() -> statement.executeLargeUpdate(DML_RETURNING)); + assertEquals(LARGE_UPDATE_COUNT, statement.executeLargeUpdate(largeDml)); + verifyException(() -> statement.executeLargeUpdate(query)); + verifyException(() -> statement.executeLargeUpdate(dmlReturning)); } } @@ -242,13 +279,13 @@ public void testStatementExecuteLargeUpdateReturnGeneratedKeys() throws SQLExcep try (Connection connection = createConnection(); Statement statement = connection.createStatement()) { // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. - assertEquals(1, statement.executeLargeUpdate(DML, Statement.NO_GENERATED_KEYS)); + assertEquals(1, statement.executeLargeUpdate(dml, Statement.NO_GENERATED_KEYS)); assertEquals(0, statement.executeLargeUpdate(DDL, Statement.NO_GENERATED_KEYS)); assertEquals( - LARGE_UPDATE_COUNT, statement.executeLargeUpdate(LARGE_DML, Statement.NO_GENERATED_KEYS)); - verifyException(() -> statement.executeLargeUpdate(QUERY, Statement.NO_GENERATED_KEYS)); + LARGE_UPDATE_COUNT, statement.executeLargeUpdate(largeDml, Statement.NO_GENERATED_KEYS)); + verifyException(() -> statement.executeLargeUpdate(query, Statement.NO_GENERATED_KEYS)); verifyException( - () -> statement.executeLargeUpdate(DML_RETURNING, Statement.NO_GENERATED_KEYS)); + () -> statement.executeLargeUpdate(dmlReturning, Statement.NO_GENERATED_KEYS)); } } @@ -256,13 +293,12 @@ public void testStatementExecuteLargeUpdateReturnGeneratedKeys() throws SQLExcep public void testStatementExecuteLargeUpdateReturnColumnNames() throws SQLException { try (Connection connection = createConnection(); Statement statement = connection.createStatement()) { - assertEquals(1, statement.executeLargeUpdate(DML, new String[] {"id"})); + assertEquals(1, statement.executeLargeUpdate(dml, new String[] {"id"})); assertEquals(0, statement.executeLargeUpdate(DDL, new String[] {"id"})); - assertEquals( - LARGE_UPDATE_COUNT, statement.executeLargeUpdate(LARGE_DML, new String[] {"id"})); + assertEquals(LARGE_UPDATE_COUNT, statement.executeLargeUpdate(largeDml, new String[] {"id"})); verifyException( - () -> statement.executeLargeUpdate(QUERY, new String[] {"id"}), Code.FAILED_PRECONDITION); - assertEquals(1L, statement.executeLargeUpdate(DML_RETURNING, new String[] {"id"})); + () -> statement.executeLargeUpdate(query, new String[] {"id"}), Code.FAILED_PRECONDITION); + assertEquals(1L, statement.executeLargeUpdate(dmlReturning, new String[] {"id"})); } } @@ -270,11 +306,11 @@ public void testStatementExecuteLargeUpdateReturnColumnNames() throws SQLExcepti public void testStatementExecuteLargeUpdateReturnColumnIndexes() throws SQLException { try (Connection connection = createConnection(); Statement statement = connection.createStatement()) { - assertEquals(1, statement.executeLargeUpdate(DML, new int[] {1})); + assertEquals(1, statement.executeLargeUpdate(dml, new int[] {1})); assertEquals(0, statement.executeLargeUpdate(DDL, new int[] {1})); - assertEquals(LARGE_UPDATE_COUNT, statement.executeLargeUpdate(LARGE_DML, new int[] {1})); - verifyException(() -> statement.executeLargeUpdate(QUERY, new int[] {1})); - verifyException(() -> statement.executeLargeUpdate(DML_RETURNING, new int[] {1})); + assertEquals(LARGE_UPDATE_COUNT, statement.executeLargeUpdate(largeDml, new int[] {1})); + verifyException(() -> statement.executeLargeUpdate(query, new int[] {1})); + verifyException(() -> statement.executeLargeUpdate(dmlReturning, new int[] {1})); } } @@ -282,11 +318,11 @@ public void testStatementExecuteLargeUpdateReturnColumnIndexes() throws SQLExcep public void testStatementExecute() throws SQLException { try (Connection connection = createConnection(); Statement statement = connection.createStatement()) { - verifyUpdateCount(statement, () -> statement.execute(DML), 1L); - verifyUpdateCount(statement, () -> statement.execute(LARGE_DML), LARGE_UPDATE_COUNT); + verifyUpdateCount(statement, () -> statement.execute(dml), 1L); + verifyUpdateCount(statement, () -> statement.execute(largeDml), LARGE_UPDATE_COUNT); verifyUpdateCount(statement, () -> statement.execute(DDL), Statement.SUCCESS_NO_INFO); - verifyResultSet(statement, () -> statement.execute(QUERY)); - verifyResultSet(statement, () -> statement.execute(DML_RETURNING)); + verifyResultSet(statement, () -> statement.execute(query)); + verifyResultSet(statement, () -> statement.execute(dmlReturning)); } } @@ -295,18 +331,18 @@ public void testStatementExecuteReturnGeneratedKeys() throws SQLException { try (Connection connection = createConnection(); Statement statement = connection.createStatement()) { // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. - verifyUpdateCount(statement, () -> statement.execute(DML, Statement.NO_GENERATED_KEYS), 1L); + verifyUpdateCount(statement, () -> statement.execute(dml, Statement.NO_GENERATED_KEYS), 1L); verifyUpdateCount( statement, - () -> statement.execute(LARGE_DML, Statement.NO_GENERATED_KEYS), + () -> statement.execute(largeDml, Statement.NO_GENERATED_KEYS), LARGE_UPDATE_COUNT); verifyUpdateCount( statement, () -> statement.execute(DDL, Statement.NO_GENERATED_KEYS), Statement.SUCCESS_NO_INFO); - verifyResultSet(statement, () -> statement.execute(QUERY, Statement.NO_GENERATED_KEYS)); + verifyResultSet(statement, () -> statement.execute(query, Statement.NO_GENERATED_KEYS)); verifyResultSet( - statement, () -> statement.execute(DML_RETURNING, Statement.NO_GENERATED_KEYS)); + statement, () -> statement.execute(dmlReturning, Statement.NO_GENERATED_KEYS)); } } @@ -314,13 +350,13 @@ public void testStatementExecuteReturnGeneratedKeys() throws SQLException { public void testStatementExecuteReturnColumnNames() throws SQLException { try (Connection connection = createConnection(); Statement statement = connection.createStatement()) { - verifyUpdateCount(statement, () -> statement.execute(DML, new String[] {"id"}), 1L); + verifyUpdateCount(statement, () -> statement.execute(dml, new String[] {"id"}), 1L); verifyUpdateCount( - statement, () -> statement.execute(LARGE_DML, new String[] {"id"}), LARGE_UPDATE_COUNT); + statement, () -> statement.execute(largeDml, new String[] {"id"}), LARGE_UPDATE_COUNT); verifyUpdateCount( statement, () -> statement.execute(DDL, new String[] {"id"}), Statement.SUCCESS_NO_INFO); - verifyResultSet(statement, () -> statement.execute(QUERY, new String[] {"id"})); - verifyResultSet(statement, () -> statement.execute(DML_RETURNING, new String[] {"id"})); + verifyResultSet(statement, () -> statement.execute(query, new String[] {"id"})); + verifyResultSet(statement, () -> statement.execute(dmlReturning, new String[] {"id"})); } } @@ -328,27 +364,27 @@ public void testStatementExecuteReturnColumnNames() throws SQLException { public void testStatementExecuteReturnColumnIndexes() throws SQLException { try (Connection connection = createConnection(); Statement statement = connection.createStatement()) { - verifyUpdateCount(statement, () -> statement.execute(DML, new int[] {1}), 1L); + verifyUpdateCount(statement, () -> statement.execute(dml, new int[] {1}), 1L); verifyUpdateCount( - statement, () -> statement.execute(LARGE_DML, new int[] {1}), LARGE_UPDATE_COUNT); + statement, () -> statement.execute(largeDml, new int[] {1}), LARGE_UPDATE_COUNT); verifyUpdateCount( statement, () -> statement.execute(DDL, new int[] {1}), Statement.SUCCESS_NO_INFO); - verifyResultSet(statement, () -> statement.execute(QUERY, new int[] {1})); - verifyResultSet(statement, () -> statement.execute(DML_RETURNING, new int[] {1})); + verifyResultSet(statement, () -> statement.execute(query, new int[] {1})); + verifyResultSet(statement, () -> statement.execute(dmlReturning, new int[] {1})); } } @Test public void testPreparedStatementExecuteQuery() throws SQLException { try (Connection connection = createConnection()) { - try (ResultSet resultSet = connection.prepareStatement(QUERY).executeQuery()) { + try (ResultSet resultSet = connection.prepareStatement(query).executeQuery()) { verifyResultSet(resultSet); } - try (ResultSet resultSet = connection.prepareStatement(DML_RETURNING).executeQuery()) { + try (ResultSet resultSet = connection.prepareStatement(dmlReturning).executeQuery()) { verifyResultSet(resultSet); } - verifyException(() -> connection.prepareStatement(DML).executeQuery()); - verifyException(() -> connection.prepareStatement(LARGE_DML).executeQuery()); + verifyException(() -> connection.prepareStatement(dml).executeQuery()); + verifyException(() -> connection.prepareStatement(largeDml).executeQuery()); verifyException(() -> connection.prepareStatement(DDL).executeQuery()); } } @@ -356,14 +392,14 @@ public void testPreparedStatementExecuteQuery() throws SQLException { @Test public void testPreparedStatementExecuteUpdate() throws SQLException { try (Connection connection = createConnection()) { - assertEquals(1, connection.prepareStatement(DML).executeUpdate()); + assertEquals(1, connection.prepareStatement(dml).executeUpdate()); // TODO: Enable the next statement once PreparedStatement supports executing DDL through the // executeUpdate() method. // assertEquals(0, connection.prepareStatement(DDL).executeUpdate()); - verifyOverflow(() -> connection.prepareStatement(LARGE_DML).executeUpdate()); - verifyException(() -> connection.prepareStatement(QUERY).executeUpdate()); + verifyOverflow(() -> connection.prepareStatement(largeDml).executeUpdate()); + verifyException(() -> connection.prepareStatement(query).executeUpdate()); verifyException( - () -> connection.prepareStatement(DML_RETURNING).executeUpdate(), Code.INVALID_ARGUMENT); + () -> connection.prepareStatement(dmlReturning).executeUpdate(), Code.INVALID_ARGUMENT); } } @@ -372,20 +408,19 @@ public void testPreparedStatementExecuteUpdateReturnGeneratedKeys() throws SQLEx try (Connection connection = createConnection()) { // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. assertEquals( - 1, connection.prepareStatement(DML, Statement.NO_GENERATED_KEYS).executeUpdate()); + 1, connection.prepareStatement(dml, Statement.NO_GENERATED_KEYS).executeUpdate()); // TODO: Enable the next statement once PreparedStatement supports executing DDL through the // executeUpdate() method. // assertEquals(0, connection.prepareStatement(DDL, // Statement.NO_GENERATED_KEYS).executeUpdate()); verifyOverflow( - () -> - connection.prepareStatement(LARGE_DML, Statement.NO_GENERATED_KEYS).executeUpdate()); + () -> connection.prepareStatement(largeDml, Statement.NO_GENERATED_KEYS).executeUpdate()); verifyException( - () -> connection.prepareStatement(QUERY, Statement.NO_GENERATED_KEYS).executeUpdate()); + () -> connection.prepareStatement(query, Statement.NO_GENERATED_KEYS).executeUpdate()); verifyException( () -> connection - .prepareStatement(DML_RETURNING, Statement.NO_GENERATED_KEYS) + .prepareStatement(dmlReturning, Statement.NO_GENERATED_KEYS) .executeUpdate(), Code.INVALID_ARGUMENT); } @@ -394,31 +429,31 @@ public void testPreparedStatementExecuteUpdateReturnGeneratedKeys() throws SQLEx @Test public void testPreparedStatementExecuteUpdateReturnColumnNames() throws SQLException { try (Connection connection = createConnection()) { - assertEquals(1, connection.prepareStatement(DML, new String[] {"id"}).executeUpdate()); + assertEquals(1, connection.prepareStatement(dml, new String[] {"id"}).executeUpdate()); // TODO: Enable the next statement once PreparedStatement supports executing DDL through the // executeUpdate() method. // assertEquals(0, connection.prepareStatement(DDL, new String[] {"id"}).executeUpdate()); verifyOverflow( - () -> connection.prepareStatement(LARGE_DML, new String[] {"id"}).executeUpdate()); + () -> connection.prepareStatement(largeDml, new String[] {"id"}).executeUpdate()); verifyException( - () -> connection.prepareStatement(QUERY, new String[] {"id"}).executeUpdate(), + () -> connection.prepareStatement(query, new String[] {"id"}).executeUpdate(), Code.FAILED_PRECONDITION); assertEquals( - 1, connection.prepareStatement(DML_RETURNING, new String[] {"id"}).executeUpdate()); + 1, connection.prepareStatement(dmlReturning, new String[] {"id"}).executeUpdate()); } } @Test public void testPreparedStatementExecuteUpdateReturnColumnIndexes() throws SQLException { try (Connection connection = createConnection()) { - assertEquals(1, connection.prepareStatement(DML, new int[] {1}).executeUpdate()); + assertEquals(1, connection.prepareStatement(dml, new int[] {1}).executeUpdate()); // TODO: Enable the next statement once PreparedStatement supports executing DDL through the // executeUpdate() method. // assertEquals(0, connection.prepareStatement(DDL, new int[] {1}).executeUpdate()); - verifyOverflow(() -> connection.prepareStatement(LARGE_DML, new int[] {1}).executeUpdate()); - verifyException(() -> connection.prepareStatement(QUERY, new int[] {1}).executeUpdate()); + verifyOverflow(() -> connection.prepareStatement(largeDml, new int[] {1}).executeUpdate()); + verifyException(() -> connection.prepareStatement(query, new int[] {1}).executeUpdate()); verifyException( - () -> connection.prepareStatement(DML_RETURNING, new int[] {1}).executeUpdate(), + () -> connection.prepareStatement(dmlReturning, new int[] {1}).executeUpdate(), Code.INVALID_ARGUMENT); } } @@ -426,14 +461,14 @@ public void testPreparedStatementExecuteUpdateReturnColumnIndexes() throws SQLEx @Test public void testPreparedStatementLargeExecuteUpdate() throws SQLException { try (Connection connection = createConnection()) { - assertEquals(1L, connection.prepareStatement(DML).executeLargeUpdate()); + assertEquals(1L, connection.prepareStatement(dml).executeLargeUpdate()); // TODO: Enable the next statement once PreparedStatement supports executing DDL through the // executeUpdate() method. // assertEquals(0L, connection.prepareStatement(DDL).executeLargeUpdate()); - assertEquals(LARGE_UPDATE_COUNT, connection.prepareStatement(LARGE_DML).executeLargeUpdate()); - verifyException(() -> connection.prepareStatement(QUERY).executeLargeUpdate()); + assertEquals(LARGE_UPDATE_COUNT, connection.prepareStatement(largeDml).executeLargeUpdate()); + verifyException(() -> connection.prepareStatement(query).executeLargeUpdate()); verifyException( - () -> connection.prepareStatement(DML_RETURNING).executeLargeUpdate(), + () -> connection.prepareStatement(dmlReturning).executeLargeUpdate(), Code.INVALID_ARGUMENT); } } @@ -443,21 +478,21 @@ public void testPreparedStatementExecuteLargeUpdateReturnGeneratedKeys() throws try (Connection connection = createConnection()) { // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. assertEquals( - 1, connection.prepareStatement(DML, Statement.NO_GENERATED_KEYS).executeLargeUpdate()); + 1, connection.prepareStatement(dml, Statement.NO_GENERATED_KEYS).executeLargeUpdate()); // TODO: Enable the next statement once PreparedStatement supports executing DDL through the // executeUpdate() method. // assertEquals(0, connection.prepareStatement(DDL, // Statement.NO_GENERATED_KEYS).executeLargeUpdate()); assertEquals( LARGE_UPDATE_COUNT, - connection.prepareStatement(LARGE_DML, Statement.NO_GENERATED_KEYS).executeLargeUpdate()); + connection.prepareStatement(largeDml, Statement.NO_GENERATED_KEYS).executeLargeUpdate()); verifyException( () -> - connection.prepareStatement(QUERY, Statement.NO_GENERATED_KEYS).executeLargeUpdate()); + connection.prepareStatement(query, Statement.NO_GENERATED_KEYS).executeLargeUpdate()); verifyException( () -> connection - .prepareStatement(DML_RETURNING, Statement.NO_GENERATED_KEYS) + .prepareStatement(dmlReturning, Statement.NO_GENERATED_KEYS) .executeLargeUpdate(), Code.INVALID_ARGUMENT); } @@ -466,35 +501,35 @@ public void testPreparedStatementExecuteLargeUpdateReturnGeneratedKeys() throws @Test public void testPreparedStatementExecuteLargeUpdateReturnColumnNames() throws SQLException { try (Connection connection = createConnection()) { - assertEquals(1, connection.prepareStatement(DML, new String[] {"id"}).executeLargeUpdate()); + assertEquals(1, connection.prepareStatement(dml, new String[] {"id"}).executeLargeUpdate()); // TODO: Enable the next statement once PreparedStatement supports executing DDL through the // executeUpdate() method. // assertEquals(0, connection.prepareStatement(DDL, new String[] // {"id"}).executeLargeUpdate()); assertEquals( LARGE_UPDATE_COUNT, - connection.prepareStatement(LARGE_DML, new String[] {"id"}).executeLargeUpdate()); + connection.prepareStatement(largeDml, new String[] {"id"}).executeLargeUpdate()); verifyException( - () -> connection.prepareStatement(QUERY, new String[] {"id"}).executeLargeUpdate(), + () -> connection.prepareStatement(query, new String[] {"id"}).executeLargeUpdate(), Code.FAILED_PRECONDITION); assertEquals( - 1L, connection.prepareStatement(DML_RETURNING, new String[] {"id"}).executeLargeUpdate()); + 1L, connection.prepareStatement(dmlReturning, new String[] {"id"}).executeLargeUpdate()); } } @Test public void testPreparedStatementExecuteLargeUpdateReturnColumnIndexes() throws SQLException { try (Connection connection = createConnection()) { - assertEquals(1, connection.prepareStatement(DML, new int[] {1}).executeLargeUpdate()); + assertEquals(1, connection.prepareStatement(dml, new int[] {1}).executeLargeUpdate()); // TODO: Enable the next statement once PreparedStatement supports executing DDL through the // executeUpdate() method. // assertEquals(0, connection.prepareStatement(DDL, new int[] {1}).executeLargeUpdate()); assertEquals( LARGE_UPDATE_COUNT, - connection.prepareStatement(LARGE_DML, new int[] {1}).executeLargeUpdate()); - verifyException(() -> connection.prepareStatement(QUERY, new int[] {1}).executeLargeUpdate()); + connection.prepareStatement(largeDml, new int[] {1}).executeLargeUpdate()); + verifyException(() -> connection.prepareStatement(query, new int[] {1}).executeLargeUpdate()); verifyException( - () -> connection.prepareStatement(DML_RETURNING, new int[] {1}).executeLargeUpdate(), + () -> connection.prepareStatement(dmlReturning, new int[] {1}).executeLargeUpdate(), Code.INVALID_ARGUMENT); } } @@ -502,14 +537,14 @@ public void testPreparedStatementExecuteLargeUpdateReturnColumnIndexes() throws @Test public void testPreparedStatementExecute() throws SQLException { try (Connection connection = createConnection()) { - verifyPreparedUpdateCount(connection.prepareStatement(DML), PreparedStatement::execute, 1L); + verifyPreparedUpdateCount(connection.prepareStatement(dml), PreparedStatement::execute, 1L); verifyPreparedUpdateCount( - connection.prepareStatement(LARGE_DML), PreparedStatement::execute, LARGE_UPDATE_COUNT); + connection.prepareStatement(largeDml), PreparedStatement::execute, LARGE_UPDATE_COUNT); verifyPreparedUpdateCount( connection.prepareStatement(DDL), PreparedStatement::execute, Statement.SUCCESS_NO_INFO); - verifyPreparedResultSet(connection.prepareStatement(QUERY), PreparedStatement::execute); + verifyPreparedResultSet(connection.prepareStatement(query), PreparedStatement::execute); verifyPreparedResultSet( - connection.prepareStatement(DML_RETURNING), PreparedStatement::execute); + connection.prepareStatement(dmlReturning), PreparedStatement::execute); } } @@ -518,11 +553,11 @@ public void testPreparedStatementExecuteReturnGeneratedKeys() throws SQLExceptio try (Connection connection = createConnection()) { // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. verifyPreparedUpdateCount( - connection.prepareStatement(DML, Statement.NO_GENERATED_KEYS), + connection.prepareStatement(dml, Statement.NO_GENERATED_KEYS), PreparedStatement::execute, 1L); verifyPreparedUpdateCount( - connection.prepareStatement(LARGE_DML, Statement.NO_GENERATED_KEYS), + connection.prepareStatement(largeDml, Statement.NO_GENERATED_KEYS), PreparedStatement::execute, LARGE_UPDATE_COUNT); verifyPreparedUpdateCount( @@ -530,10 +565,10 @@ public void testPreparedStatementExecuteReturnGeneratedKeys() throws SQLExceptio PreparedStatement::execute, Statement.SUCCESS_NO_INFO); verifyPreparedResultSet( - connection.prepareStatement(QUERY, Statement.NO_GENERATED_KEYS), + connection.prepareStatement(query, Statement.NO_GENERATED_KEYS), PreparedStatement::execute); verifyPreparedResultSet( - connection.prepareStatement(DML_RETURNING, Statement.NO_GENERATED_KEYS), + connection.prepareStatement(dmlReturning, Statement.NO_GENERATED_KEYS), PreparedStatement::execute); } } @@ -542,9 +577,9 @@ public void testPreparedStatementExecuteReturnGeneratedKeys() throws SQLExceptio public void testPreparedStatementExecuteReturnColumnNames() throws SQLException { try (Connection connection = createConnection()) { verifyPreparedUpdateCount( - connection.prepareStatement(DML, new String[] {"id"}), PreparedStatement::execute, 1L); + connection.prepareStatement(dml, new String[] {"id"}), PreparedStatement::execute, 1L); verifyPreparedUpdateCount( - connection.prepareStatement(LARGE_DML, new String[] {"id"}), + connection.prepareStatement(largeDml, new String[] {"id"}), PreparedStatement::execute, LARGE_UPDATE_COUNT); verifyPreparedUpdateCount( @@ -552,9 +587,9 @@ public void testPreparedStatementExecuteReturnColumnNames() throws SQLException PreparedStatement::execute, Statement.SUCCESS_NO_INFO); verifyPreparedResultSet( - connection.prepareStatement(QUERY, new String[] {"id"}), PreparedStatement::execute); + connection.prepareStatement(query, new String[] {"id"}), PreparedStatement::execute); verifyPreparedResultSet( - connection.prepareStatement(DML_RETURNING, new String[] {"id"}), + connection.prepareStatement(dmlReturning, new String[] {"id"}), PreparedStatement::execute); } } @@ -563,9 +598,9 @@ public void testPreparedStatementExecuteReturnColumnNames() throws SQLException public void testPreparedStatementExecuteReturnColumnIndexes() throws SQLException { try (Connection connection = createConnection()) { verifyPreparedUpdateCount( - connection.prepareStatement(DML, new int[] {1}), PreparedStatement::execute, 1L); + connection.prepareStatement(dml, new int[] {1}), PreparedStatement::execute, 1L); verifyPreparedUpdateCount( - connection.prepareStatement(LARGE_DML, new int[] {1}), + connection.prepareStatement(largeDml, new int[] {1}), PreparedStatement::execute, LARGE_UPDATE_COUNT); verifyPreparedUpdateCount( @@ -573,9 +608,9 @@ public void testPreparedStatementExecuteReturnColumnIndexes() throws SQLExceptio PreparedStatement::execute, Statement.SUCCESS_NO_INFO); verifyPreparedResultSet( - connection.prepareStatement(QUERY, new int[] {1}), PreparedStatement::execute); + connection.prepareStatement(query, new int[] {1}), PreparedStatement::execute); verifyPreparedResultSet( - connection.prepareStatement(DML_RETURNING, new int[] {1}), PreparedStatement::execute); + connection.prepareStatement(dmlReturning, new int[] {1}), PreparedStatement::execute); } } @@ -671,7 +706,7 @@ public void testInvalidExecuteUpdate_shouldNotLeakSession() throws SQLException for (int i = 0; i < (maxSessions + 1); i++) { SQLException exception = assertThrows( - SQLException.class, () -> connection.createStatement().executeUpdate(QUERY)); + 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. From 893f61ab04e32c690f1ff9fc813bd2ba6ebca328 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 15 Sep 2023 15:25:44 +0200 Subject: [PATCH 089/173] deps: update dependency org.springframework.data:spring-data-bom to v2023.0.4 (#1347) --- samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index ee5a44390..ba78496a4 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2023.0.3 + 2023.0.4 import pom From 72fdbbfd735bf75eb1bebc20f40e952a496c88fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 15 Sep 2023 17:02:14 +0200 Subject: [PATCH 090/173] chore: add copyright header to expected query in test (#1348) Fixes the build error in #1345 This test failure is caused by the recent update that ensures that PostgreSQL-dialect queries also send all comments to Cloud Spanner, which means that the expected query in this test has changed. --- .../jdbc/PartitionedQueryMockServerTest.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java b/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java index d6edf9993..7e4e74953 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java @@ -411,7 +411,23 @@ public void testAutoPartitionMode() throws SQLException { mockSpanner.putPartialStatementResult( StatementResult.query( Statement.of( - "SELECT TABLE_CATALOG AS \"TABLE_CAT\", TABLE_SCHEMA AS \"TABLE_SCHEM\", TABLE_NAME AS \"TABLE_NAME\",\n" + "/*\n" + + " * Copyright 2022 Google LLC\n" + + " *\n" + + " * Licensed under the Apache License, Version 2.0 (the \"License\");\n" + + " * you may not use this file except in compliance with the License.\n" + + " * You may obtain a copy of the License at\n" + + " *\n" + + " * http://www.apache.org/licenses/LICENSE-2.0\n" + + " *\n" + + " * Unless required by applicable law or agreed to in writing, software\n" + + " * distributed under the License is distributed on an \"AS IS\" BASIS,\n" + + " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + + " * See the License for the specific language governing permissions and\n" + + " * limitations under the License.\n" + + " */\n" + + "\n" + + "SELECT TABLE_CATALOG AS \"TABLE_CAT\", TABLE_SCHEMA AS \"TABLE_SCHEM\", TABLE_NAME AS \"TABLE_NAME\",\n" + " CASE WHEN TABLE_TYPE = 'BASE TABLE' THEN 'TABLE' ELSE TABLE_TYPE END AS \"TABLE_TYPE\",\n" + " NULL AS \"REMARKS\", NULL AS \"TYPE_CAT\", NULL AS \"TYPE_SCHEM\", NULL AS \"TYPE_NAME\",\n" + " NULL AS \"SELF_REFERENCING_COL_NAME\", NULL AS \"REF_GENERATION\"\n" From ce82b42d3abb8de0f8b3ee2915c2008673775ea1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 15 Sep 2023 17:20:27 +0200 Subject: [PATCH 091/173] deps: update actions/checkout action to v4 - abandoned (#1333) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update actions/checkout action to v4 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot --- .github/workflows/integration-tests-against-emulator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration-tests-against-emulator.yaml b/.github/workflows/integration-tests-against-emulator.yaml index 8ee7c4d5d..f299be4f9 100644 --- a/.github/workflows/integration-tests-against-emulator.yaml +++ b/.github/workflows/integration-tests-against-emulator.yaml @@ -16,7 +16,7 @@ jobs: - 9020:9020 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 - uses: stCarolas/setup-maven@v4 with: maven-version: 3.8.1 From 247a35f77b76a619252d6a0ec0ae7ca89da11a59 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 16 Sep 2023 12:44:12 +0000 Subject: [PATCH 092/173] chore(main): release 2.13.0 (#1345) :robot: I have created a release *beep* *boop* --- ## [2.13.0](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.12.1...v2.13.0) (2023-09-15) ### Features * Support partitioned queries ([#1300](https://togithub.com/googleapis/java-spanner-jdbc/issues/1300)) ([c50da41](https://togithub.com/googleapis/java-spanner-jdbc/commit/c50da41e688ff48f8967c0f114f5bac8eaac49f9)) ### Bug Fixes * Comments should be sent to Spanner for PostgreSQL databases ([#1331](https://togithub.com/googleapis/java-spanner-jdbc/issues/1331)) ([7c9e781](https://togithub.com/googleapis/java-spanner-jdbc/commit/7c9e781bf45b112266e278e1df1586e56043698e)) ### Documentation * Create Spring Data JDBC sample ([#1334](https://togithub.com/googleapis/java-spanner-jdbc/issues/1334)) ([cefea55](https://togithub.com/googleapis/java-spanner-jdbc/commit/cefea55086eb191f71a1a493e046cb136f9f9f87)) ### Dependencies * Update actions/checkout action to v4 - abandoned ([#1333](https://togithub.com/googleapis/java-spanner-jdbc/issues/1333)) ([ce82b42](https://togithub.com/googleapis/java-spanner-jdbc/commit/ce82b42d3abb8de0f8b3ee2915c2008673775ea1)) * Update dependency org.springframework.data:spring-data-bom to v2023.0.4 ([#1347](https://togithub.com/googleapis/java-spanner-jdbc/issues/1347)) ([893f61a](https://togithub.com/googleapis/java-spanner-jdbc/commit/893f61ab04e32c690f1ff9fc813bd2ba6ebca328)) --- 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 | 23 +++++++++++++++++++++++ pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- versions.txt | 2 +- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index beda76d7f..af67a88f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## [2.13.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.12.1...v2.13.0) (2023-09-15) + + +### Features + +* Support partitioned queries ([#1300](https://github.com/googleapis/java-spanner-jdbc/issues/1300)) ([c50da41](https://github.com/googleapis/java-spanner-jdbc/commit/c50da41e688ff48f8967c0f114f5bac8eaac49f9)) + + +### Bug Fixes + +* Comments should be sent to Spanner for PostgreSQL databases ([#1331](https://github.com/googleapis/java-spanner-jdbc/issues/1331)) ([7c9e781](https://github.com/googleapis/java-spanner-jdbc/commit/7c9e781bf45b112266e278e1df1586e56043698e)) + + +### Documentation + +* Create Spring Data JDBC sample ([#1334](https://github.com/googleapis/java-spanner-jdbc/issues/1334)) ([cefea55](https://github.com/googleapis/java-spanner-jdbc/commit/cefea55086eb191f71a1a493e046cb136f9f9f87)) + + +### Dependencies + +* Update actions/checkout action to v4 - abandoned ([#1333](https://github.com/googleapis/java-spanner-jdbc/issues/1333)) ([ce82b42](https://github.com/googleapis/java-spanner-jdbc/commit/ce82b42d3abb8de0f8b3ee2915c2008673775ea1)) +* Update dependency org.springframework.data:spring-data-bom to v2023.0.4 ([#1347](https://github.com/googleapis/java-spanner-jdbc/issues/1347)) ([893f61a](https://github.com/googleapis/java-spanner-jdbc/commit/893f61ab04e32c690f1ff9fc813bd2ba6ebca328)) + ## [2.12.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.12.0...v2.12.1) (2023-09-12) diff --git a/pom.xml b/pom.xml index 5d2bd1a22..3535b11a1 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.2-SNAPSHOT + 2.13.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 f0f41910a..a8db364bb 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.12.2-SNAPSHOT + 2.13.0 diff --git a/versions.txt b/versions.txt index 2da236249..192f98ebc 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.2-SNAPSHOT +google-cloud-spanner-jdbc:2.13.0:2.13.0 From 644827475f2661809a015229cdf0d455f9ef90ac Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 16 Sep 2023 14:10:13 +0000 Subject: [PATCH 093/173] chore(main): release 2.13.1-SNAPSHOT (#1350) :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 3535b11a1..92be04a5a 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.13.0 + 2.13.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 a8db364bb..69d2a1b7b 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.0 + 2.13.1-SNAPSHOT diff --git a/versions.txt b/versions.txt index 192f98ebc..3ea029151 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.13.0:2.13.0 +google-cloud-spanner-jdbc:2.13.0:2.13.1-SNAPSHOT From 5561ecb2114f2fc45478e87c346659a78f1032aa Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 17 Sep 2023 13:58:25 +0200 Subject: [PATCH 094/173] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.13.0 (#1351) --- samples/install-without-bom/pom.xml | 2 +- samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 0e0e2d7ae..2cf650a89 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.1 + 2.13.0 diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index ba78496a4..6816cff36 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -48,7 +48,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.12.1 + 2.13.0 org.postgresql From 56eebd0507a75a6dbdef8c63d85998eb97060aa1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 17 Sep 2023 13:58:43 +0200 Subject: [PATCH 095/173] build(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.6.0 (#1349) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 92be04a5a..cbdc4b5e5 100644 --- a/pom.xml +++ b/pom.xml @@ -420,7 +420,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.5.0 + 3.6.0 html From 516de6ef701edcaf3eb48de5f98018d2a00a62bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 17 Sep 2023 13:58:57 +0200 Subject: [PATCH 096/173] build(deps): bump cryptography from 41.0.2 to 41.0.3 in /.kokoro (#1304) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build(deps): bump cryptography from 41.0.2 to 41.0.3 in /.kokoro Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.2 to 41.0.3. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/41.0.2...41.0.3) --- 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 88cd905bece9c8da7f26b637392e35ab2536edeb Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 21 Sep 2023 20:21:09 +0200 Subject: [PATCH 097/173] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.1.4 (#1353) --- samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 6816cff36..d9bf6c92a 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -41,7 +41,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.1.3 + 3.1.4 From 22736ccc40e5274513df39b08d4aea2a1afbaff3 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 21 Sep 2023 19:50:13 +0000 Subject: [PATCH 098/173] chore(main): release 2.13.1 (#1354) :robot: I have created a release *beep* *boop* --- ## [2.13.1](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.13.0...v2.13.1) (2023-09-21) ### Dependencies * Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.1.4 ([#1353](https://togithub.com/googleapis/java-spanner-jdbc/issues/1353)) ([88cd905](https://togithub.com/googleapis/java-spanner-jdbc/commit/88cd905bece9c8da7f26b637392e35ab2536edeb)) --- 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 af67a88f5..2b73e9670 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.13.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.13.0...v2.13.1) (2023-09-21) + + +### Dependencies + +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.1.4 ([#1353](https://github.com/googleapis/java-spanner-jdbc/issues/1353)) ([88cd905](https://github.com/googleapis/java-spanner-jdbc/commit/88cd905bece9c8da7f26b637392e35ab2536edeb)) + ## [2.13.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.12.1...v2.13.0) (2023-09-15) diff --git a/pom.xml b/pom.xml index cbdc4b5e5..aa9177211 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.13.1-SNAPSHOT + 2.13.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 69d2a1b7b..d07587fdb 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.1-SNAPSHOT + 2.13.1 diff --git a/versions.txt b/versions.txt index 3ea029151..e9091c973 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.13.0:2.13.1-SNAPSHOT +google-cloud-spanner-jdbc:2.13.1:2.13.1 From d0058f574b19e7cb9db71da3d313d735dd70876a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 21 Sep 2023 21:14:13 +0000 Subject: [PATCH 099/173] chore(main): release 2.13.2-SNAPSHOT (#1356) :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 aa9177211..f16371b5d 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.13.1 + 2.13.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 d07587fdb..c60583de4 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.1 + 2.13.2-SNAPSHOT diff --git a/versions.txt b/versions.txt index e9091c973..993752b80 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.13.1:2.13.1 +google-cloud-spanner-jdbc:2.13.1:2.13.2-SNAPSHOT From c4c492576d3e6c192a1855e8d6b3474bb2ad0c22 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 23 Sep 2023 07:38:06 +0200 Subject: [PATCH 100/173] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.16.0 (#1358) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f16371b5d..9e42da0ec 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.15.0 + 3.16.0 pom import From 70af99e96451fb0158abb45580eaae09ad0b6210 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 23 Sep 2023 07:38:39 +0200 Subject: [PATCH 101/173] deps: update dependency com.spotify.fmt:fmt-maven-plugin to v2.21.1 (#1359) --- samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index d9bf6c92a..576c13c23 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -88,7 +88,7 @@ com.spotify.fmt fmt-maven-plugin - 2.20 + 2.21.1 From d27cd0acf76d8e338a405d9cd406eaf18c84d8c6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 23 Sep 2023 09:02:13 +0200 Subject: [PATCH 102/173] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.13.1 (#1357) 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.13.0` -> `2.13.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.13.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-jdbc/2.13.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-jdbc/2.13.0/2.13.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-jdbc/2.13.0/2.13.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes

googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.13.1`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2131-2023-09-21) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.13.0...v2.13.1) ##### Dependencies - Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.1.4 ([#​1353](https://togithub.com/googleapis/java-spanner-jdbc/issues/1353)) ([88cd905](https://togithub.com/googleapis/java-spanner-jdbc/commit/88cd905bece9c8da7f26b637392e35ab2536edeb))
--- ### 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 +- samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 2cf650a89..ed2d67e79 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.13.0 + 2.13.1 diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 576c13c23..557270816 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -48,7 +48,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.0 + 2.13.1 org.postgresql From f2542d46c7b105b43d2ccb2db2b305196b8a898f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 25 Sep 2023 07:03:36 +0200 Subject: [PATCH 103/173] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.1 (#1362) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9e42da0ec..b69c474d7 100644 --- a/pom.xml +++ b/pom.xml @@ -256,7 +256,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.1 From d574dbb761fa7d0a7d1977844b48b8e4904f1bb0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 08:47:49 +0200 Subject: [PATCH 104/173] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.16.1 (#1363) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b69c474d7..0424a311b 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.16.0 + 3.16.1 pom import From 2b85f842fa56521f194e4e13cd2b7a674f6ac01c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 08:14:17 +0000 Subject: [PATCH 105/173] chore(main): release 2.13.2 (#1360) :robot: I have created a release *beep* *boop* --- ## [2.13.2](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.13.1...v2.13.2) (2023-09-26) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.16.0 ([#1358](https://togithub.com/googleapis/java-spanner-jdbc/issues/1358)) ([c4c4925](https://togithub.com/googleapis/java-spanner-jdbc/commit/c4c492576d3e6c192a1855e8d6b3474bb2ad0c22)) * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.16.1 ([#1363](https://togithub.com/googleapis/java-spanner-jdbc/issues/1363)) ([d574dbb](https://togithub.com/googleapis/java-spanner-jdbc/commit/d574dbb761fa7d0a7d1977844b48b8e4904f1bb0)) * Update dependency com.spotify.fmt:fmt-maven-plugin to v2.21.1 ([#1359](https://togithub.com/googleapis/java-spanner-jdbc/issues/1359)) ([70af99e](https://togithub.com/googleapis/java-spanner-jdbc/commit/70af99e96451fb0158abb45580eaae09ad0b6210)) --- 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 | 9 +++++++++ pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- versions.txt | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b73e9670..659f4d353 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [2.13.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.13.1...v2.13.2) (2023-09-26) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.16.0 ([#1358](https://github.com/googleapis/java-spanner-jdbc/issues/1358)) ([c4c4925](https://github.com/googleapis/java-spanner-jdbc/commit/c4c492576d3e6c192a1855e8d6b3474bb2ad0c22)) +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.16.1 ([#1363](https://github.com/googleapis/java-spanner-jdbc/issues/1363)) ([d574dbb](https://github.com/googleapis/java-spanner-jdbc/commit/d574dbb761fa7d0a7d1977844b48b8e4904f1bb0)) +* Update dependency com.spotify.fmt:fmt-maven-plugin to v2.21.1 ([#1359](https://github.com/googleapis/java-spanner-jdbc/issues/1359)) ([70af99e](https://github.com/googleapis/java-spanner-jdbc/commit/70af99e96451fb0158abb45580eaae09ad0b6210)) + ## [2.13.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.13.0...v2.13.1) (2023-09-21) diff --git a/pom.xml b/pom.xml index 0424a311b..8ea55af4b 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.13.2-SNAPSHOT + 2.13.2 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 c60583de4..038e5e0d3 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.2-SNAPSHOT + 2.13.2 diff --git a/versions.txt b/versions.txt index 993752b80..fc35a6a01 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.13.1:2.13.2-SNAPSHOT +google-cloud-spanner-jdbc:2.13.2:2.13.2 From f0153614998209d387539f85c88bef9f865908b5 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 09:36:17 +0000 Subject: [PATCH 106/173] chore(main): release 2.13.3-SNAPSHOT (#1364) :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 8ea55af4b..ee49db7d9 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.13.2 + 2.13.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 038e5e0d3..ec9a8dd95 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.2 + 2.13.3-SNAPSHOT diff --git a/versions.txt b/versions.txt index fc35a6a01..094a46df1 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.13.2:2.13.2 +google-cloud-spanner-jdbc:2.13.2:2.13.3-SNAPSHOT From ce52d07c308bcde0ed1b0c9f4d3556db2590f722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 26 Sep 2023 14:45:03 +0200 Subject: [PATCH 107/173] docs: add sample for Spring Data MyBatis (#1352) * docs: add sample for Spring Data MyBatis Adds a sample application for using Spring Data and MyBatis with the Cloud Spanner JDBC driver and a PostgreSQL-dialect database. * chore: update sample database name --- samples/spring-data-mybatis/README.md | 93 ++ samples/spring-data-mybatis/pom.xml | 112 +++ .../cloud/spanner/sample/Application.java | 133 +++ .../cloud/spanner/sample/DatabaseSeeder.java | 342 +++++++ .../spanner/sample/JdbcConfiguration.java | 70 ++ .../sample/entities/AbstractEntity.java | 73 ++ .../cloud/spanner/sample/entities/Album.java | 84 ++ .../spanner/sample/entities/Concert.java | 78 ++ .../cloud/spanner/sample/entities/Singer.java | 73 ++ .../cloud/spanner/sample/entities/Track.java | 66 ++ .../cloud/spanner/sample/entities/Venue.java | 43 + .../spanner/sample/mappers/AlbumMapper.java | 48 + .../spanner/sample/mappers/ConcertMapper.java | 29 + .../spanner/sample/mappers/SingerMapper.java | 59 ++ .../spanner/sample/mappers/TrackMapper.java | 37 + .../spanner/sample/mappers/VenueMapper.java | 29 + .../spanner/sample/service/AlbumService.java | 49 + .../spanner/sample/service/SingerService.java | 67 ++ .../main/resources/application-cs.properties | 9 + .../main/resources/application-pg.properties | 7 + .../src/main/resources/application.properties | 13 + .../src/main/resources/create_schema.sql | 68 ++ .../src/main/resources/drop_schema.sql | 5 + .../cloud/spanner/sample/ApplicationTest.java | 879 ++++++++++++++++++ .../test/resources/application-cs.properties | 9 + .../test/resources/application-pg.properties | 7 + .../src/test/resources/application.properties | 13 + 27 files changed, 2495 insertions(+) create mode 100644 samples/spring-data-mybatis/README.md create mode 100644 samples/spring-data-mybatis/pom.xml create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/Application.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Album.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Track.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java create mode 100644 samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java create mode 100644 samples/spring-data-mybatis/src/main/resources/application-cs.properties create mode 100644 samples/spring-data-mybatis/src/main/resources/application-pg.properties create mode 100644 samples/spring-data-mybatis/src/main/resources/application.properties create mode 100644 samples/spring-data-mybatis/src/main/resources/create_schema.sql create mode 100644 samples/spring-data-mybatis/src/main/resources/drop_schema.sql create mode 100644 samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java create mode 100644 samples/spring-data-mybatis/src/test/resources/application-cs.properties create mode 100644 samples/spring-data-mybatis/src/test/resources/application-pg.properties create mode 100644 samples/spring-data-mybatis/src/test/resources/application.properties diff --git a/samples/spring-data-mybatis/README.md b/samples/spring-data-mybatis/README.md new file mode 100644 index 000000000..02cf135d4 --- /dev/null +++ b/samples/spring-data-mybatis/README.md @@ -0,0 +1,93 @@ +# Spring Data MyBatis Sample Application with Cloud Spanner PostgreSQL + +This sample application shows how to develop portable applications using Spring Data MyBatis 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 MyBatis 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 MyBatis 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. + +## MyBatis Spring +[MyBatis Spring](http://mybatis.org/spring/) integrates MyBatis with the popular Java Spring +framework. This allows MyBatis to participate in Spring transactions and to automatically inject +MyBatis mappers into other beans. + +## Sample Application + +This sample shows how to create a portable application using Spring Data MyBatis 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): + This utility class is used to determine whether the application is running on Cloud Spanner + PostgreSQL or open-source PostgreSQL. This can be used if you have specific features that should + only be executed on one of the two systems. +* [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. +* [SingerService](src/main/java/com/google/cloud/spanner/sample/service/SingerService.java) and + [AlbumService](src/main/java/com/google/cloud/spanner/sample/service/SingerService.java) are + standard Spring service beans that contain business logic that can be executed as transactions. + This includes both read/write and read-only transactions. diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml new file mode 100644 index 000000000..2d9de56fb --- /dev/null +++ b/samples/spring-data-mybatis/pom.xml @@ -0,0 +1,112 @@ + + + 4.0.0 + + org.example + cloud-spanner-spring-data-mybatis-example + 1.0-SNAPSHOT + + Sample application showing how to use Spring Data MyBatis with Cloud Spanner PostgreSQL. + + + org.springframework.boot + spring-boot-starter-parent + 3.1.3 + + + + 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.mybatis.spring.boot + mybatis-spring-boot-starter + 3.0.2 + + + org.mybatis.dynamic-sql + mybatis-dynamic-sql + 1.5.0 + + + + + com.google.cloud + google-cloud-spanner-jdbc + 2.12.1 + + + 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-mybatis/src/main/java/com/google/cloud/spanner/sample/Application.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/Application.java new file mode 100644 index 000000000..04286b5a9 --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/Application.java @@ -0,0 +1,133 @@ +/* + * 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.mappers.AlbumMapper; +import com.google.cloud.spanner.sample.mappers.SingerMapper; +import com.google.cloud.spanner.sample.service.AlbumService; +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 AlbumService albumService; + + private final SingerMapper singerMapper; + + private final AlbumMapper albumMapper; + + public Application( + SingerService singerService, + AlbumService albumService, + DatabaseSeeder databaseSeeder, + SingerMapper singerMapper, + AlbumMapper albumMapper) { + this.databaseSeeder = databaseSeeder; + this.singerService = singerService; + this.albumService = albumService; + this.singerMapper = singerMapper; + this.albumMapper = albumMapper; + } + + @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 = singerMapper.findAll(); + for (Singer singer : allSingers) { + logger.info( + "Found singer: {} with {} albums", + singer, + albumMapper.countAlbumsBySingerId(singer.getId())); + for (Album album : albumMapper.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 Album and some Tracks in a read/write transaction. + // Track is an interleaved table. + Album album = new Album(DatabaseSeeder.randomTitle()); + album.setSingerId(insertedSinger.getId()); + albumService.createAlbumAndTracks( + album, + new Track(album, 1, DatabaseSeeder.randomTitle(), 3.14d), + new Track(album, 2, DatabaseSeeder.randomTitle(), 3.14d), + new Track(album, 3, DatabaseSeeder.randomTitle(), 3.14d), + new Track(album, 4, DatabaseSeeder.randomTitle(), 3.14d), + new Track(album, 5, DatabaseSeeder.randomTitle(), 3.14d), + new Track(album, 6, DatabaseSeeder.randomTitle(), 3.14d), + new Track(album, 7, DatabaseSeeder.randomTitle(), 3.14d)); + logger.info("Inserted album {}", album.getTitle()); + + // 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 : singerMapper.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-mybatis/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java new file mode 100644 index 000000000..eabd04c3b --- /dev/null +++ b/samples/spring-data-mybatis/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-mybatis/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java new file mode 100644 index 000000000..2398add31 --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java @@ -0,0 +1,70 @@ +/* + * 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 org.springframework.context.annotation.Configuration; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.IncorrectResultSizeDataAccessException; +import org.springframework.jdbc.core.JdbcOperations; + +@Configuration +public class JdbcConfiguration { + + /** 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.getCause(); + 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-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java new file mode 100644 index 000000000..2dbffd0e7 --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.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 java.time.OffsetDateTime; + +public abstract class AbstractEntity { + + /** This ID is generated using a (bit-reversed) sequence. */ + 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; + } + + public 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-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Album.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Album.java new file mode 100644 index 000000000..57df330bf --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Album.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 java.math.BigDecimal; +import java.time.LocalDate; + +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-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java new file mode 100644 index 000000000..fa219b16d --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java @@ -0,0 +1,78 @@ +/* + * 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; + +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-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java new file mode 100644 index 000000000..90dc0e1e0 --- /dev/null +++ b/samples/spring-data-mybatis/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; + +public class Singer extends AbstractEntity { + + private String firstName; + + private String lastName; + + /** The full name is generated by the database using a generated column. */ + 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 void setFullName(String fullName) { + this.fullName = fullName; + } + + public Boolean getActive() { + return active; + } + + public void setActive(Boolean active) { + this.active = active; + } +} diff --git a/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Track.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Track.java new file mode 100644 index 000000000..51fb756c9 --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Track.java @@ -0,0 +1,66 @@ +/* + * 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; + +/** + * 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. + */ +public class Track extends AbstractEntity { + + /** + * This is the second part of the primary key of a Track. The first part, the 'id' column is + * defined in the {@link AbstractEntity} super class. + */ + private int trackNumber; + + private String title; + + private Double sampleRate; + + public Track(Album album, int trackNumber, String title, Double sampleRate) { + setId(album.getId()); + this.trackNumber = trackNumber; + this.title = title; + this.sampleRate = sampleRate; + } + + 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-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java new file mode 100644 index 000000000..ff7ee5049 --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java @@ -0,0 +1,43 @@ +/* + * 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; + +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-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java new file mode 100644 index 000000000..85a05f28e --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java @@ -0,0 +1,48 @@ +/* + * 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.mappers; + +import com.google.cloud.spanner.sample.entities.Album; +import java.util.List; +import java.util.Optional; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Options; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +@Mapper +public interface AlbumMapper { + + @Select("SELECT * FROM albums WHERE id = #{albumId}") + Album get(@Param("albumId") long albumId); + + @Select("SELECT * FROM albums LIMIT 1") + Optional getFirst(); + + @Select("SELECT COUNT(1) FROM albums WHERE singer_id = #{singerId}") + long countAlbumsBySingerId(@Param("singerId") long singerId); + + @Select("SELECT * FROM albums WHERE singer_id = #{singerId}") + List findAlbumsBySingerId(@Param("singerId") long singerId); + + @Insert( + "INSERT INTO albums (title, marketing_budget, release_date, cover_picture, singer_id) " + + "VALUES (#{title}, #{marketingBudget}, #{releaseDate}, #{coverPicture}, #{singerId})") + @Options(useGeneratedKeys = true, keyProperty = "id") + int insert(Album album); +} diff --git a/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java new file mode 100644 index 000000000..d268b4327 --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java @@ -0,0 +1,29 @@ +/* + * 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.mappers; + +import com.google.cloud.spanner.sample.entities.Venue; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +@Mapper +public interface ConcertMapper { + + @Select("SELECT * FROM concerts WHERE id = #{concertId}") + Venue get(@Param("concertId") long concertId); +} diff --git a/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java new file mode 100644 index 000000000..7f55466fe --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java @@ -0,0 +1,59 @@ +/* + * 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.mappers; + +import com.google.cloud.spanner.sample.entities.Singer; +import java.util.List; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Options; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; + +@Mapper +public interface SingerMapper { + + @Select("SELECT * FROM singers WHERE id = #{singerId}") + Singer get(@Param("singerId") long singerId); + + @Select("SELECT * FROM singers ORDER BY last_name, first_name, id") + List findAll(); + + @Select("SELECT * FROM singers WHERE starts_with(last_name, #{lastName})") + List findSingersByLastNameStartingWith(@Param("lastName") String lastName); + + /** + * Inserts a new singer record and returns both the generated primary key value and the generated + * full name. + */ + @Insert( + "INSERT INTO singers (first_name, last_name, active) " + + "VALUES (#{firstName}, #{lastName}, #{active})") + @Options(useGeneratedKeys = true, keyProperty = "id,fullName") + int insert(Singer singer); + + /** Updates an existing singer and returns the generated full name. */ + @Update( + "UPDATE singers SET " + + "first_name=#{first_name}, " + + "last_name=#{last_name}, " + + "active=#{active} " + + "WHERE id=#{id}") + @Options(useGeneratedKeys = true, keyProperty = "fullName") + int update(Singer singer); +} diff --git a/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java new file mode 100644 index 000000000..5972e2711 --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java @@ -0,0 +1,37 @@ +/* + * 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.mappers; + +import com.google.cloud.spanner.sample.entities.Track; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Options; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +@Mapper +public interface TrackMapper { + + @Select("SELECT * FROM tracks WHERE id = #{albumId} AND track_number = #{trackNumber}") + Track get(@Param("albumId") long albumId, @Param("trackNumber") long trackNumber); + + @Insert( + "INSERT INTO tracks (id, track_number, title, sample_rate) " + + "VALUES (#{id}, #{trackNumber}, #{title}, #{sampleRate})") + @Options(useGeneratedKeys = true, keyProperty = "id") + int insert(Track track); +} diff --git a/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java new file mode 100644 index 000000000..ab81c45cd --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java @@ -0,0 +1,29 @@ +/* + * 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.mappers; + +import com.google.cloud.spanner.sample.entities.Venue; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +@Mapper +public interface VenueMapper { + + @Select("SELECT * FROM venues WHERE id = #{venueId}") + Venue get(@Param("venueId") long venueId); +} diff --git a/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java new file mode 100644 index 000000000..4e326a47c --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java @@ -0,0 +1,49 @@ +/* + * 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.service; + +import com.google.cloud.spanner.sample.entities.Album; +import com.google.cloud.spanner.sample.entities.Track; +import com.google.cloud.spanner.sample.mappers.AlbumMapper; +import com.google.cloud.spanner.sample.mappers.TrackMapper; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class AlbumService { + private final AlbumMapper albumMapper; + + private final TrackMapper trackMapper; + + public AlbumService(AlbumMapper albumMapper, TrackMapper trackMapper) { + this.albumMapper = albumMapper; + this.trackMapper = trackMapper; + } + + /** Creates an album and a set of tracks in a read/write transaction. */ + @Transactional + public Album createAlbumAndTracks(Album album, Track... tracks) { + // Saving an album will update the album entity with the generated primary key. + albumMapper.insert(album); + for (Track track : tracks) { + // Set the id that was generated on the Album before saving it. + track.setId(album.getId()); + trackMapper.insert(track); + } + return album; + } +} diff --git a/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java new file mode 100644 index 000000000..6298bb63e --- /dev/null +++ b/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java @@ -0,0 +1,67 @@ +/* + * 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.service; + +import com.google.cloud.spanner.sample.entities.Album; +import com.google.cloud.spanner.sample.entities.Singer; +import com.google.cloud.spanner.sample.mappers.AlbumMapper; +import com.google.cloud.spanner.sample.mappers.SingerMapper; +import com.google.common.collect.ImmutableList; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SingerService { + private final SingerMapper singerRepository; + + private final AlbumMapper albumRepository; + + public SingerService(SingerMapper singerRepository, AlbumMapper albumRepository) { + this.singerRepository = singerRepository; + this.albumRepository = albumRepository; + } + + /** Creates a singer and a list of albums in a read/write transaction. */ + @Transactional + public Singer createSingerAndAlbums(Singer singer, Album... albums) { + // Saving a singer will update the singer entity with the generated primary key. + singerRepository.insert(singer); + for (Album album : albums) { + // Set the singerId that was generated on the Album before saving it. + album.setSingerId(singer.getId()); + albumRepository.insert(album); + } + return singer; + } + + /** + * Searches for all singers that have a last name starting with any of the given prefixes. This + * method uses a read-only transaction. Read-only transactions should be preferred to read/write + * transactions whenever possible, as read-only transactions do not take locks. + */ + @Transactional(readOnly = true) + public List listSingersWithLastNameStartingWith(String... prefixes) { + ImmutableList.Builder result = ImmutableList.builder(); + // This is not the most efficient way to search for this, but the main purpose of this method is + // to show how to use read-only transactions. + for (String prefix : prefixes) { + result.addAll(singerRepository.findSingersByLastNameStartingWith(prefix)); + } + return result.build(); + } +} diff --git a/samples/spring-data-mybatis/src/main/resources/application-cs.properties b/samples/spring-data-mybatis/src/main/resources/application-cs.properties new file mode 100644 index 000000000..cf70836d2 --- /dev/null +++ b/samples/spring-data-mybatis/src/main/resources/application-cs.properties @@ -0,0 +1,9 @@ + +# This profile uses a Cloud Spanner PostgreSQL database. + +spanner.project=my-project +spanner.instance=my-instance +spanner.database=mybatis-sample + +spring.datasource.url=jdbc:cloudspanner:/projects/${spanner.project}/instances/${spanner.instance}/databases/${spanner.database} +spring.datasource.driver-class-name=com.google.cloud.spanner.jdbc.JdbcDriver diff --git a/samples/spring-data-mybatis/src/main/resources/application-pg.properties b/samples/spring-data-mybatis/src/main/resources/application-pg.properties new file mode 100644 index 000000000..0605cd3ab --- /dev/null +++ b/samples/spring-data-mybatis/src/main/resources/application-pg.properties @@ -0,0 +1,7 @@ + +# This profile uses an open-source PostgreSQL database. + +spring.datasource.url=jdbc:postgresql://localhost:5432/mybatis-sample +spring.datasource.driver-class-name=org.postgresql.Driver +spring.datasource.username=postgres +spring.datasource.password=mysecretpassword diff --git a/samples/spring-data-mybatis/src/main/resources/application.properties b/samples/spring-data-mybatis/src/main/resources/application.properties new file mode 100644 index 000000000..a6900a8ef --- /dev/null +++ b/samples/spring-data-mybatis/src/main/resources/application.properties @@ -0,0 +1,13 @@ + +# This application can use both a Cloud Spanner PostgreSQL database or an open-source PostgreSQL +# database. Which database is used is determined by the active profile: +# 1. 'cs' means use Cloud Spanner. +# 2. 'pg' means use open-source PostgreSQL. + +# Activate the Cloud Spanner profile by default. +# Change to 'pg' to activate the PostgreSQL profile. +spring.profiles.default=cs + +# Map column names with an underscore to property names in camel case. +# E.g. column 'full_name' maps to Java property 'fullName'. +mybatis.configuration.map-underscore-to-camel-case=true diff --git a/samples/spring-data-mybatis/src/main/resources/create_schema.sql b/samples/spring-data-mybatis/src/main/resources/create_schema.sql new file mode 100644 index 000000000..60552d3ad --- /dev/null +++ b/samples/spring-data-mybatis/src/main/resources/create_schema.sql @@ -0,0 +1,68 @@ +/* + This script creates the database schema for this sample application. + All lines that start with /* skip_on_open_source_pg */ are skipped when the application is running on a + normal PostgreSQL database. The same lines are executed when the application is running on a Cloud + Spanner database. The script is executed by the DatabaseSeeder class. +*/ + +create sequence if not exists id_generator +/* skip_on_open_source_pg */ bit_reversed_positive +; + +create table if not exists singers ( + id bigint not null primary key default nextval('id_generator'), + first_name varchar, + last_name varchar, + full_name varchar generated always as (CASE WHEN first_name IS NULL THEN last_name + WHEN last_name IS NULL THEN first_name + ELSE first_name || ' ' || last_name END) stored, + active boolean default true, + created_at timestamptz default current_timestamp, + updated_at timestamptz default current_timestamp +); + +create table if not exists albums ( + id bigint not null primary key default nextval('id_generator'), + title varchar not null, + marketing_budget numeric, + release_date date, + cover_picture bytea, + singer_id bigint not null, + created_at timestamptz default current_timestamp, + updated_at timestamptz default current_timestamp, + constraint fk_albums_singers foreign key (singer_id) references singers (id) +); + +create table if not exists tracks ( + id bigint not null, + track_number bigint not null, + title varchar not null, + sample_rate float8 not null, + created_at timestamptz default current_timestamp, + updated_at timestamptz default current_timestamp, + primary key (id, track_number) +) +/* skip_on_open_source_pg */ interleave in parent albums on delete cascade +; + +create table if not exists venues ( + id bigint not null primary key default nextval('id_generator'), + name varchar not null, + description jsonb not null, + created_at timestamptz default current_timestamp, + updated_at timestamptz default current_timestamp +); + +create table if not exists concerts ( + id bigint not null primary key default nextval('id_generator'), + venue_id bigint not null, + singer_id bigint not null, + name varchar not null, + start_time timestamptz not null, + end_time timestamptz not null, + created_at timestamptz default current_timestamp, + updated_at timestamptz default current_timestamp, + constraint fk_concerts_venues foreign key (venue_id) references venues (id), + constraint fk_concerts_singers foreign key (singer_id) references singers (id), + constraint chk_end_time_after_start_time check (end_time > start_time) +); diff --git a/samples/spring-data-mybatis/src/main/resources/drop_schema.sql b/samples/spring-data-mybatis/src/main/resources/drop_schema.sql new file mode 100644 index 000000000..23e7b65d3 --- /dev/null +++ b/samples/spring-data-mybatis/src/main/resources/drop_schema.sql @@ -0,0 +1,5 @@ +drop table if exists concerts; +drop table if exists venues; +drop table if exists tracks; +drop table if exists albums; +drop table if exists singers; diff --git a/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java b/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java new file mode 100644 index 000000000..677e086ec --- /dev/null +++ b/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java @@ -0,0 +1,879 @@ +/* + * 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 com.google.cloud.spanner.sample.DatabaseSeeder.INITIAL_SINGERS; +import static com.google.cloud.spanner.sample.DatabaseSeeder.randomDate; +import static com.google.cloud.spanner.sample.DatabaseSeeder.randomTitle; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertNotEquals; + +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.sample.entities.Singer; +import com.google.common.collect.Streams; +import com.google.longrunning.Operation; +import com.google.protobuf.Any; +import com.google.protobuf.Empty; +import com.google.protobuf.ListValue; +import com.google.protobuf.NullValue; +import com.google.protobuf.Value; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import com.google.spanner.v1.BeginTransactionRequest; +import com.google.spanner.v1.CommitRequest; +import com.google.spanner.v1.ExecuteBatchDmlRequest; +import com.google.spanner.v1.ExecuteSqlRequest; +import com.google.spanner.v1.ResultSet; +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.TypeAnnotationCode; +import com.google.spanner.v1.TypeCode; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.springframework.boot.SpringApplication; + +@RunWith(JUnit4.class) +public class ApplicationTest extends AbstractMockServerTest { + + @BeforeClass + public static void setupQueryResults() { + // Set the database dialect. + mockSpanner.putStatementResult(StatementResult.detectDialectResult(Dialect.POSTGRESQL)); + // Set up a result for the dialect check that is executed by the JdbcConfiguration class. + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of( + "select 1 " + + "from information_schema.database_options " + + "where schema_name='public' " + + "and option_name='database_dialect' " + + "and option_value='POSTGRESQL'"), + ResultSet.newBuilder() + .setMetadata( + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("c") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("1").build()) + .build()) + .build())); + // Add a DDL response to the server. + addDdlResponseToSpannerAdmin(); + + // Set up results for the 'delete all test data' operations. + mockSpanner.putStatementResult( + StatementResult.update(Statement.of("delete from concerts"), 0L)); + mockSpanner.putStatementResult(StatementResult.update(Statement.of("delete from venues"), 0L)); + mockSpanner.putStatementResult(StatementResult.update(Statement.of("delete from tracks"), 0L)); + mockSpanner.putStatementResult(StatementResult.update(Statement.of("delete from albums"), 0L)); + mockSpanner.putStatementResult(StatementResult.update(Statement.of("delete from singers"), 0L)); + + // Set up results for inserting test data. + for (Singer singer : INITIAL_SINGERS) { + mockSpanner.putStatementResult( + StatementResult.update( + Statement.newBuilder("insert into singers (first_name, last_name) values ($1, $2)") + .bind("p1") + .to(singer.getFirstName()) + .bind("p2") + .to(singer.getLastName()) + .build(), + 1L)); + } + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of("select id from singers"), + ResultSet.newBuilder() + .setMetadata( + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("id") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .build()) + .build()) + .addAllRows( + LongStream.rangeClosed(1L, INITIAL_SINGERS.size()) + .mapToObj( + id -> + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue(String.valueOf(Long.reverse(id))) + .build()) + .build()) + .collect(Collectors.toList())) + .build())); + mockSpanner.putPartialStatementResult( + StatementResult.update( + Statement.of( + "insert into albums (title, marketing_budget, release_date, cover_picture, singer_id) values ($1, $2, $3, $4, $5)"), + 1L)); + + // Set up results for the queries that the application runs. + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of("SELECT * FROM singers ORDER BY last_name, first_name, id"), + 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("active") + .setType(Type.newBuilder().setCode(TypeCode.BOOL).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("last_name") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("full_name") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("first_name") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .build()) + .build()) + .addAllRows( + Streams.mapWithIndex( + INITIAL_SINGERS.stream(), + (singer, index) -> + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue(String.valueOf(Long.reverse(index + 1))) + .build()) + .addValues(Value.newBuilder().setBoolValue(true).build()) + .addValues( + Value.newBuilder() + .setStringValue(singer.getLastName()) + .build()) + .addValues( + Value.newBuilder() + .setStringValue( + singer.getFirstName() + " " + singer.getLastName()) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setStringValue(singer.getFirstName()) + .build()) + .build()) + .collect(Collectors.toList())) + .build())); + mockSpanner.putPartialStatementResult( + StatementResult.query( + Statement.of("SELECT COUNT(1) FROM albums WHERE singer_id = $1"), + ResultSet.newBuilder() + .setMetadata( + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("c") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("10").build()) + .build()) + .build())); + for (long singerId : LongStream.rangeClosed(1L, INITIAL_SINGERS.size()).toArray()) { + mockSpanner.putStatementResult( + StatementResult.query( + Statement.newBuilder("SELECT * FROM albums WHERE singer_id = $1") + .bind("p1") + .to(Long.reverse(singerId)) + .build(), + 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("title") + .setType( + Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("singer_id") + .setType( + Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("release_date") + .setType(Type.newBuilder().setCode(TypeCode.DATE).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("cover_picture") + .setType( + Type.newBuilder().setCode(TypeCode.BYTES).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("marketing_budget") + .setType( + Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation(TypeAnnotationCode.PG_NUMERIC) + .build()) + .build()) + .build()) + .build()) + .addAllRows( + IntStream.rangeClosed(1, 10) + .mapToObj( + albumId -> + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue( + String.valueOf(Long.reverse(albumId * singerId))) + .build()) + .addValues(Value.newBuilder().setStringValue(randomTitle())) + .addValues( + Value.newBuilder() + .setStringValue( + String.valueOf(Long.reverse(singerId)))) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setStringValue(randomDate().toString()) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .build()) + .collect(Collectors.toList())) + .build())); + } + mockSpanner.putStatementResult( + StatementResult.query( + Statement.newBuilder( + "INSERT INTO singers (first_name, last_name, active) VALUES ($1, $2, $3)\n" + + "RETURNING *") + .bind("p1") + .to("Amethyst") + .bind("p2") + .to("Jiang") + .bind("p3") + .to((com.google.cloud.spanner.Value) null) + .build(), + 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("active") + .setType(Type.newBuilder().setCode(TypeCode.BOOL).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("last_name") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("full_name") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("first_name") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue( + String.valueOf(Long.reverse(INITIAL_SINGERS.size() + 2))) + .build()) + .addValues(Value.newBuilder().setBoolValue(true).build()) + .addValues(Value.newBuilder().setStringValue("Amethyst").build()) + .addValues(Value.newBuilder().setStringValue("Amethyst Jiang").build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setStringValue("Jiang").build()) + .build()) + .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) + .build())); + mockSpanner.putPartialStatementResult( + StatementResult.query( + Statement.of( + "INSERT INTO albums (title, marketing_budget, release_date, cover_picture, singer_id) VALUES ($1, $2, $3, $4, $5)\n" + + "RETURNING *"), + 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("title") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("singer_id") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("release_date") + .setType(Type.newBuilder().setCode(TypeCode.DATE).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("cover_picture") + .setType(Type.newBuilder().setCode(TypeCode.BYTES).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("marketing_budget") + .setType( + Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation(TypeAnnotationCode.PG_NUMERIC) + .build()) + .build()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue(String.valueOf(Long.reverse(1L))) + .build()) + .addValues(Value.newBuilder().setStringValue(randomTitle())) + .addValues(Value.newBuilder().setStringValue(String.valueOf(1L))) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues( + Value.newBuilder().setStringValue(randomDate().toString()).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .build()) + .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) + .build())); + mockSpanner.putPartialStatementResult( + StatementResult.query( + Statement.of( + "INSERT INTO tracks (id, track_number, title, sample_rate) VALUES ($1, $2, $3, $4)\n" + + "RETURNING *"), + 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("track_number") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("title") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("sample_rate") + .setType( + Type.newBuilder().setCode(TypeCode.FLOAT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue(String.valueOf(Long.reverse(1L))) + .build()) + .addValues(Value.newBuilder().setStringValue("1").build()) + .addValues(Value.newBuilder().setStringValue(randomTitle())) + .addValues(Value.newBuilder().setNumberValue(3.14d)) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .build()) + .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) + .build())); + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of("select * from albums limit 1"), + 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("title") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("singer_id") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("release_date") + .setType(Type.newBuilder().setCode(TypeCode.DATE).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("cover_picture") + .setType(Type.newBuilder().setCode(TypeCode.BYTES).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("marketing_budget") + .setType( + Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation(TypeAnnotationCode.PG_NUMERIC) + .build()) + .build()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue(String.valueOf(Long.reverse(1L))) + .build()) + .addValues(Value.newBuilder().setStringValue(randomTitle())) + .addValues(Value.newBuilder().setStringValue(String.valueOf(1L))) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues( + Value.newBuilder().setStringValue(randomDate().toString()).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .build()) + .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) + .build())); + for (String prefix : new String[] {"J", "A", "B", "C"}) { + mockSpanner.putStatementResult( + StatementResult.query( + Statement.newBuilder("SELECT * FROM singers WHERE starts_with(last_name, $1)") + .bind("p1") + .to(prefix) + .build(), + 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("active") + .setType(Type.newBuilder().setCode(TypeCode.BOOL).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("last_name") + .setType( + Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("full_name") + .setType( + Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("updated_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("created_at") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("first_name") + .setType( + Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .build()) + .build()) + .addAllRows( + Streams.mapWithIndex( + INITIAL_SINGERS.stream() + .filter( + singer -> + singer.getLastName().startsWith(prefix.substring(0, 1))), + (singer, index) -> + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue( + String.valueOf(Long.reverse(index + 1))) + .build()) + .addValues(Value.newBuilder().setBoolValue(true).build()) + .addValues( + Value.newBuilder() + .setStringValue(singer.getLastName()) + .build()) + .addValues( + Value.newBuilder() + .setStringValue( + singer.getFirstName() + + " " + + singer.getLastName()) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build()) + .addValues( + Value.newBuilder() + .setStringValue(singer.getFirstName()) + .build()) + .build()) + .collect(Collectors.toList())) + .build())); + } + } + + @Test + public void testRunApplication() { + System.setProperty("port", String.valueOf(getPort())); + SpringApplication.run(Application.class).close(); + + assertEquals( + 39, + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(request -> !request.getSql().equals("SELECT 1")) + .count()); + assertEquals(3, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(5, mockSpanner.countRequestsOfType(CommitRequest.class)); + + // Verify that the service methods use transactions. + String insertSingerSql = + "INSERT INTO singers (first_name, last_name, active) VALUES ($1, $2, $3)\nRETURNING *"; + assertEquals( + 1, + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(request -> request.getSql().equals(insertSingerSql)) + .count()); + ExecuteSqlRequest insertSingerRequest = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(request -> request.getSql().equals(insertSingerSql)) + .findFirst() + .orElseThrow(); + assertTrue(insertSingerRequest.hasTransaction()); + assertTrue(insertSingerRequest.getTransaction().hasBegin()); + assertTrue(insertSingerRequest.getTransaction().getBegin().hasReadWrite()); + String insertAlbumSql = + "INSERT INTO albums (title, marketing_budget, release_date, cover_picture, singer_id) " + + "VALUES ($1, $2, $3, $4, $5)\nRETURNING *"; + assertEquals( + 4, + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(request -> request.getSql().equals(insertAlbumSql)) + .count()); + // The first 3 requests belong to the transaction that is executed together with the 'INSERT + // INTO singers' statement. + List insertAlbumRequests = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(request -> request.getSql().equals(insertAlbumSql)) + .toList() + .subList(0, 3); + ExecuteSqlRequest firstInsertAlbumRequest = insertAlbumRequests.get(0); + for (ExecuteSqlRequest request : insertAlbumRequests) { + assertTrue(request.hasTransaction()); + assertTrue(request.getTransaction().hasId()); + assertEquals( + firstInsertAlbumRequest.getTransaction().getId(), request.getTransaction().getId()); + } + // Verify that the transaction is committed. + assertEquals( + 1, + mockSpanner.getRequestsOfType(CommitRequest.class).stream() + .filter( + request -> + request + .getTransactionId() + .equals(firstInsertAlbumRequest.getTransaction().getId())) + .count()); + + // The last 'INSERT INTO albums' request belong in a transaction with 8 'INSERT INTO tracks' + // requests. + ExecuteSqlRequest lastInsertAlbumRequest = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(request -> request.getSql().equals(insertAlbumSql)) + .toList() + .get(3); + assertNotEquals( + lastInsertAlbumRequest.getTransaction().getId(), + firstInsertAlbumRequest.getTransaction().getId()); + assertTrue(lastInsertAlbumRequest.hasTransaction()); + assertTrue(lastInsertAlbumRequest.getTransaction().hasBegin()); + assertTrue(lastInsertAlbumRequest.getTransaction().getBegin().hasReadWrite()); + String insertTrackSql = + "INSERT INTO tracks (id, track_number, title, sample_rate) " + + "VALUES ($1, $2, $3, $4)\nRETURNING *"; + assertEquals( + 7, + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(request -> request.getSql().equals(insertTrackSql)) + .count()); + List insertTrackRequests = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(request -> request.getSql().equals(insertTrackSql)) + .toList(); + for (ExecuteSqlRequest request : insertTrackRequests) { + assertTrue(request.hasTransaction()); + assertTrue(request.getTransaction().hasId()); + assertEquals( + insertTrackRequests.get(0).getTransaction().getId(), request.getTransaction().getId()); + } + // Verify that the transaction is committed. + assertEquals( + 1, + mockSpanner.getRequestsOfType(CommitRequest.class).stream() + .filter( + request -> + request + .getTransactionId() + .equals(insertTrackRequests.get(0).getTransaction().getId())) + .count()); + + // Verify that the SingerService#listSingersWithLastNameStartingWith(..) method uses a read-only + // transaction. + assertEquals( + 1, + mockSpanner.getRequestsOfType(BeginTransactionRequest.class).stream() + .filter(request -> request.getOptions().hasReadOnly()) + .count()); + String selectSingersSql = "SELECT * FROM singers WHERE starts_with(last_name, $1)"; + assertEquals( + 4, + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(request -> request.getSql().equals(selectSingersSql)) + .count()); + List selectSingersRequests = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(request -> request.getSql().equals(selectSingersSql)) + .toList() + .subList(1, 4); + ExecuteSqlRequest firstSelectSingersRequest = selectSingersRequests.get(0); + for (ExecuteSqlRequest request : selectSingersRequests) { + assertTrue(request.hasTransaction()); + assertTrue(request.getTransaction().hasId()); + } + // Verify that the read-only transaction is not committed. + assertEquals( + 0, + mockSpanner.getRequestsOfType(CommitRequest.class).stream() + .filter( + request -> + request + .getTransactionId() + .equals(firstSelectSingersRequest.getTransaction().getId())) + .count()); + } + + private static void addDdlResponseToSpannerAdmin() { + mockDatabaseAdmin.addResponse( + Operation.newBuilder() + .setDone(true) + .setResponse(Any.pack(Empty.getDefaultInstance())) + .setMetadata(Any.pack(UpdateDatabaseDdlMetadata.getDefaultInstance())) + .build()); + } +} diff --git a/samples/spring-data-mybatis/src/test/resources/application-cs.properties b/samples/spring-data-mybatis/src/test/resources/application-cs.properties new file mode 100644 index 000000000..05f7cfa92 --- /dev/null +++ b/samples/spring-data-mybatis/src/test/resources/application-cs.properties @@ -0,0 +1,9 @@ + +# This profile uses a Cloud Spanner PostgreSQL database. + +spanner.project=my-project +spanner.instance=my-instance +spanner.database=spring-data-jdbc + +spring.datasource.url=jdbc:cloudspanner://localhost:${port}/projects/${spanner.project}/instances/${spanner.instance}/databases/${spanner.database}?usePlainText=true +spring.datasource.driver-class-name=com.google.cloud.spanner.jdbc.JdbcDriver diff --git a/samples/spring-data-mybatis/src/test/resources/application-pg.properties b/samples/spring-data-mybatis/src/test/resources/application-pg.properties new file mode 100644 index 000000000..894f63eba --- /dev/null +++ b/samples/spring-data-mybatis/src/test/resources/application-pg.properties @@ -0,0 +1,7 @@ + +# This profile uses an open-source PostgreSQL database. + +spring.datasource.url=jdbc:postgresql://localhost:5432/spring-data-jdbc +spring.datasource.driver-class-name=org.postgresql.Driver +spring.datasource.username=postgres +spring.datasource.password=mysecretpassword diff --git a/samples/spring-data-mybatis/src/test/resources/application.properties b/samples/spring-data-mybatis/src/test/resources/application.properties new file mode 100644 index 000000000..a6900a8ef --- /dev/null +++ b/samples/spring-data-mybatis/src/test/resources/application.properties @@ -0,0 +1,13 @@ + +# This application can use both a Cloud Spanner PostgreSQL database or an open-source PostgreSQL +# database. Which database is used is determined by the active profile: +# 1. 'cs' means use Cloud Spanner. +# 2. 'pg' means use open-source PostgreSQL. + +# Activate the Cloud Spanner profile by default. +# Change to 'pg' to activate the PostgreSQL profile. +spring.profiles.default=cs + +# Map column names with an underscore to property names in camel case. +# E.g. column 'full_name' maps to Java property 'fullName'. +mybatis.configuration.map-underscore-to-camel-case=true From 749d2c3698c900560b6f85247b0a41a85cd55ac8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 16:06:13 +0200 Subject: [PATCH 108/173] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.1.4 (#1366) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot-starter-parent](https://spring.io/projects/spring-boot) ([source](https://togithub.com/spring-projects/spring-boot)) | `3.1.3` -> `3.1.4` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot-starter-parent/3.1.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot-starter-parent/3.1.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot-starter-parent/3.1.3/3.1.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot-starter-parent/3.1.3/3.1.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
spring-projects/spring-boot (org.springframework.boot:spring-boot-starter-parent) ### [`v3.1.4`](https://togithub.com/spring-projects/spring-boot/releases/tag/v3.1.4) [Compare Source](https://togithub.com/spring-projects/spring-boot/compare/v3.1.3...v3.1.4) ##### :star: New Features - Add TWENTY_ONE to JavaVersion enum [#​37364](https://togithub.com/spring-projects/spring-boot/issues/37364) ##### :lady_beetle: Bug Fixes - When SLF4J and Logback are initialized on multiple threads in parallel, startup may fail due to SubstituteLoggerFactory being considered to be a competing LoggerFactory implementation [#​37484](https://togithub.com/spring-projects/spring-boot/issues/37484) - Saml2RelyingPartyAutoConfiguration ignores `sign-request` when `metadata-url` is used [#​37482](https://togithub.com/spring-projects/spring-boot/issues/37482) - Leaking file descriptor / socket within DomainSocket tooling [#​37460](https://togithub.com/spring-projects/spring-boot/issues/37460) - Invalid Accept header produces HTTP 500 in WelcomePageHandlerMapping [#​37457](https://togithub.com/spring-projects/spring-boot/issues/37457) - PrivateKeyParser doesn't support ed448, XDH and RSA-PSS keys [#​37422](https://togithub.com/spring-projects/spring-boot/issues/37422) - "languageVersion is final and cannot be changed" when using Gradle 8.3 and configuring the Java toolchain's language version [#​37380](https://togithub.com/spring-projects/spring-boot/issues/37380) - AOT processing fails when a `@ConfigurationProperties-annotated` record has multiple constructors [#​37336](https://togithub.com/spring-projects/spring-boot/issues/37336) - Spring Boot dependency management not working for ehcache when using Gradle and the dependency management plugin [#​37270](https://togithub.com/spring-projects/spring-boot/issues/37270) - SslStoreBundle implementations aren't immutable [#​37222](https://togithub.com/spring-projects/spring-boot/issues/37222) - Parsing OCI image names that are invalid due to the use of upper case letters is very slow [#​37183](https://togithub.com/spring-projects/spring-boot/issues/37183) - Producing and consuming different tracing propagation formats doesn't work [#​37178](https://togithub.com/spring-projects/spring-boot/issues/37178) - Using https with elliptic curves other than secp384r1 fails [#​37169](https://togithub.com/spring-projects/spring-boot/issues/37169) - In 3.0.x and later, Spring Security cannot be used to secure a WebSocket upgrade request when using Jetty [#​37158](https://togithub.com/spring-projects/spring-boot/issues/37158) - Local baggage is propagated when using Brave and W3C [#​37156](https://togithub.com/spring-projects/spring-boot/issues/37156) - ServiceConnectionContextCustomizer can trigger docker usage during AOT processing [#​37097](https://togithub.com/spring-projects/spring-boot/issues/37097) - java.lang.OutOfMemoryError: Metaspace when repeatedly deploying and undeploying a Spring Boot web application multiple times in Tomcat [#​37096](https://togithub.com/spring-projects/spring-boot/issues/37096) - Property 'logging.threshold.console' not working [#​36741](https://togithub.com/spring-projects/spring-boot/issues/36741) ##### :notebook_with_decorative_cover: Documentation - Document that PKCS8 PEM files should be used whenever possible [#​37443](https://togithub.com/spring-projects/spring-boot/issues/37443) - Add reference to Oracle Spring Boot Starters [#​37411](https://togithub.com/spring-projects/spring-boot/issues/37411) - Correct the description of spring.artemis.broker-url [#​37309](https://togithub.com/spring-projects/spring-boot/issues/37309) - Add default value metadata for management.metrics.export.signalfx.published-histogram-type [#​37253](https://togithub.com/spring-projects/spring-boot/issues/37253) - Polish javadoc [#​37143](https://togithub.com/spring-projects/spring-boot/issues/37143) ##### :hammer: Dependency Upgrades - Upgrade to Byte Buddy 1.14.8 [#​37419](https://togithub.com/spring-projects/spring-boot/issues/37419) - Upgrade to Couchbase Client 3.4.10 [#​37297](https://togithub.com/spring-projects/spring-boot/issues/37297) - Upgrade to Groovy 4.0.15 [#​37386](https://togithub.com/spring-projects/spring-boot/issues/37386) - Upgrade to Hibernate 6.2.9.Final [#​37465](https://togithub.com/spring-projects/spring-boot/issues/37465) - Upgrade to Infinispan 14.0.17.Final [#​37299](https://togithub.com/spring-projects/spring-boot/issues/37299) - Upgrade to Jakarta XML Bind 4.0.1 [#​37387](https://togithub.com/spring-projects/spring-boot/issues/37387) - Upgrade to Jetty 11.0.16 [#​37300](https://togithub.com/spring-projects/spring-boot/issues/37300) - Upgrade to Lombok 1.18.30 [#​37488](https://togithub.com/spring-projects/spring-boot/issues/37488) - Upgrade to Micrometer 1.11.4 [#​37261](https://togithub.com/spring-projects/spring-boot/issues/37261) - Upgrade to Micrometer Tracing 1.1.5 [#​37262](https://togithub.com/spring-projects/spring-boot/issues/37262) - Upgrade to Native Build Tools Plugin 0.9.27 [#​37420](https://togithub.com/spring-projects/spring-boot/issues/37420) - Upgrade to Neo4j Java Driver 5.12.0 [#​37353](https://togithub.com/spring-projects/spring-boot/issues/37353) - Upgrade to Pooled JMS 3.1.3 [#​37421](https://togithub.com/spring-projects/spring-boot/issues/37421) - Upgrade to R2DBC MySQL 1.0.3 [#​37466](https://togithub.com/spring-projects/spring-boot/issues/37466) - Upgrade to Reactor Bom 2022.0.11 [#​37263](https://togithub.com/spring-projects/spring-boot/issues/37263) - Upgrade to REST Assured 5.3.2 [#​37303](https://togithub.com/spring-projects/spring-boot/issues/37303) - Upgrade to SLF4J 2.0.9 [#​37304](https://togithub.com/spring-projects/spring-boot/issues/37304) - Upgrade to Spring AMQP 3.0.9 [#​37264](https://togithub.com/spring-projects/spring-boot/issues/37264) - Upgrade to Spring Data Bom 2023.0.4 [#​37350](https://togithub.com/spring-projects/spring-boot/issues/37350) - Upgrade to Spring Framework 6.0.12 [#​37265](https://togithub.com/spring-projects/spring-boot/issues/37265) - Upgrade to Spring GraphQL 1.2.3 [#​37266](https://togithub.com/spring-projects/spring-boot/issues/37266) - Upgrade to Spring Integration 6.1.3 [#​37267](https://togithub.com/spring-projects/spring-boot/issues/37267) - Upgrade to Spring Kafka 3.0.11 [#​37305](https://togithub.com/spring-projects/spring-boot/issues/37305) - Upgrade to Spring Retry 2.0.3 [#​37280](https://togithub.com/spring-projects/spring-boot/issues/37280) - Upgrade to Spring Security 6.1.4 [#​37424](https://togithub.com/spring-projects/spring-boot/issues/37424) - Upgrade to Spring WS 4.0.6 [#​37425](https://togithub.com/spring-projects/spring-boot/issues/37425) - Upgrade to Tomcat 10.1.13 [#​37306](https://togithub.com/spring-projects/spring-boot/issues/37306) ##### :heart: Contributors Thank you to all the contributors who worked on this release: [@​Eng-Fouad](https://togithub.com/Eng-Fouad), [@​dependabot](https://togithub.com/dependabot)\[bot], [@​izeye](https://togithub.com/izeye), [@​markxnelson](https://togithub.com/markxnelson), [@​mdeinum](https://togithub.com/mdeinum), and [@​quaff](https://togithub.com/quaff)
--- ### 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/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index 2d9de56fb..e522b1756 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.1.3 + 3.1.4 From 8db200cdae34c5b7e85fbf9ddf989bf4b39f9e90 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 16:08:14 +0200 Subject: [PATCH 109/173] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.13.2 (#1365) 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.12.1` -> `2.13.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.13.2?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.13.2?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.12.1/2.13.2?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.12.1/2.13.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [com.google.cloud:google-cloud-spanner-jdbc](https://togithub.com/googleapis/java-spanner-jdbc) | `2.13.1` -> `2.13.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.13.2?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.13.2?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.13.1/2.13.2?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.13.1/2.13.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.13.2`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2132-2023-09-26) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.13.1...v2.13.2) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.16.0 ([#​1358](https://togithub.com/googleapis/java-spanner-jdbc/issues/1358)) ([c4c4925](https://togithub.com/googleapis/java-spanner-jdbc/commit/c4c492576d3e6c192a1855e8d6b3474bb2ad0c22)) - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.16.1 ([#​1363](https://togithub.com/googleapis/java-spanner-jdbc/issues/1363)) ([d574dbb](https://togithub.com/googleapis/java-spanner-jdbc/commit/d574dbb761fa7d0a7d1977844b48b8e4904f1bb0)) - Update dependency com.spotify.fmt:fmt-maven-plugin to v2.21.1 ([#​1359](https://togithub.com/googleapis/java-spanner-jdbc/issues/1359)) ([70af99e](https://togithub.com/googleapis/java-spanner-jdbc/commit/70af99e96451fb0158abb45580eaae09ad0b6210)) ### [`v2.13.1`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2131-2023-09-21) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.13.0...v2.13.1) ##### Dependencies - Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.1.4 ([#​1353](https://togithub.com/googleapis/java-spanner-jdbc/issues/1353)) ([88cd905](https://togithub.com/googleapis/java-spanner-jdbc/commit/88cd905bece9c8da7f26b637392e35ab2536edeb)) ### [`v2.13.0`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2130-2023-09-15) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.12.1...v2.13.0) ##### Features - Support partitioned queries ([#​1300](https://togithub.com/googleapis/java-spanner-jdbc/issues/1300)) ([c50da41](https://togithub.com/googleapis/java-spanner-jdbc/commit/c50da41e688ff48f8967c0f114f5bac8eaac49f9)) ##### Bug Fixes - Comments should be sent to Spanner for PostgreSQL databases ([#​1331](https://togithub.com/googleapis/java-spanner-jdbc/issues/1331)) ([7c9e781](https://togithub.com/googleapis/java-spanner-jdbc/commit/7c9e781bf45b112266e278e1df1586e56043698e)) ##### Documentation - Create Spring Data JDBC sample ([#​1334](https://togithub.com/googleapis/java-spanner-jdbc/issues/1334)) ([cefea55](https://togithub.com/googleapis/java-spanner-jdbc/commit/cefea55086eb191f71a1a493e046cb136f9f9f87)) ##### Dependencies - Update actions/checkout action to v4 - abandoned ([#​1333](https://togithub.com/googleapis/java-spanner-jdbc/issues/1333)) ([ce82b42](https://togithub.com/googleapis/java-spanner-jdbc/commit/ce82b42d3abb8de0f8b3ee2915c2008673775ea1)) - Update dependency org.springframework.data:spring-data-bom to v2023.0.4 ([#​1347](https://togithub.com/googleapis/java-spanner-jdbc/issues/1347)) ([893f61a](https://togithub.com/googleapis/java-spanner-jdbc/commit/893f61ab04e32c690f1ff9fc813bd2ba6ebca328))
--- ### 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 these updates 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 +- samples/spring-data-jdbc/pom.xml | 2 +- samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index ed2d67e79..015e8b35d 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.13.1 + 2.13.2 diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 557270816..44d3da890 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -48,7 +48,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.1 + 2.13.2 org.postgresql diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index e522b1756..d97a09d24 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -58,7 +58,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.12.1 + 2.13.2 org.postgresql From 916ad4a9e07b3afc15e53664f175db9e58f06376 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 16:12:13 +0200 Subject: [PATCH 110/173] deps: update dependency org.springframework.data:spring-data-bom to v2023.0.4 (#1367) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.data:spring-data-bom](https://togithub.com/spring-projects/spring-data-bom) | `2023.0.3` -> `2023.0.4` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.data:spring-data-bom/2023.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.data:spring-data-bom/2023.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.data:spring-data-bom/2023.0.3/2023.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.data:spring-data-bom/2023.0.3/2023.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
spring-projects/spring-data-bom (org.springframework.data:spring-data-bom) ### [`v2023.0.4`](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.0.4) [Compare Source](https://togithub.com/spring-projects/spring-data-bom/compare/2023.0.3...2023.0.4) #### :shipit: Participating Modules - [Spring Data BOM 2023.0.4](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.0.4) - [Spring Data Build 3.1.4](https://togithub.com/spring-projects/spring-data-build/releases/tag/3.1.4) - [Spring Data Cassandra 4.1.4](https://togithub.com/spring-projects/spring-data-cassandra/releases/tag/4.1.4) - [Spring Data Commons 3.1.4](https://togithub.com/spring-projects/spring-data-commons/releases/tag/3.1.4) - [Spring Data Couchbase 5.1.4](https://togithub.com/spring-projects/spring-data-couchbase/releases/tag/5.1.4) - [Spring Data Elasticsearch 5.1.4](https://togithub.com/spring-projects/spring-data-elasticsearch/releases/tag/5.1.4) - [Spring Data JPA 3.1.4](https://togithub.com/spring-projects/spring-data-jpa/releases/tag/3.1.4) - [Spring Data KeyValue 3.1.4](https://togithub.com/spring-projects/spring-data-keyvalue/releases/tag/3.1.4) - [Spring Data LDAP 3.1.4](https://togithub.com/spring-projects/spring-data-ldap/releases/tag/3.1.4) - [Spring Data MongoDB 4.1.4](https://togithub.com/spring-projects/spring-data-mongodb/releases/tag/4.1.4) - [Spring Data Neo4j 7.1.4](https://togithub.com/spring-projects/spring-data-neo4j/releases/tag/7.1.4) - [Spring Data REST 4.1.4](https://togithub.com/spring-projects/spring-data-rest/releases/tag/4.1.4) - [Spring Data Redis 3.1.4](https://togithub.com/spring-projects/spring-data-redis/releases/tag/3.1.4) - [Spring Data Relational 3.1.4](https://togithub.com/spring-projects/spring-data-relational/releases/tag/3.1.4)
--- ### 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/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index d97a09d24..68026c1a2 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2023.0.3 + 2023.0.4 import pom From d59c8f553be17136e91dcd133bee310cff9fcf94 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 17:02:06 +0200 Subject: [PATCH 111/173] chore(deps): update dependency com.google.cloud:libraries-bom to v26.23.0 (#1369) --- samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index 68026c1a2..a350dc1dd 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.22.0 + 26.23.0 import pom From 376e1c3ccdd71351a5d6151ce19b9f88df163776 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 17:02:29 +0200 Subject: [PATCH 112/173] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.48.0 (#1370) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ee49db7d9..ba8863857 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.47.0 + 6.48.0 pom import From bf64add3e9ce8148d2fc3ad010b8abd446208e4f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 17:28:16 +0200 Subject: [PATCH 113/173] deps: update dependency com.spotify.fmt:fmt-maven-plugin to v2.21.1 (#1372) 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.spotify.fmt:fmt-maven-plugin](https://togithub.com/spotify/fmt-maven-plugin) | `2.20` -> `2.21.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.spotify.fmt:fmt-maven-plugin/2.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.spotify.fmt:fmt-maven-plugin/2.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.spotify.fmt:fmt-maven-plugin/2.20/2.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.spotify.fmt:fmt-maven-plugin/2.20/2.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
spotify/fmt-maven-plugin (com.spotify.fmt:fmt-maven-plugin) ### [`v2.21.1`](https://togithub.com/spotify/fmt-maven-plugin/releases/tag/2.21.1) [Compare Source](https://togithub.com/spotify/fmt-maven-plugin/compare/2.21...2.21.1) #### What's Changed - Upgrade dependencies by [@​caesar-ralf](https://togithub.com/caesar-ralf) in [https://togithub.com/spotify/fmt-maven-plugin/pull/180](https://togithub.com/spotify/fmt-maven-plugin/pull/180) **Full Changelog**: https://togithub.com/spotify/fmt-maven-plugin/compare/2.21...2.21.1 ### [`v2.21`](https://togithub.com/spotify/fmt-maven-plugin/releases/tag/2.21) #### What's Changed - Use 2.19 for formatting code in this repo by [@​klaraward](https://togithub.com/klaraward) in [https://togithub.com/spotify/fmt-maven-plugin/pull/154](https://togithub.com/spotify/fmt-maven-plugin/pull/154) - Add metadata for Spotify OSS by [@​klaraward](https://togithub.com/klaraward) in [https://togithub.com/spotify/fmt-maven-plugin/pull/155](https://togithub.com/spotify/fmt-maven-plugin/pull/155) - check release in Central instead of search by [@​hboutemy](https://togithub.com/hboutemy) in [https://togithub.com/spotify/fmt-maven-plugin/pull/156](https://togithub.com/spotify/fmt-maven-plugin/pull/156) - configure for Reproducible Builds by [@​hboutemy](https://togithub.com/hboutemy) in [https://togithub.com/spotify/fmt-maven-plugin/pull/157](https://togithub.com/spotify/fmt-maven-plugin/pull/157) - Allow skipping of sourceDirectory or testSourceDirectory by [@​camac](https://togithub.com/camac) in [https://togithub.com/spotify/fmt-maven-plugin/pull/128](https://togithub.com/spotify/fmt-maven-plugin/pull/128) - \[Snyk] Upgrade org.apache.maven.plugin-tools:maven-plugin-annotations from 3.4 to 3.7.1 by [@​snyk-bot](https://togithub.com/snyk-bot) in [https://togithub.com/spotify/fmt-maven-plugin/pull/162](https://togithub.com/spotify/fmt-maven-plugin/pull/162) - \[Snyk] Upgrade io.norberg:auto-matter from 0.25.1 to 0.26.1 by [@​snyk-bot](https://togithub.com/snyk-bot) in [https://togithub.com/spotify/fmt-maven-plugin/pull/163](https://togithub.com/spotify/fmt-maven-plugin/pull/163) - \[Snyk] Upgrade org.apache.maven:maven-plugin-api from 3.8.4 to 3.8.7 by [@​snyk-bot](https://togithub.com/snyk-bot) in [https://togithub.com/spotify/fmt-maven-plugin/pull/164](https://togithub.com/spotify/fmt-maven-plugin/pull/164) - \[Snyk] Upgrade org.apache.maven.plugin-tools:maven-plugin-annotations from 3.7.1 to 3.8.1 by [@​perploug](https://togithub.com/perploug) in [https://togithub.com/spotify/fmt-maven-plugin/pull/169](https://togithub.com/spotify/fmt-maven-plugin/pull/169) - \[Snyk] Upgrade io.norberg:auto-matter from 0.26.1 to 0.26.2 by [@​perploug](https://togithub.com/perploug) in [https://togithub.com/spotify/fmt-maven-plugin/pull/173](https://togithub.com/spotify/fmt-maven-plugin/pull/173) - \[Snyk] Upgrade org.apache.maven.plugin-tools:maven-plugin-annotations from 3.8.1 to 3.8.2 by [@​snyk-bot](https://togithub.com/snyk-bot) in [https://togithub.com/spotify/fmt-maven-plugin/pull/174](https://togithub.com/spotify/fmt-maven-plugin/pull/174) - Bump org.apache.maven:maven-core from 3.3.9 to 3.8.1 by [@​dependabot](https://togithub.com/dependabot) in [https://togithub.com/spotify/fmt-maven-plugin/pull/177](https://togithub.com/spotify/fmt-maven-plugin/pull/177) - \[Snyk] Upgrade org.apache.maven:maven-plugin-api from 3.8.7 to 3.9.0 by [@​snyk-bot](https://togithub.com/snyk-bot) in [https://togithub.com/spotify/fmt-maven-plugin/pull/167](https://togithub.com/spotify/fmt-maven-plugin/pull/167) - Support java 21 by [@​caesar-ralf](https://togithub.com/caesar-ralf) in [https://togithub.com/spotify/fmt-maven-plugin/pull/179](https://togithub.com/spotify/fmt-maven-plugin/pull/179) #### New Contributors - [@​hboutemy](https://togithub.com/hboutemy) made their first contribution in [https://togithub.com/spotify/fmt-maven-plugin/pull/156](https://togithub.com/spotify/fmt-maven-plugin/pull/156) - [@​caesar-ralf](https://togithub.com/caesar-ralf) made their first contribution in [https://togithub.com/spotify/fmt-maven-plugin/pull/179](https://togithub.com/spotify/fmt-maven-plugin/pull/179) **Full Changelog**: https://togithub.com/spotify/fmt-maven-plugin/compare/2.19.0...2.21
--- ### 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/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index a350dc1dd..615d6ca27 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -98,7 +98,7 @@ com.spotify.fmt fmt-maven-plugin - 2.20 + 2.21.1 From b30e391792f2c2811038b35a065b35104bc614e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 27 Sep 2023 10:48:13 +0200 Subject: [PATCH 114/173] deps: remove specific JDBC version from samples (#1371) - Removes the specific JDBC version from the samples. This is no longer needed, as the BOM now contains a JDBC driver version that is up-to-date enough to work with these samples (they require RETURN_GENERATED_KEYS). - Adds a GitHub Actions workflow for testing the MyBatis sample. --- .../workflows/spring-data-mybatis-sample.yaml | 30 +++++++++++++++++++ samples/spring-data-jdbc/pom.xml | 1 - samples/spring-data-mybatis/pom.xml | 1 - 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/spring-data-mybatis-sample.yaml diff --git a/.github/workflows/spring-data-mybatis-sample.yaml b/.github/workflows/spring-data-mybatis-sample.yaml new file mode 100644 index 000000000..39be0e6e6 --- /dev/null +++ b/.github/workflows/spring-data-mybatis-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-mybatis-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-mybatis diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 44d3da890..20f858d95 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -48,7 +48,6 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.2 org.postgresql diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index 615d6ca27..07563c648 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -58,7 +58,6 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.2 org.postgresql From 4372838caf5a1c9c8b173e32d373b4d8a25699a1 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 13:16:14 +0000 Subject: [PATCH 115/173] chore(main): release 2.13.3 (#1368) :robot: I have created a release *beep* *boop* --- ## [2.13.3](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.13.2...v2.13.3) (2023-09-27) ### Dependencies * Remove specific JDBC version from samples ([#1371](https://togithub.com/googleapis/java-spanner-jdbc/issues/1371)) ([b30e391](https://togithub.com/googleapis/java-spanner-jdbc/commit/b30e391792f2c2811038b35a065b35104bc614e7)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.48.0 ([#1370](https://togithub.com/googleapis/java-spanner-jdbc/issues/1370)) ([376e1c3](https://togithub.com/googleapis/java-spanner-jdbc/commit/376e1c3ccdd71351a5d6151ce19b9f88df163776)) * Update dependency com.spotify.fmt:fmt-maven-plugin to v2.21.1 ([#1372](https://togithub.com/googleapis/java-spanner-jdbc/issues/1372)) ([bf64add](https://togithub.com/googleapis/java-spanner-jdbc/commit/bf64add3e9ce8148d2fc3ad010b8abd446208e4f)) * Update dependency org.springframework.boot:spring-boot-starter-parent to v3.1.4 ([#1366](https://togithub.com/googleapis/java-spanner-jdbc/issues/1366)) ([749d2c3](https://togithub.com/googleapis/java-spanner-jdbc/commit/749d2c3698c900560b6f85247b0a41a85cd55ac8)) * Update dependency org.springframework.data:spring-data-bom to v2023.0.4 ([#1367](https://togithub.com/googleapis/java-spanner-jdbc/issues/1367)) ([916ad4a](https://togithub.com/googleapis/java-spanner-jdbc/commit/916ad4a9e07b3afc15e53664f175db9e58f06376)) ### Documentation * Add sample for Spring Data MyBatis ([#1352](https://togithub.com/googleapis/java-spanner-jdbc/issues/1352)) ([ce52d07](https://togithub.com/googleapis/java-spanner-jdbc/commit/ce52d07c308bcde0ed1b0c9f4d3556db2590f722)) --- 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 | 16 ++++++++++++++++ pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- versions.txt | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 659f4d353..a6db5acc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [2.13.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.13.2...v2.13.3) (2023-09-27) + + +### Dependencies + +* Remove specific JDBC version from samples ([#1371](https://github.com/googleapis/java-spanner-jdbc/issues/1371)) ([b30e391](https://github.com/googleapis/java-spanner-jdbc/commit/b30e391792f2c2811038b35a065b35104bc614e7)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.48.0 ([#1370](https://github.com/googleapis/java-spanner-jdbc/issues/1370)) ([376e1c3](https://github.com/googleapis/java-spanner-jdbc/commit/376e1c3ccdd71351a5d6151ce19b9f88df163776)) +* Update dependency com.spotify.fmt:fmt-maven-plugin to v2.21.1 ([#1372](https://github.com/googleapis/java-spanner-jdbc/issues/1372)) ([bf64add](https://github.com/googleapis/java-spanner-jdbc/commit/bf64add3e9ce8148d2fc3ad010b8abd446208e4f)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.1.4 ([#1366](https://github.com/googleapis/java-spanner-jdbc/issues/1366)) ([749d2c3](https://github.com/googleapis/java-spanner-jdbc/commit/749d2c3698c900560b6f85247b0a41a85cd55ac8)) +* Update dependency org.springframework.data:spring-data-bom to v2023.0.4 ([#1367](https://github.com/googleapis/java-spanner-jdbc/issues/1367)) ([916ad4a](https://github.com/googleapis/java-spanner-jdbc/commit/916ad4a9e07b3afc15e53664f175db9e58f06376)) + + +### Documentation + +* Add sample for Spring Data MyBatis ([#1352](https://github.com/googleapis/java-spanner-jdbc/issues/1352)) ([ce52d07](https://github.com/googleapis/java-spanner-jdbc/commit/ce52d07c308bcde0ed1b0c9f4d3556db2590f722)) + ## [2.13.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.13.1...v2.13.2) (2023-09-26) diff --git a/pom.xml b/pom.xml index ba8863857..ab808ec92 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.13.3-SNAPSHOT + 2.13.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 ec9a8dd95..83ae791af 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.3-SNAPSHOT + 2.13.3 diff --git a/versions.txt b/versions.txt index 094a46df1..60ce25154 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.13.2:2.13.3-SNAPSHOT +google-cloud-spanner-jdbc:2.13.3:2.13.3 From cb2ffb219e3bfa8c716dddad585d3bf9f28e3ff8 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 14:42:16 +0000 Subject: [PATCH 116/173] chore(main): release 2.13.4-SNAPSHOT (#1373) :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 ab808ec92..14bae4c9f 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.13.3 + 2.13.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 83ae791af..8da9c02e4 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.3 + 2.13.4-SNAPSHOT diff --git a/versions.txt b/versions.txt index 60ce25154..2b54a5197 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.13.3:2.13.3 +google-cloud-spanner-jdbc:2.13.3:2.13.4-SNAPSHOT From 52d5ebc481f1598d2c2aebf9a55147dba8aba928 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 11:01:39 -0400 Subject: [PATCH 117/173] build(deps): bump cryptography from 41.0.2 to 41.0.4 in /.kokoro (#1355) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build(deps): bump cryptography from 41.0.2 to 41.0.4 in /.kokoro Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.2 to 41.0.4. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/41.0.2...41.0.4) --- 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 cc28b44595d9a3cb112a35081fda98200d529ebf Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 28 Sep 2023 22:04:25 +0200 Subject: [PATCH 118/173] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.49.0 (#1376) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 14bae4c9f..ff8b7cbcf 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.48.0 + 6.49.0 pom import From 25ccb13b786cf3ac610935b6afd5b0fba0f64d59 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:28:17 +0000 Subject: [PATCH 119/173] chore(main): release 2.13.4 (#1377) :robot: I have created a release *beep* *boop* --- ## [2.13.4](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.13.3...v2.13.4) (2023-09-28) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.49.0 ([#1376](https://togithub.com/googleapis/java-spanner-jdbc/issues/1376)) ([cc28b44](https://togithub.com/googleapis/java-spanner-jdbc/commit/cc28b44595d9a3cb112a35081fda98200d529ebf)) --- 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 a6db5acc0..65d0eaf13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.13.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.13.3...v2.13.4) (2023-09-28) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.49.0 ([#1376](https://github.com/googleapis/java-spanner-jdbc/issues/1376)) ([cc28b44](https://github.com/googleapis/java-spanner-jdbc/commit/cc28b44595d9a3cb112a35081fda98200d529ebf)) + ## [2.13.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.13.2...v2.13.3) (2023-09-27) diff --git a/pom.xml b/pom.xml index ff8b7cbcf..bf6670714 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.13.4-SNAPSHOT + 2.13.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 8da9c02e4..e83d7a010 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.4-SNAPSHOT + 2.13.4 diff --git a/versions.txt b/versions.txt index 2b54a5197..f042756d0 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.13.3:2.13.4-SNAPSHOT +google-cloud-spanner-jdbc:2.13.4:2.13.4 From 4f8bac42a9d4fae7936fb1d577f18bbc4b90485e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 22:56:13 +0000 Subject: [PATCH 120/173] chore(main): release 2.13.5-SNAPSHOT (#1378) :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 bf6670714..ee537da53 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.13.4 + 2.13.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 e83d7a010..4c60212c8 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.4 + 2.13.5-SNAPSHOT diff --git a/versions.txt b/versions.txt index f042756d0..d8e1b2e19 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.13.4:2.13.4 +google-cloud-spanner-jdbc:2.13.4:2.13.5-SNAPSHOT From 49e6a0c4e663f3848cba993e45d3e22fc781400e Mon Sep 17 00:00:00 2001 From: Alice <65933803+alicejli@users.noreply.github.com> Date: Tue, 10 Oct 2023 09:49:46 -0400 Subject: [PATCH 121/173] build: do not declare javadoc plugin version (#1385) --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index ee537da53..66f8a9aa4 100644 --- a/pom.xml +++ b/pom.xml @@ -420,7 +420,6 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.0 html From 2737ecec00abd51b796e13375f2ebdfbf8e1b201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 11 Oct 2023 14:26:22 +0200 Subject: [PATCH 122/173] feat: support default schema and catalog for PostgreSQL databases (#1375) * feat: support default schema and catalog for PostgreSQL databases The JDBC driver would return the empty string as the current catalog and schema for PostgreSQL databases. This is incorrect, as the default catalog and schema for PostgreSQL is the database name and the 'public' schema. * test: add additional testing for getSchema and getCatalog * fix: column name should be TABLE_CAT * fix: emulator now supports spanner_sys --- .../cloud/spanner/jdbc/JdbcConnection.java | 50 ++++++++++++++++--- .../spanner/jdbc/JdbcDatabaseMetaData.java | 12 +++-- .../spanner/jdbc/JdbcConnectionTest.java | 38 +++++++------- .../jdbc/JdbcDatabaseMetaDataTest.java | 17 +++++-- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 22 ++++++-- .../jdbc/it/ITJdbcPgDatabaseMetaDataTest.java | 14 ++++++ 6 files changed, 114 insertions(+), 39 deletions(-) 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 6031afe93..9248dace4 100644 --- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -47,6 +47,7 @@ import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Function; +import javax.annotation.Nonnull; /** Jdbc Connection class for Google Cloud Spanner */ class JdbcConnection extends AbstractJdbcConnection { @@ -394,31 +395,66 @@ public Array createArrayOf(String typeName, Object[] elements) throws SQLExcepti @Override public void setCatalog(String catalog) throws SQLException { // This method could be changed to allow the user to change to another database. - // For now we only support setting an empty string in order to support frameworks + // For now, we only support setting the default catalog in order to support frameworks // and applications that set this when no catalog has been specified in the connection // URL. checkClosed(); - JdbcPreconditions.checkArgument("".equals(catalog), "Only catalog \"\" is supported"); + checkValidCatalog(catalog); + } + + void checkValidCatalog(String catalog) throws SQLException { + String defaultCatalog = getDefaultCatalog(); + JdbcPreconditions.checkArgument( + defaultCatalog.equals(catalog), + String.format("Only catalog %s is supported", defaultCatalog)); } @Override public String getCatalog() throws SQLException { checkClosed(); - return ""; + return getDefaultCatalog(); + } + + @Nonnull + String getDefaultCatalog() { + switch (getDialect()) { + case POSTGRESQL: + String database = getConnectionOptions().getDatabaseName(); + // It should not be possible that database is null, but it's better to be safe than sorry. + return database == null ? "" : database; + case GOOGLE_STANDARD_SQL: + default: + return ""; + } } @Override public void setSchema(String schema) throws SQLException { checkClosed(); - // Cloud Spanner does not support schemas, but does contain a pseudo 'empty string' schema that - // might be set by frameworks and applications that read the database metadata. - JdbcPreconditions.checkArgument("".equals(schema), "Only schema \"\" is supported"); + checkValidSchema(schema); + } + + void checkValidSchema(String schema) throws SQLException { + String defaultSchema = getDefaultSchema(); + JdbcPreconditions.checkArgument( + defaultSchema.equals(schema), String.format("Only schema %s is supported", defaultSchema)); } @Override public String getSchema() throws SQLException { checkClosed(); - return ""; + return getDefaultSchema(); + } + + @Nonnull + String getDefaultSchema() { + switch (getDialect()) { + case POSTGRESQL: + return "public"; + case GOOGLE_STANDARD_SQL: + default: + return ""; + } } @Override diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index b9c7cb863..446339587 100644 --- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -777,11 +777,12 @@ public ResultSet getSchemas() throws SQLException { } @Override - public ResultSet getCatalogs() { + public ResultSet getCatalogs() throws SQLException { return JdbcResultSet.of( ResultSets.forRows( Type.struct(StructField.of("TABLE_CAT", Type.string())), - Collections.singletonList(Struct.newBuilder().set("TABLE_CAT").to("").build()))); + Collections.singletonList( + Struct.newBuilder().set("TABLE_CAT").to(getConnection().getCatalog()).build()))); } @Override @@ -1524,9 +1525,10 @@ public RowIdLifetime getRowIdLifetime() { @Override public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { String sql = readSqlFromFile("DatabaseMetaData_GetSchemas.sql", connection.getDialect()); - JdbcPreparedStatement statement = - prepareStatementReplaceNullWithAnyString(sql, catalog, schemaPattern); - return statement.executeQueryWithOptions(InternalMetadataQuery.INSTANCE); + try (JdbcPreparedStatement statement = + prepareStatementReplaceNullWithAnyString(sql, catalog, schemaPattern)) { + return statement.executeQueryWithOptions(InternalMetadataQuery.INSTANCE); + } } @Override 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 592d40409..ff811f370 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.any; @@ -700,34 +701,33 @@ public void testCatalog() throws SQLException { ConnectionOptions options = mockOptions(); when(options.getDatabaseName()).thenReturn("test"); try (JdbcConnection connection = createConnection(options)) { - // The connection should always return the empty string as the current catalog, as no other + // The connection should always return the default catalog as the current catalog, as no other // catalogs exist in the INFORMATION_SCHEMA. - assertThat(connection.getCatalog()).isEqualTo(""); + // The default catalog is the empty string for GoogleSQL databases. + // The default catalog is the database name for PostgreSQL databases. + assertEquals(connection.getDefaultCatalog(), connection.getCatalog()); // This should be allowed. - connection.setCatalog(""); - try { - // This should cause an exception. - connection.setCatalog("other"); - fail("missing expected exception"); - } catch (JdbcSqlExceptionImpl e) { - assertThat(e.getCode()).isEqualTo(Code.INVALID_ARGUMENT); - } + connection.setCatalog(connection.getDefaultCatalog()); + // This should cause an exception. + JdbcSqlExceptionImpl exception = + assertThrows(JdbcSqlExceptionImpl.class, () -> connection.setCatalog("other")); + assertEquals(Code.INVALID_ARGUMENT, exception.getCode()); } } @Test public void testSchema() throws SQLException { try (JdbcConnection connection = createConnection(mockOptions())) { - assertThat(connection.getSchema()).isEqualTo(""); + // The connection should always return the default schema as the current schema, as we + // currently do not support setting the connection to a different schema. + // The default schema is the empty string for GoogleSQL databases. + // The default schema is 'public' for PostgreSQL databases. + assertEquals(connection.getDefaultSchema(), connection.getSchema()); // This should be allowed. - connection.setSchema(""); - try { - // This should cause an exception. - connection.setSchema("other"); - fail("missing expected exception"); - } catch (JdbcSqlExceptionImpl e) { - assertThat(e.getCode()).isEqualTo(Code.INVALID_ARGUMENT); - } + connection.setSchema(connection.getDefaultSchema()); + JdbcSqlExceptionImpl exception = + assertThrows(JdbcSqlExceptionImpl.class, () -> connection.setSchema("other")); + assertEquals(Code.INVALID_ARGUMENT, exception.getCode()); } } diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 6a2b0cac0..9782e964a 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -41,10 +41,19 @@ import java.util.Objects; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class JdbcDatabaseMetaDataTest { + @Parameter public Dialect dialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + private static final String DEFAULT_CATALOG = ""; private static final String DEFAULT_SCHEMA = ""; private static final String TEST_TABLE = "FOO"; @@ -314,10 +323,12 @@ public void testGetBestRowIdentifier() throws SQLException { @Test public void testGetCatalogs() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); + when(connection.getDialect()).thenReturn(dialect); + when(connection.getCatalog()).thenCallRealMethod(); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getCatalogs()) { assertThat(rs.next(), is(true)); - assertThat(rs.getString("TABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("TABLE_CAT"), is(equalTo(connection.getDefaultCatalog()))); assertThat(rs.next(), is(false)); ResultSetMetaData rsmd = rs.getMetaData(); assertThat(rsmd.getColumnCount(), is(equalTo(1))); diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 7e2481a23..820bdfac9 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -822,6 +822,7 @@ public void testGetViews() throws SQLException { @Test public void testGetSchemas() throws SQLException { try (Connection connection = createConnection(env, database)) { + assertEquals("", connection.getSchema()); try (ResultSet rs = connection.getMetaData().getSchemas()) { assertThat(rs.next(), is(true)); assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); @@ -829,11 +830,22 @@ public void testGetSchemas() throws SQLException { assertThat(rs.next(), is(true)); assertThat(rs.getString("TABLE_SCHEM"), is(equalTo("INFORMATION_SCHEMA"))); assertThat(rs.getString("TABLE_CATALOG"), is(equalTo(DEFAULT_CATALOG))); - if (!EmulatorSpannerHelper.isUsingEmulator()) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TABLE_SCHEM"), is(equalTo("SPANNER_SYS"))); - assertThat(rs.getString("TABLE_CATALOG"), is(equalTo(DEFAULT_CATALOG))); - } + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TABLE_SCHEM"), is(equalTo("SPANNER_SYS"))); + assertThat(rs.getString("TABLE_CATALOG"), is(equalTo(DEFAULT_CATALOG))); + assertFalse(rs.next()); + } + } + } + + @Test + public void testGetCatalogs() throws SQLException { + try (Connection connection = createConnection(env, database)) { + assertEquals("", connection.getCatalog()); + try (ResultSet rs = connection.getMetaData().getCatalogs()) { + assertTrue(rs.next()); + assertEquals("", rs.getString("TABLE_CAT")); + assertFalse(rs.next()); } } diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java index ff0bff7a9..56d75db1a 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java @@ -752,6 +752,7 @@ public void testGetViews() throws SQLException { @Test public void testGetSchemas() throws SQLException { try (Connection connection = createConnection(env, database)) { + assertEquals("public", connection.getSchema()); try (ResultSet rs = connection.getMetaData().getSchemas()) { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); @@ -774,6 +775,19 @@ public void testGetSchemas() throws SQLException { } } + @Test + public void testGetCatalogs() throws SQLException { + try (Connection connection = createConnection(env, database)) { + assertEquals(database.getId().getDatabase(), connection.getCatalog()); + try (ResultSet rs = connection.getMetaData().getCatalogs()) { + assertTrue(rs.next()); + assertEquals(database.getId().getDatabase(), rs.getString("TABLE_CAT")); + + assertFalse(rs.next()); + } + } + } + private static final class Table { private final String name; private final String type; From 7452479da4140dcc0829ca83ce64c790feadad2e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 11 Oct 2023 14:27:23 +0200 Subject: [PATCH 123/173] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.13.4 (#1374) --- 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 015e8b35d..1bc1db91e 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.13.2 + 2.13.4 From 5fae1e668b36922a3101a42cb2ebc297bb92e1ee Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 11 Oct 2023 14:27:53 +0200 Subject: [PATCH 124/173] chore(deps): update dependency com.google.cloud:libraries-bom to v26.24.0 (#1379) --- samples/snippets/pom.xml | 2 +- samples/spring-data-jdbc/pom.xml | 2 +- samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index a00b7a567..31441498d 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.23.0 + 26.24.0 pom import diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 20f858d95..5ed1d02df 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.23.0 + 26.24.0 import pom diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index 07563c648..8dbf02520 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.23.0 + 26.24.0 import pom From 29fc5f4aec38ad670dd08771272dbb6301c38a4a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 11 Oct 2023 14:28:34 +0200 Subject: [PATCH 125/173] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.5.8 (#1382) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 66f8a9aa4..07e029eed 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.5.7 + 1.5.8 From 9f805a5c47c62472fd44195f132d042d364a5049 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 11 Oct 2023 14:28:56 +0200 Subject: [PATCH 126/173] chore: bump urllib3 from 1.26.16 to 1.26.17 in /synthtool/gcp/templates/java_library/.kokoro (#1875) (#1381) chore: bump urllib3 in /synthtool/gcp/templates/java_library/.kokoro Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.16 to 1.26.17. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.26.16...1.26.17) --- updated-dependencies: - dependency-name: urllib3 dependency-type: indirect ... Source-Link: https://github.com/googleapis/synthtool/commit/dbb940f3b99eca99265fda43dd4526a548b63a54 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:6e2fc7eba84c3100cde964ebcfd0e553d4664ec4a74989c978a143812785ff23 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 | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 52eaa54d8..11fe20466 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:88ba8dcc5c2c7792e1c3511381f4ab329002a1c42c512f66ca87ced572dfbf9f -# created: 2023-09-05T18:54:42.225408832Z + digest: sha256:6e2fc7eba84c3100cde964ebcfd0e553d4664ec4a74989c978a143812785ff23 +# created: 2023-10-03T23:18:35.620358763Z diff --git a/.kokoro/requirements.txt b/.kokoro/requirements.txt index a73256ab8..59de49234 100644 --- a/.kokoro/requirements.txt +++ b/.kokoro/requirements.txt @@ -418,6 +418,7 @@ protobuf==3.20.3 \ # gcp-docuploader # gcp-releasetool # google-api-core + # googleapis-common-protos pyasn1==0.5.0 \ --hash=sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57 \ --hash=sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde @@ -469,9 +470,9 @@ typing-extensions==4.7.1 \ --hash=sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36 \ --hash=sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2 # via -r requirements.in -urllib3==1.26.16 \ - --hash=sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f \ - --hash=sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14 +urllib3==1.26.17 \ + --hash=sha256:24d6a242c28d29af46c3fae832c36db3bbebcc533dd1bb549172cd739c82df21 \ + --hash=sha256:94a757d178c9be92ef5539b8840d48dc9cf1b2709c9d6b588232a055c524458b # via # google-auth # requests @@ -485,5 +486,6 @@ 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. Consider using the --allow-unsafe flag. +# 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 8401ef868493a83d2c8b8d68a33a118d2b94f769 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 11 Oct 2023 15:54:13 +0200 Subject: [PATCH 127/173] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.50.0 (#1386) 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.49.0` -> `6.50.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.50.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.50.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.49.0/6.50.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.49.0/6.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.50.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6500-2023-10-09) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.49.0...v6.50.0) ##### Features - Support setting core pool size for async API in system property ([#​2632](https://togithub.com/googleapis/java-spanner/issues/2632)) ([e51c55d](https://togithub.com/googleapis/java-spanner/commit/e51c55d332bacb9d174a24b0d842b2cba4762db8)), closes [#​2631](https://togithub.com/googleapis/java-spanner/issues/2631) ##### Dependencies - Update dependency com.google.cloud:google-cloud-trace to v2.24.0 ([#​2577](https://togithub.com/googleapis/java-spanner/issues/2577)) ([311c2ad](https://togithub.com/googleapis/java-spanner/commit/311c2ad97311490893f3abf4da5fe4d511c445dd))
--- ### 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 07e029eed..5f8907216 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.49.0 + 6.50.0 pom import From f0209a7be923465a30effc30ac23294299e0cd72 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 11 Oct 2023 15:56:13 +0200 Subject: [PATCH 128/173] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.17.0 (#1383) 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.16.1` -> `3.17.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-shared-dependencies/3.17.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.17.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.16.1/3.17.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.16.1/3.17.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 5f8907216..3a2a8240b 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.16.1 + 3.17.0 pom import From 8ae3919e352dbe02a03a41cfbc440619d299454c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 12 Oct 2023 09:55:27 +0200 Subject: [PATCH 129/173] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.50.1 (#1388) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3a2a8240b..82fa683e9 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.50.0 + 6.50.1 pom import From 1467f3a00603a4b80e9f1f0784b0aeea944e3862 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 06:56:13 +0000 Subject: [PATCH 130/173] chore(main): release 2.14.0 (#1387) :robot: I have created a release *beep* *boop* --- ## [2.14.0](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.13.4...v2.14.0) (2023-10-12) ### Features * Support default schema and catalog for PostgreSQL databases ([#1375](https://togithub.com/googleapis/java-spanner-jdbc/issues/1375)) ([2737ece](https://togithub.com/googleapis/java-spanner-jdbc/commit/2737ecec00abd51b796e13375f2ebdfbf8e1b201)) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.17.0 ([#1383](https://togithub.com/googleapis/java-spanner-jdbc/issues/1383)) ([f0209a7](https://togithub.com/googleapis/java-spanner-jdbc/commit/f0209a7be923465a30effc30ac23294299e0cd72)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.50.0 ([#1386](https://togithub.com/googleapis/java-spanner-jdbc/issues/1386)) ([8401ef8](https://togithub.com/googleapis/java-spanner-jdbc/commit/8401ef868493a83d2c8b8d68a33a118d2b94f769)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.50.1 ([#1388](https://togithub.com/googleapis/java-spanner-jdbc/issues/1388)) ([8ae3919](https://togithub.com/googleapis/java-spanner-jdbc/commit/8ae3919e352dbe02a03a41cfbc440619d299454c)) --- 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 | 14 ++++++++++++++ pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- versions.txt | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65d0eaf13..2259f449d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [2.14.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.13.4...v2.14.0) (2023-10-12) + + +### Features + +* Support default schema and catalog for PostgreSQL databases ([#1375](https://github.com/googleapis/java-spanner-jdbc/issues/1375)) ([2737ece](https://github.com/googleapis/java-spanner-jdbc/commit/2737ecec00abd51b796e13375f2ebdfbf8e1b201)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.17.0 ([#1383](https://github.com/googleapis/java-spanner-jdbc/issues/1383)) ([f0209a7](https://github.com/googleapis/java-spanner-jdbc/commit/f0209a7be923465a30effc30ac23294299e0cd72)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.50.0 ([#1386](https://github.com/googleapis/java-spanner-jdbc/issues/1386)) ([8401ef8](https://github.com/googleapis/java-spanner-jdbc/commit/8401ef868493a83d2c8b8d68a33a118d2b94f769)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.50.1 ([#1388](https://github.com/googleapis/java-spanner-jdbc/issues/1388)) ([8ae3919](https://github.com/googleapis/java-spanner-jdbc/commit/8ae3919e352dbe02a03a41cfbc440619d299454c)) + ## [2.13.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.13.3...v2.13.4) (2023-09-28) diff --git a/pom.xml b/pom.xml index 82fa683e9..bff3f8dab 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.13.5-SNAPSHOT + 2.14.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 4c60212c8..eb6a609de 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.5-SNAPSHOT + 2.14.0 diff --git a/versions.txt b/versions.txt index d8e1b2e19..ecc788570 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.13.4:2.13.5-SNAPSHOT +google-cloud-spanner-jdbc:2.14.0:2.14.0 From 31a810e07da4899ee01e27fcbdaa0050d41b2c52 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 08:26:14 +0000 Subject: [PATCH 131/173] chore(main): release 2.14.1-SNAPSHOT (#1389) :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 bff3f8dab..53221acc9 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.14.0 + 2.14.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 eb6a609de..e64e91e54 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.0 + 2.14.1-SNAPSHOT diff --git a/versions.txt b/versions.txt index ecc788570..6136c9c94 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.0:2.14.0 +google-cloud-spanner-jdbc:2.14.0:2.14.1-SNAPSHOT From 89b34550ff72aa00dbeab776db98da8c0486b62c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Oct 2023 11:56:38 +0200 Subject: [PATCH 132/173] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.14.0 (#1390) 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.13.4` -> `2.14.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.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-spanner-jdbc/2.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-spanner-jdbc/2.13.4/2.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-spanner-jdbc/2.13.4/2.14.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.14.0`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2140-2023-10-12) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.13.4...v2.14.0) ##### Features - Support default schema and catalog for PostgreSQL databases ([#​1375](https://togithub.com/googleapis/java-spanner-jdbc/issues/1375)) ([2737ece](https://togithub.com/googleapis/java-spanner-jdbc/commit/2737ecec00abd51b796e13375f2ebdfbf8e1b201)) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.17.0 ([#​1383](https://togithub.com/googleapis/java-spanner-jdbc/issues/1383)) ([f0209a7](https://togithub.com/googleapis/java-spanner-jdbc/commit/f0209a7be923465a30effc30ac23294299e0cd72)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.50.0 ([#​1386](https://togithub.com/googleapis/java-spanner-jdbc/issues/1386)) ([8401ef8](https://togithub.com/googleapis/java-spanner-jdbc/commit/8401ef868493a83d2c8b8d68a33a118d2b94f769)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.50.1 ([#​1388](https://togithub.com/googleapis/java-spanner-jdbc/issues/1388)) ([8ae3919](https://togithub.com/googleapis/java-spanner-jdbc/commit/8ae3919e352dbe02a03a41cfbc440619d299454c))
--- ### 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 1bc1db91e..086be6b76 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.13.4 + 2.14.0 From 74d106f2590abc592b501093b6a30d2493e49868 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 14 Oct 2023 21:07:31 +0200 Subject: [PATCH 133/173] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.51.0 (#1393) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 53221acc9..7e2462ca9 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.50.1 + 6.51.0 pom import From f85e0ce9097dbd7b810cef2ba10fcde00c614814 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 14 Oct 2023 21:07:52 +0200 Subject: [PATCH 134/173] chore(deps): update dependency com.google.cloud:libraries-bom to v26.25.0 (#1392) --- samples/snippets/pom.xml | 2 +- samples/spring-data-jdbc/pom.xml | 2 +- samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 31441498d..c3a67a698 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.24.0 + 26.25.0 pom import diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 5ed1d02df..28d5e238e 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.24.0 + 26.25.0 import pom diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index 8dbf02520..b00e6b218 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.24.0 + 26.25.0 import pom From c5a7ee439f5d1f2242ffa2f3522b589cefb25744 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 14 Oct 2023 21:08:13 +0200 Subject: [PATCH 135/173] deps: update dependency org.springframework.data:spring-data-bom to v2023.0.5 (#1391) --- samples/spring-data-jdbc/pom.xml | 2 +- samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 28d5e238e..fc22d388e 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2023.0.4 + 2023.0.5 import pom diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index b00e6b218..7afc28b02 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2023.0.4 + 2023.0.5 import pom From 724a87ed68cf7d24b542d9e7f1a963d2ca341fa2 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 14 Oct 2023 20:20:14 +0000 Subject: [PATCH 136/173] chore(main): release 2.14.1 (#1394) :robot: I have created a release *beep* *boop* --- ## [2.14.1](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.14.0...v2.14.1) (2023-10-14) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.51.0 ([#1393](https://togithub.com/googleapis/java-spanner-jdbc/issues/1393)) ([74d106f](https://togithub.com/googleapis/java-spanner-jdbc/commit/74d106f2590abc592b501093b6a30d2493e49868)) * Update dependency org.springframework.data:spring-data-bom to v2023.0.5 ([#1391](https://togithub.com/googleapis/java-spanner-jdbc/issues/1391)) ([c5a7ee4](https://togithub.com/googleapis/java-spanner-jdbc/commit/c5a7ee439f5d1f2242ffa2f3522b589cefb25744)) --- 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 2259f449d..8296568b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [2.14.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.0...v2.14.1) (2023-10-14) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.51.0 ([#1393](https://github.com/googleapis/java-spanner-jdbc/issues/1393)) ([74d106f](https://github.com/googleapis/java-spanner-jdbc/commit/74d106f2590abc592b501093b6a30d2493e49868)) +* Update dependency org.springframework.data:spring-data-bom to v2023.0.5 ([#1391](https://github.com/googleapis/java-spanner-jdbc/issues/1391)) ([c5a7ee4](https://github.com/googleapis/java-spanner-jdbc/commit/c5a7ee439f5d1f2242ffa2f3522b589cefb25744)) + ## [2.14.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.13.4...v2.14.0) (2023-10-12) diff --git a/pom.xml b/pom.xml index 7e2462ca9..db7948f5a 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.14.1-SNAPSHOT + 2.14.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 e64e91e54..5339ef48b 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.1-SNAPSHOT + 2.14.1 diff --git a/versions.txt b/versions.txt index 6136c9c94..02b84e1b4 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.0:2.14.1-SNAPSHOT +google-cloud-spanner-jdbc:2.14.1:2.14.1 From cb047b0b216d3cf576a7e22ec488e50c07b814ff Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 14 Oct 2023 21:32:14 +0000 Subject: [PATCH 137/173] chore(main): release 2.14.2-SNAPSHOT (#1395) :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 db7948f5a..e34b75419 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.14.1 + 2.14.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 5339ef48b..64656478c 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.1 + 2.14.2-SNAPSHOT diff --git a/versions.txt b/versions.txt index 02b84e1b4..90d9204a5 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.1:2.14.1 +google-cloud-spanner-jdbc:2.14.1:2.14.2-SNAPSHOT From b09ab7218f30b64283dddbddd1fab9d81cc2122d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 16 Oct 2023 15:58:50 +0200 Subject: [PATCH 138/173] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.14.1 (#1396) --- 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 086be6b76..b001af5a9 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.14.0 + 2.14.1 From 764c9d244df16307fe3b13e647759b777bb145ab Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Oct 2023 14:03:31 +0200 Subject: [PATCH 139/173] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.18.0 (#1402) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e34b75419..30656f94f 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.17.0 + 3.18.0 pom import From ca4b183c828b1d3cc4496e98ec3b609f7f80c2a8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Oct 2023 14:04:16 +0200 Subject: [PATCH 140/173] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.1.5 (#1399) --- samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index fc22d388e..c750693c3 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -41,7 +41,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.1.4 + 3.1.5 From 9b139aa200a9ddf436b089555d25274f5ef7ee4a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Oct 2023 14:04:37 +0200 Subject: [PATCH 141/173] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.1.5 (#1400) --- samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index 7afc28b02..b908ea798 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.1.4 + 3.1.5 From cf577ee89faa84444b37a7b0b7fe931223461836 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Oct 2023 15:16:14 +0200 Subject: [PATCH 142/173] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.52.1 (#1401) 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.51.0` -> `6.52.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.52.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.52.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.51.0/6.52.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.51.0/6.52.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.52.1`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6521-2023-10-20) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.52.0...v6.52.1) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.18.0 ([#​2691](https://togithub.com/googleapis/java-spanner/issues/2691)) ([b425021](https://togithub.com/googleapis/java-spanner/commit/b4250218a500eb1540920ed0023454d06c54d621)) ### [`v6.52.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6520-2023-10-19) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.51.0...v6.52.0) ##### Features - Add support for Managed Autoscaler ([#​2624](https://togithub.com/googleapis/java-spanner/issues/2624)) ([e5e6923](https://togithub.com/googleapis/java-spanner/commit/e5e6923a351670ab237c411bb4a549533dac1b6b))
--- ### 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 30656f94f..3e9336710 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.51.0 + 6.52.1 pom import From a8c65ed0b4777f11e18f6feecdc5fdb4f703189a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Oct 2023 17:14:14 +0200 Subject: [PATCH 143/173] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.6.0 (#1397) 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-config](https://togithub.com/googleapis/java-shared-config) | `1.5.8` -> `1.6.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-shared-config/1.6.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-config/1.6.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-config/1.5.8/1.6.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-config/1.5.8/1.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-shared-config (com.google.cloud:google-cloud-shared-config) ### [`v1.6.0`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#160-2023-10-17) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.5.8...v1.6.0) ##### Features - Add graal-sdk dependency management to java-shared-config ([#​683](https://togithub.com/googleapis/java-shared-config/issues/683)) ([5cd1d84](https://togithub.com/googleapis/java-shared-config/commit/5cd1d84bf2d68dbe8f9fa7e02d9065082bd56726))
--- ### 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 3e9336710..46480b703 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.5.8 + 1.6.0 From c0bf117f687fc010f2b84d1a22de14b13e6d2800 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 17:37:14 +0200 Subject: [PATCH 144/173] chore(main): release 2.14.2 (#1404) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- CHANGELOG.md | 10 ++++++++++ pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- versions.txt | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8296568b8..b179babc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [2.14.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.1...v2.14.2) (2023-10-24) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.18.0 ([#1402](https://github.com/googleapis/java-spanner-jdbc/issues/1402)) ([764c9d2](https://github.com/googleapis/java-spanner-jdbc/commit/764c9d244df16307fe3b13e647759b777bb145ab)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.52.1 ([#1401](https://github.com/googleapis/java-spanner-jdbc/issues/1401)) ([cf577ee](https://github.com/googleapis/java-spanner-jdbc/commit/cf577ee89faa84444b37a7b0b7fe931223461836)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.1.5 ([#1399](https://github.com/googleapis/java-spanner-jdbc/issues/1399)) ([ca4b183](https://github.com/googleapis/java-spanner-jdbc/commit/ca4b183c828b1d3cc4496e98ec3b609f7f80c2a8)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.1.5 ([#1400](https://github.com/googleapis/java-spanner-jdbc/issues/1400)) ([9b139aa](https://github.com/googleapis/java-spanner-jdbc/commit/9b139aa200a9ddf436b089555d25274f5ef7ee4a)) + ## [2.14.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.0...v2.14.1) (2023-10-14) diff --git a/pom.xml b/pom.xml index 46480b703..85b3f54c4 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.14.2-SNAPSHOT + 2.14.2 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 64656478c..f910472f8 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.2-SNAPSHOT + 2.14.2 diff --git a/versions.txt b/versions.txt index 90d9204a5..8de2b27ed 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.1:2.14.2-SNAPSHOT +google-cloud-spanner-jdbc:2.14.2:2.14.2 From 61ca7fe04c82baa44c4ec3b576465f902891a593 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 16:48:14 +0000 Subject: [PATCH 145/173] chore(main): release 2.14.3-SNAPSHOT (#1405) :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 85b3f54c4..dc7331973 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.14.2 + 2.14.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index f910472f8..920c5a65a 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.2 + 2.14.3-SNAPSHOT diff --git a/versions.txt b/versions.txt index 8de2b27ed..6e526f3fd 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.2:2.14.2 +google-cloud-spanner-jdbc:2.14.2:2.14.3-SNAPSHOT From add214c3f78274af462fff6be21c32e80be47b29 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 25 Oct 2023 08:48:22 +0200 Subject: [PATCH 146/173] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.14.2 (#1406) --- 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 b001af5a9..b25a24c49 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.14.1 + 2.14.2 From 5210a6219e7e9c0f050fc9430ce1e578551191ef Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 28 Oct 2023 12:36:48 +0200 Subject: [PATCH 147/173] chore(deps): update dependency com.google.cloud:libraries-bom to v26.26.0 (#1407) --- samples/snippets/pom.xml | 2 +- samples/spring-data-jdbc/pom.xml | 2 +- samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index c3a67a698..d050f886d 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.25.0 + 26.26.0 pom import diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index c750693c3..3882c0d67 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.25.0 + 26.26.0 import pom diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index b908ea798..98e446bd7 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.25.0 + 26.26.0 import pom From 251a87413b30b0993e8a5051f1d7eaa9090dc77e Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Sat, 28 Oct 2023 12:37:09 +0200 Subject: [PATCH 148/173] chore: bump urllib3 from 2.0.6 to 2.0.7 in /docker/owlbot/java/src (#1883) (#1408) Source-Link: https://github.com/googleapis/synthtool/commit/247239027cad7678adea8f57e529ebd12600ee93 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:fb7584f6adb3847ac480ed49a4bfe1463965026b2919a1be270e3174f3ce1191 Co-authored-by: Owl Bot --- .github/.OwlBot.lock.yaml | 4 ++-- .kokoro/nightly/java11-integration.cfg | 1 + .kokoro/presubmit/integration.cfg | 1 + .kokoro/requirements.txt | 6 +++--- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 11fe20466..208af3438 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:6e2fc7eba84c3100cde964ebcfd0e553d4664ec4a74989c978a143812785ff23 -# created: 2023-10-03T23:18:35.620358763Z + digest: sha256:fb7584f6adb3847ac480ed49a4bfe1463965026b2919a1be270e3174f3ce1191 +# created: 2023-10-26T23:22:21.357007231Z diff --git a/.kokoro/nightly/java11-integration.cfg b/.kokoro/nightly/java11-integration.cfg index 58049cc38..6a6ef94ef 100644 --- a/.kokoro/nightly/java11-integration.cfg +++ b/.kokoro/nightly/java11-integration.cfg @@ -35,3 +35,4 @@ env_vars: { key: "SECRET_MANAGER_KEYS" value: "java-it-service-account" } + diff --git a/.kokoro/presubmit/integration.cfg b/.kokoro/presubmit/integration.cfg index dded67a9d..5864c603e 100644 --- a/.kokoro/presubmit/integration.cfg +++ b/.kokoro/presubmit/integration.cfg @@ -31,3 +31,4 @@ env_vars: { key: "SECRET_MANAGER_KEYS" value: "java-it-service-account" } + diff --git a/.kokoro/requirements.txt b/.kokoro/requirements.txt index 59de49234..c5c11bbe7 100644 --- a/.kokoro/requirements.txt +++ b/.kokoro/requirements.txt @@ -470,9 +470,9 @@ typing-extensions==4.7.1 \ --hash=sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36 \ --hash=sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2 # via -r requirements.in -urllib3==1.26.17 \ - --hash=sha256:24d6a242c28d29af46c3fae832c36db3bbebcc533dd1bb549172cd739c82df21 \ - --hash=sha256:94a757d178c9be92ef5539b8840d48dc9cf1b2709c9d6b588232a055c524458b +urllib3==1.26.18 \ + --hash=sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07 \ + --hash=sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0 # via # google-auth # requests From 3b47298e4f2743bad0fda08bb03861bc25bfab06 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 31 Oct 2023 16:43:53 +0100 Subject: [PATCH 149/173] chore: update graalvm version to 22.3.3 in kokoro cfg files. (#1889) (#1409) Source-Link: https://github.com/googleapis/synthtool/commit/1547f9a33de075d31d434bb3c9d7f53f068e0ff3 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:bc2bf47c7370f1b1a8a46b0c104ce7e43644ac58902c9de265fe1f253fcc2506 Co-authored-by: Owl Bot --- .github/.OwlBot.lock.yaml | 4 ++-- .kokoro/presubmit/graalvm-native-17.cfg | 2 +- .kokoro/presubmit/graalvm-native.cfg | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 208af3438..f930d4846 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:fb7584f6adb3847ac480ed49a4bfe1463965026b2919a1be270e3174f3ce1191 -# created: 2023-10-26T23:22:21.357007231Z + digest: sha256:bc2bf47c7370f1b1a8a46b0c104ce7e43644ac58902c9de265fe1f253fcc2506 +# created: 2023-10-31T13:44:21.909247346Z diff --git a/.kokoro/presubmit/graalvm-native-17.cfg b/.kokoro/presubmit/graalvm-native-17.cfg index f52533545..fb5bb678f 100644 --- a/.kokoro/presubmit/graalvm-native-17.cfg +++ b/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/graalvm17:22.3.2" + value: "gcr.io/cloud-devrel-kokoro-resources/graalvm17:22.3.3" } env_vars: { diff --git a/.kokoro/presubmit/graalvm-native.cfg b/.kokoro/presubmit/graalvm-native.cfg index 44b100487..59efee340 100644 --- a/.kokoro/presubmit/graalvm-native.cfg +++ b/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/graalvm:22.3.2" + value: "gcr.io/cloud-devrel-kokoro-resources/graalvm:22.3.3" } env_vars: { From e9d613a770a2ad045ceb140327a90370e6795880 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 1 Nov 2023 09:57:42 +0100 Subject: [PATCH 150/173] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.6.1 (#1410) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dc7331973..a7287ec53 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.6.0 + 1.6.1 From eb14ea005dbb810ee9e303971338edf0edfedb75 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 1 Nov 2023 09:58:01 +0100 Subject: [PATCH 151/173] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.19.0 (#1411) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a7287ec53..fcba765e0 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.18.0 + 3.19.0 pom import From c55eb05c0069f2a44ac52385b415b2075fbc7129 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 10:06:15 +0000 Subject: [PATCH 152/173] chore(main): release 2.14.3 (#1412) :robot: I have created a release *beep* *boop* --- ## [2.14.3](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.14.2...v2.14.3) (2023-11-01) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.19.0 ([#1411](https://togithub.com/googleapis/java-spanner-jdbc/issues/1411)) ([eb14ea0](https://togithub.com/googleapis/java-spanner-jdbc/commit/eb14ea005dbb810ee9e303971338edf0edfedb75)) --- 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 b179babc3..23d287f96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.14.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.2...v2.14.3) (2023-11-01) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.19.0 ([#1411](https://github.com/googleapis/java-spanner-jdbc/issues/1411)) ([eb14ea0](https://github.com/googleapis/java-spanner-jdbc/commit/eb14ea005dbb810ee9e303971338edf0edfedb75)) + ## [2.14.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.1...v2.14.2) (2023-10-24) diff --git a/pom.xml b/pom.xml index fcba765e0..49f7bd617 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.14.3-SNAPSHOT + 2.14.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 920c5a65a..59e0af876 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.3-SNAPSHOT + 2.14.3 diff --git a/versions.txt b/versions.txt index 6e526f3fd..90ad0651c 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.2:2.14.3-SNAPSHOT +google-cloud-spanner-jdbc:2.14.3:2.14.3 From 6dbb3993ea1a414779aad9f6805b1cef3c5d428c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 11:16:14 +0000 Subject: [PATCH 153/173] chore(main): release 2.14.4-SNAPSHOT (#1413) :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 49f7bd617..c21fd6660 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.14.3 + 2.14.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 59e0af876..c6115f1ca 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.3 + 2.14.4-SNAPSHOT diff --git a/versions.txt b/versions.txt index 90ad0651c..c07654d0d 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.3:2.14.3 +google-cloud-spanner-jdbc:2.14.3:2.14.4-SNAPSHOT From 4d5fb29b7a6d36c622470ff32f4b9453d01631f3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 5 Nov 2023 15:43:40 +0100 Subject: [PATCH 154/173] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.14.3 (#1414) --- 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 b25a24c49..5158d8c9d 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.14.2 + 2.14.3 From e6a4396c158048fed0b4391183f289f0fad66900 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 9 Nov 2023 10:09:48 +0100 Subject: [PATCH 155/173] chore(deps): update dependency com.google.cloud:libraries-bom to v26.27.0 (#1416) --- samples/snippets/pom.xml | 2 +- samples/spring-data-jdbc/pom.xml | 2 +- samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index d050f886d..8a87cff39 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.26.0 + 26.27.0 pom import diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 3882c0d67..299d4227f 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.26.0 + 26.27.0 import pom diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index 98e446bd7..72fef9dcf 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.26.0 + 26.27.0 import pom From f2b578dc38bd9328022fd1ecd627d8e1d20c2dbc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 9 Nov 2023 10:10:14 +0100 Subject: [PATCH 156/173] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.53.0 (#1415) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c21fd6660..7c4f8a7fd 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.52.1 + 6.53.0 pom import From 63f0471a5de19fc1cbf740c2ac2863684ac19bd0 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 9 Nov 2023 10:22:15 +0000 Subject: [PATCH 157/173] chore(main): release 2.14.4 (#1417) :robot: I have created a release *beep* *boop* --- ## [2.14.4](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.14.3...v2.14.4) (2023-11-09) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.53.0 ([#1415](https://togithub.com/googleapis/java-spanner-jdbc/issues/1415)) ([f2b578d](https://togithub.com/googleapis/java-spanner-jdbc/commit/f2b578dc38bd9328022fd1ecd627d8e1d20c2dbc)) --- 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 23d287f96..b10c0b0ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.14.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.3...v2.14.4) (2023-11-09) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.53.0 ([#1415](https://github.com/googleapis/java-spanner-jdbc/issues/1415)) ([f2b578d](https://github.com/googleapis/java-spanner-jdbc/commit/f2b578dc38bd9328022fd1ecd627d8e1d20c2dbc)) + ## [2.14.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.2...v2.14.3) (2023-11-01) diff --git a/pom.xml b/pom.xml index 7c4f8a7fd..cf84cdf1c 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.14.4-SNAPSHOT + 2.14.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 c6115f1ca..f60fa36cb 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.4-SNAPSHOT + 2.14.4 diff --git a/versions.txt b/versions.txt index c07654d0d..08bc71527 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.3:2.14.4-SNAPSHOT +google-cloud-spanner-jdbc:2.14.4:2.14.4 From 36a4508f06693a1a03680044665e19a1f9bce793 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 9 Nov 2023 11:30:14 +0000 Subject: [PATCH 158/173] chore(main): release 2.14.5-SNAPSHOT (#1418) :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 cf84cdf1c..8b7e513b5 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.14.4 + 2.14.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 f60fa36cb..77395be95 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.4 + 2.14.5-SNAPSHOT diff --git a/versions.txt b/versions.txt index 08bc71527..d79775c9e 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.4:2.14.4 +google-cloud-spanner-jdbc:2.14.4:2.14.5-SNAPSHOT From cc9f1d4abbf8f7fdea4fd00d841e5e2449e01504 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 27 Nov 2023 20:19:55 +0100 Subject: [PATCH 159/173] build(deps): update dependency org.codehaus.mojo:build-helper-maven-plugin to v3.5.0 (#1427) --- samples/install-without-bom/pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 5158d8c9d..1952dec56 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -53,7 +53,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.4.0 + 3.5.0 add-snippets-source diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 77395be95..9d5e19da0 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -52,7 +52,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.4.0 + 3.5.0 add-snippets-source From 7816ad5ac4e6aade67356c6b56ef6abf8f466d73 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 27 Nov 2023 20:26:14 +0100 Subject: [PATCH 160/173] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.14.4 (#1419) 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.14.3` -> `2.14.4` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.14.4?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.14.4?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.14.3/2.14.4?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.14.3/2.14.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.14.4`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2144-2023-11-09) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.14.3...v2.14.4) ##### Dependencies - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.53.0 ([#​1415](https://togithub.com/googleapis/java-spanner-jdbc/issues/1415)) ([f2b578d](https://togithub.com/googleapis/java-spanner-jdbc/commit/f2b578dc38bd9328022fd1ecd627d8e1d20c2dbc))
--- ### 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 1952dec56..f74fb2cd7 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.14.3 + 2.14.4 From 8667ee8c16841b9a526ac7f1bd025f13f9149dc7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 28 Nov 2023 21:43:53 +0100 Subject: [PATCH 161/173] deps: update dependency org.mybatis.spring.boot:mybatis-spring-boot-starter to v3.0.3 (#1426) --- samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index 72fef9dcf..6fe135cb4 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -46,7 +46,7 @@ org.mybatis.spring.boot mybatis-spring-boot-starter - 3.0.2 + 3.0.3 org.mybatis.dynamic-sql From 89adedbe1ba6a6f47cc6bdce024f109993549bb7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 28 Nov 2023 21:44:16 +0100 Subject: [PATCH 162/173] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.5.0 (#1423) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8b7e513b5..e998ad780 100644 --- a/pom.xml +++ b/pom.xml @@ -393,7 +393,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.4.5 + 3.5.0 From d107b25b2d6ad1dcf91a94118bd96d5f975be116 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 28 Nov 2023 21:45:22 +0100 Subject: [PATCH 163/173] deps: update dependency org.postgresql:postgresql to v42.7.0 (#1422) --- samples/spring-data-jdbc/pom.xml | 2 +- samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml index 299d4227f..d1dd5748b 100644 --- a/samples/spring-data-jdbc/pom.xml +++ b/samples/spring-data-jdbc/pom.xml @@ -52,7 +52,7 @@ org.postgresql postgresql - 42.6.0 + 42.7.0 diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml index 6fe135cb4..4dbd0925b 100644 --- a/samples/spring-data-mybatis/pom.xml +++ b/samples/spring-data-mybatis/pom.xml @@ -62,7 +62,7 @@ org.postgresql postgresql - 42.6.0 + 42.7.0 From d3f5361bbe03eca85c1bdba5af0a716dc923a231 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 28 Nov 2023 21:45:44 +0100 Subject: [PATCH 164/173] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.54.0 (#1420) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e998ad780..dceeeb741 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.53.0 + 6.54.0 pom import From 5da2d71c69036a8a4f4033b0bb00c39f98715fd1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 30 Nov 2023 18:23:36 +0100 Subject: [PATCH 165/173] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.20.0 (#1430) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dceeeb741..db262c30b 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.19.0 + 3.20.0 pom import From 2d08829cb28f31ef3a733cbb98114c607abd5c4b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:44:59 +0100 Subject: [PATCH 166/173] chore(main): release 2.14.5 (#1428) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- CHANGELOG.md | 10 ++++++++++ pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- versions.txt | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b10c0b0ab..117cc6e58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [2.14.5](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.4...v2.14.5) (2023-11-30) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.20.0 ([#1430](https://github.com/googleapis/java-spanner-jdbc/issues/1430)) ([5da2d71](https://github.com/googleapis/java-spanner-jdbc/commit/5da2d71c69036a8a4f4033b0bb00c39f98715fd1)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.54.0 ([#1420](https://github.com/googleapis/java-spanner-jdbc/issues/1420)) ([d3f5361](https://github.com/googleapis/java-spanner-jdbc/commit/d3f5361bbe03eca85c1bdba5af0a716dc923a231)) +* Update dependency org.mybatis.spring.boot:mybatis-spring-boot-starter to v3.0.3 ([#1426](https://github.com/googleapis/java-spanner-jdbc/issues/1426)) ([8667ee8](https://github.com/googleapis/java-spanner-jdbc/commit/8667ee8c16841b9a526ac7f1bd025f13f9149dc7)) +* Update dependency org.postgresql:postgresql to v42.7.0 ([#1422](https://github.com/googleapis/java-spanner-jdbc/issues/1422)) ([d107b25](https://github.com/googleapis/java-spanner-jdbc/commit/d107b25b2d6ad1dcf91a94118bd96d5f975be116)) + ## [2.14.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.3...v2.14.4) (2023-11-09) diff --git a/pom.xml b/pom.xml index db262c30b..8d0093c28 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.14.5-SNAPSHOT + 2.14.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 9d5e19da0..3a2bc646b 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.5-SNAPSHOT + 2.14.5 diff --git a/versions.txt b/versions.txt index d79775c9e..8993de115 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.4:2.14.5-SNAPSHOT +google-cloud-spanner-jdbc:2.14.5:2.14.5 From 94d084cacd7877cada279f211973e673e0820e2f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 1 Dec 2023 16:00:28 +0000 Subject: [PATCH 167/173] chore(main): release 2.14.6-SNAPSHOT (#1431) :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 8d0093c28..b67782f35 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.14.5 + 2.14.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 3a2bc646b..18344f2dc 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.5 + 2.14.6-SNAPSHOT diff --git a/versions.txt b/versions.txt index 8993de115..c203137bd 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.5:2.14.5 +google-cloud-spanner-jdbc:2.14.5:2.14.6-SNAPSHOT From 0e06794e3f5f5a7a1b047c19c58167218a9154a6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 1 Dec 2023 20:42:42 +0100 Subject: [PATCH 168/173] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.14.5 (#1432) --- 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 f74fb2cd7..80864ee32 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.14.4 + 2.14.5 From e976703debbc1f45840e66c5620dd68adda3d38a Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 12:31:03 +0100 Subject: [PATCH 169/173] ci: Update ci.yaml to introduce Java 21 unit testing (#1907) (#1433) Source-Link: https://github.com/googleapis/synthtool/commit/c06d605503f34e91c9d7dfee8f5287d58b5988ae Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:6f431774e11cc46619cf093fd1481193c4024031073697fa18f0099b943aab88 Co-authored-by: Owl Bot --- .github/.OwlBot.lock.yaml | 4 ++-- .github/workflows/ci.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index f930d4846..d304652e1 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:bc2bf47c7370f1b1a8a46b0c104ce7e43644ac58902c9de265fe1f253fcc2506 -# created: 2023-10-31T13:44:21.909247346Z + digest: sha256:6f431774e11cc46619cf093fd1481193c4024031073697fa18f0099b943aab88 +# created: 2023-12-01T19:50:20.444857406Z diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e27b2c575..ae66b1973 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -25,7 +25,7 @@ jobs: strategy: fail-fast: false matrix: - java: [11, 17] + java: [11, 17, 21] steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 From 4168611a973f3cd35a4cb1ce56d0eefe5e1dd571 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 4 Dec 2023 12:31:22 +0100 Subject: [PATCH 170/173] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.55.0 (#1434) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b67782f35..65860ae84 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.54.0 + 6.55.0 pom import From e54fd26ac8f88624e6f92ad3e56a4dc59382b9b8 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 18:16:14 +0100 Subject: [PATCH 171/173] chore(main): release 2.14.6 (#1435) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- 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 117cc6e58..8fdf14867 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.14.6](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.5...v2.14.6) (2023-12-04) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.55.0 ([#1434](https://github.com/googleapis/java-spanner-jdbc/issues/1434)) ([4168611](https://github.com/googleapis/java-spanner-jdbc/commit/4168611a973f3cd35a4cb1ce56d0eefe5e1dd571)) + ## [2.14.5](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.4...v2.14.5) (2023-11-30) diff --git a/pom.xml b/pom.xml index 65860ae84..fdea168b4 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.14.6-SNAPSHOT + 2.14.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 18344f2dc..3f8deae8d 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.6-SNAPSHOT + 2.14.6 diff --git a/versions.txt b/versions.txt index c203137bd..1b47ecd01 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.5:2.14.6-SNAPSHOT +google-cloud-spanner-jdbc:2.14.6:2.14.6 From 79688f1a97317e710e4462efc411e57aa0568495 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 18:26:20 +0000 Subject: [PATCH 172/173] chore(main): release 2.14.7-SNAPSHOT (#1436) :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 fdea168b4..90ac8a53d 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.14.6 + 2.14.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 3f8deae8d..ce3483e6f 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.6 + 2.14.7-SNAPSHOT diff --git a/versions.txt b/versions.txt index 1b47ecd01..6dc9f85ed 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.6:2.14.6 +google-cloud-spanner-jdbc:2.14.6:2.14.7-SNAPSHOT From 1f89f78c37b9e118e2c0cbc7f56d3eb1d5745863 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 5 Dec 2023 14:16:16 +0100 Subject: [PATCH 173/173] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.14.6 (#1437) --- 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 80864ee32..d71f8cf03 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.14.5 + 2.14.6